blob: 33c6589d0d7f4b5067612fc74533cce5f15f15ef [file] [log] [blame]
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package time_test
import (
"reflect"
"testing"
"time"
_ "time/tzdata"
)
var zones = []string{
"Asia/Jerusalem",
"America/Los_Angeles",
}
func TestEmbeddedTZData(t *testing.T) {
undo := time.DisablePlatformSources()
defer undo()
for _, zone := range zones {
ref, err := time.LoadLocation(zone)
if err != nil {
t.Errorf("LoadLocation(%q): %v", zone, err)
continue
}
embedded, err := time.LoadFromEmbeddedTZData(zone)
if err != nil {
t.Errorf("LoadFromEmbeddedTZData(%q): %v", zone, err)
continue
}
sample, err := time.LoadLocationFromTZData(zone, []byte(embedded))
if err != nil {
t.Errorf("LoadLocationFromTZData failed for %q: %v", zone, err)
continue
}
// Compare the name and zone fields of ref and sample.
// The tx field changes faster as tzdata is updated.
// The cache fields are expected to differ.
v1 := reflect.ValueOf(ref).Elem()
v2 := reflect.ValueOf(sample).Elem()
typ := v1.Type()
nf := typ.NumField()
found := 0
for i := 0; i < nf; i++ {
ft := typ.Field(i)
if ft.Name != "name" && ft.Name != "zone" {
continue
}
found++
if !equal(t, v1.Field(i), v2.Field(i)) {
t.Errorf("zone %s: system and embedded tzdata field %s differs", zone, ft.Name)
}
}
if found != 2 {
t.Errorf("test must be updated for change to time.Location struct")
}
}
}
// equal is a small version of reflect.DeepEqual that we use to
// compare the values of zoneinfo unexported fields.
func equal(t *testing.T, f1, f2 reflect.Value) bool {
switch f1.Type().Kind() {
case reflect.Slice:
if f1.Len() != f2.Len() {
return false
}
for i := 0; i < f1.Len(); i++ {
if !equal(t, f1.Index(i), f2.Index(i)) {
return false
}
}
return true
case reflect.Struct:
nf := f1.Type().NumField()
for i := 0; i < nf; i++ {
if !equal(t, f1.Field(i), f2.Field(i)) {
return false
}
}
return true
case reflect.String:
return f1.String() == f2.String()
case reflect.Bool:
return f1.Bool() == f2.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return f1.Int() == f2.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return f1.Uint() == f2.Uint()
default:
t.Errorf("test internal error: unsupported kind %v", f1.Type().Kind())
return true
}
}