Source file src/time/tzdata_test.go

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package time_test
     6  
     7  import (
     8  	"reflect"
     9  	"testing"
    10  	"time"
    11  	_ "time/tzdata"
    12  )
    13  
    14  var zones = []string{
    15  	"Asia/Jerusalem",
    16  	"America/Los_Angeles",
    17  }
    18  
    19  func TestEmbeddedTZData(t *testing.T) {
    20  	time.ForceZipFileForTesting(true)
    21  	defer time.ForceZipFileForTesting(false)
    22  
    23  	for _, zone := range zones {
    24  		ref, err := time.LoadLocation(zone)
    25  		if err != nil {
    26  			t.Errorf("LoadLocation(%q): %v", zone, err)
    27  			continue
    28  		}
    29  
    30  		embedded, err := time.LoadFromEmbeddedTZData(zone)
    31  		if err != nil {
    32  			t.Errorf("LoadFromEmbeddedTZData(%q): %v", zone, err)
    33  			continue
    34  		}
    35  		sample, err := time.LoadLocationFromTZData(zone, []byte(embedded))
    36  		if err != nil {
    37  			t.Errorf("LoadLocationFromTZData failed for %q: %v", zone, err)
    38  			continue
    39  		}
    40  
    41  		// Compare the name and zone fields of ref and sample.
    42  		// The tx field changes faster as tzdata is updated.
    43  		// The cache fields are expected to differ.
    44  		v1 := reflect.ValueOf(ref).Elem()
    45  		v2 := reflect.ValueOf(sample).Elem()
    46  		typ := v1.Type()
    47  		nf := typ.NumField()
    48  		found := 0
    49  		for i := 0; i < nf; i++ {
    50  			ft := typ.Field(i)
    51  			if ft.Name != "name" && ft.Name != "zone" {
    52  				continue
    53  			}
    54  			found++
    55  			if !equal(t, v1.Field(i), v2.Field(i)) {
    56  				t.Errorf("zone %s: system and embedded tzdata field %s differs", zone, ft.Name)
    57  			}
    58  		}
    59  		if found != 2 {
    60  			t.Errorf("test must be updated for change to time.Location struct")
    61  		}
    62  	}
    63  }
    64  
    65  // equal is a small version of reflect.DeepEqual that we use to
    66  // compare the values of zoneinfo unexported fields.
    67  func equal(t *testing.T, f1, f2 reflect.Value) bool {
    68  	switch f1.Type().Kind() {
    69  	case reflect.Slice:
    70  		if f1.Len() != f2.Len() {
    71  			return false
    72  		}
    73  		for i := 0; i < f1.Len(); i++ {
    74  			if !equal(t, f1.Index(i), f2.Index(i)) {
    75  				return false
    76  			}
    77  		}
    78  		return true
    79  	case reflect.Struct:
    80  		nf := f1.Type().NumField()
    81  		for i := 0; i < nf; i++ {
    82  			if !equal(t, f1.Field(i), f2.Field(i)) {
    83  				return false
    84  			}
    85  		}
    86  		return true
    87  	case reflect.String:
    88  		return f1.String() == f2.String()
    89  	case reflect.Bool:
    90  		return f1.Bool() == f2.Bool()
    91  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    92  		return f1.Int() == f2.Int()
    93  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
    94  		return f1.Uint() == f2.Uint()
    95  	default:
    96  		t.Errorf("test internal error: unsupported kind %v", f1.Type().Kind())
    97  		return true
    98  	}
    99  }
   100  

View as plain text