Source file src/reflect/iter_test.go

     1  // Copyright 2024 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 reflect_test
     6  
     7  import (
     8  	"iter"
     9  	"maps"
    10  	"reflect"
    11  	. "reflect"
    12  	"testing"
    13  )
    14  
    15  type N int8
    16  
    17  func TestValueSeq(t *testing.T) {
    18  	m := map[string]int{
    19  		"1": 1,
    20  		"2": 2,
    21  		"3": 3,
    22  		"4": 4,
    23  	}
    24  	c := make(chan int, 3)
    25  	for i := range 3 {
    26  		c <- i
    27  	}
    28  	close(c)
    29  	tests := []struct {
    30  		name  string
    31  		val   Value
    32  		check func(*testing.T, iter.Seq[Value])
    33  	}{
    34  		{"int", ValueOf(4), func(t *testing.T, s iter.Seq[Value]) {
    35  			i := int64(0)
    36  			for v := range s {
    37  				if v.Int() != i {
    38  					t.Fatalf("got %d, want %d", v.Int(), i)
    39  				}
    40  				i++
    41  			}
    42  			if i != 4 {
    43  				t.Fatalf("should loop four times")
    44  			}
    45  		}},
    46  		{"int8", ValueOf(int8(4)), func(t *testing.T, s iter.Seq[Value]) {
    47  			i := int8(0)
    48  			for v := range s {
    49  				if v.Interface().(int8) != i {
    50  					t.Fatalf("got %d, want %d", v.Int(), i)
    51  				}
    52  				i++
    53  			}
    54  			if i != 4 {
    55  				t.Fatalf("should loop four times")
    56  			}
    57  		}},
    58  		{"uint", ValueOf(uint64(4)), func(t *testing.T, s iter.Seq[Value]) {
    59  			i := uint64(0)
    60  			for v := range s {
    61  				if v.Uint() != i {
    62  					t.Fatalf("got %d, want %d", v.Uint(), i)
    63  				}
    64  				i++
    65  			}
    66  			if i != 4 {
    67  				t.Fatalf("should loop four times")
    68  			}
    69  		}},
    70  		{"uint8", ValueOf(uint8(4)), func(t *testing.T, s iter.Seq[Value]) {
    71  			i := uint8(0)
    72  			for v := range s {
    73  				if v.Interface().(uint8) != i {
    74  					t.Fatalf("got %d, want %d", v.Int(), i)
    75  				}
    76  				i++
    77  			}
    78  			if i != 4 {
    79  				t.Fatalf("should loop four times")
    80  			}
    81  		}},
    82  		{"*[4]int", ValueOf(&[4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq[Value]) {
    83  			i := int64(0)
    84  			for v := range s {
    85  				if v.Int() != i {
    86  					t.Fatalf("got %d, want %d", v.Int(), i)
    87  				}
    88  				i++
    89  			}
    90  			if i != 4 {
    91  				t.Fatalf("should loop four times")
    92  			}
    93  		}},
    94  		// Regression: Value.Seq on a nil *[n]int must not panic (Elem of nil ptr is invalid).
    95  		{"nil *[3]int", ValueOf((*[3]int)(nil)), func(t *testing.T, s iter.Seq[Value]) {
    96  			i := int64(0)
    97  			for v := range s {
    98  				if v.Int() != i {
    99  					t.Fatalf("got %d, want %d", v.Int(), i)
   100  				}
   101  				i++
   102  			}
   103  			if i != 3 {
   104  				t.Fatalf("should loop three times, got %d", i)
   105  			}
   106  		}},
   107  		{"[4]int", ValueOf([4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq[Value]) {
   108  			i := int64(0)
   109  			for v := range s {
   110  				if v.Int() != i {
   111  					t.Fatalf("got %d, want %d", v.Int(), i)
   112  				}
   113  				i++
   114  			}
   115  			if i != 4 {
   116  				t.Fatalf("should loop four times")
   117  			}
   118  		}},
   119  		{"[]int", ValueOf([]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq[Value]) {
   120  			i := int64(0)
   121  			for v := range s {
   122  				if v.Int() != i {
   123  					t.Fatalf("got %d, want %d", v.Int(), i)
   124  				}
   125  				i++
   126  			}
   127  			if i != 4 {
   128  				t.Fatalf("should loop four times")
   129  			}
   130  		}},
   131  		{"string", ValueOf("12语言"), func(t *testing.T, s iter.Seq[Value]) {
   132  			i := int64(0)
   133  			indexes := []int64{0, 1, 2, 5}
   134  			for v := range s {
   135  				if v.Int() != indexes[i] {
   136  					t.Fatalf("got %d, want %d", v.Int(), indexes[i])
   137  				}
   138  				i++
   139  			}
   140  			if i != 4 {
   141  				t.Fatalf("should loop four times")
   142  			}
   143  		}},
   144  		{"map[string]int", ValueOf(m), func(t *testing.T, s iter.Seq[Value]) {
   145  			copy := maps.Clone(m)
   146  			for v := range s {
   147  				if _, ok := copy[v.String()]; !ok {
   148  					t.Fatalf("unexpected %v", v.Interface())
   149  				}
   150  				delete(copy, v.String())
   151  			}
   152  			if len(copy) != 0 {
   153  				t.Fatalf("should loop four times")
   154  			}
   155  		}},
   156  		{"chan int", ValueOf(c), func(t *testing.T, s iter.Seq[Value]) {
   157  			i := 0
   158  			m := map[int64]bool{
   159  				0: false,
   160  				1: false,
   161  				2: false,
   162  			}
   163  			for v := range s {
   164  				if b, ok := m[v.Int()]; !ok || b {
   165  					t.Fatalf("unexpected %v", v.Interface())
   166  				}
   167  				m[v.Int()] = true
   168  				i++
   169  			}
   170  			if i != 3 {
   171  				t.Fatalf("should loop three times")
   172  			}
   173  		}},
   174  		{"func", ValueOf(func(yield func(int) bool) {
   175  			for i := range 4 {
   176  				if !yield(i) {
   177  					return
   178  				}
   179  			}
   180  		}), func(t *testing.T, s iter.Seq[Value]) {
   181  			i := int64(0)
   182  			for v := range s {
   183  				if v.Int() != i {
   184  					t.Fatalf("got %d, want %d", v.Int(), i)
   185  				}
   186  				i++
   187  			}
   188  			if i != 4 {
   189  				t.Fatalf("should loop four times")
   190  			}
   191  		}},
   192  		{"method", ValueOf(methodIter{}).MethodByName("Seq"), func(t *testing.T, s iter.Seq[Value]) {
   193  			i := int64(0)
   194  			for v := range s {
   195  				if v.Int() != i {
   196  					t.Fatalf("got %d, want %d", v.Int(), i)
   197  				}
   198  				i++
   199  			}
   200  			if i != 4 {
   201  				t.Fatalf("should loop four times")
   202  			}
   203  		}},
   204  		{"type N int8", ValueOf(N(4)), func(t *testing.T, s iter.Seq[Value]) {
   205  			i := N(0)
   206  			for v := range s {
   207  				if v.Int() != int64(i) {
   208  					t.Fatalf("got %d, want %d", v.Int(), i)
   209  				}
   210  				i++
   211  				if v.Type() != reflect.TypeOf(i) {
   212  					t.Fatalf("got %s, want %s", v.Type(), reflect.TypeOf(i))
   213  				}
   214  			}
   215  			if i != 4 {
   216  				t.Fatalf("should loop four times")
   217  			}
   218  		}},
   219  	}
   220  	for _, tc := range tests {
   221  		seq := tc.val.Seq()
   222  		tc.check(t, seq)
   223  	}
   224  }
   225  
   226  func TestValueSeq2(t *testing.T) {
   227  	m := map[string]int{
   228  		"1": 1,
   229  		"2": 2,
   230  		"3": 3,
   231  		"4": 4,
   232  	}
   233  	tests := []struct {
   234  		name  string
   235  		val   Value
   236  		check func(*testing.T, iter.Seq2[Value, Value])
   237  	}{
   238  		{"*[4]int", ValueOf(&[4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   239  			i := int64(0)
   240  			for v1, v2 := range s {
   241  				if v1.Int() != i {
   242  					t.Fatalf("got %d, want %d", v1.Int(), i)
   243  				}
   244  				i++
   245  				if v2.Int() != i {
   246  					t.Fatalf("got %d, want %d", v2.Int(), i)
   247  				}
   248  			}
   249  			if i != 4 {
   250  				t.Fatalf("should loop four times")
   251  			}
   252  		}},
   253  		{"[4]int", ValueOf([4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   254  			i := int64(0)
   255  			for v1, v2 := range s {
   256  				if v1.Int() != i {
   257  					t.Fatalf("got %d, want %d", v1.Int(), i)
   258  				}
   259  				i++
   260  				if v2.Int() != i {
   261  					t.Fatalf("got %d, want %d", v2.Int(), i)
   262  				}
   263  			}
   264  			if i != 4 {
   265  				t.Fatalf("should loop four times")
   266  			}
   267  		}},
   268  		{"[]int", ValueOf([]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   269  			i := int64(0)
   270  			for v1, v2 := range s {
   271  				if v1.Int() != i {
   272  					t.Fatalf("got %d, want %d", v1.Int(), i)
   273  				}
   274  				i++
   275  				if v2.Int() != i {
   276  					t.Fatalf("got %d, want %d", v2.Int(), i)
   277  				}
   278  			}
   279  			if i != 4 {
   280  				t.Fatalf("should loop four times")
   281  			}
   282  		}},
   283  		{"string", ValueOf("12语言"), func(t *testing.T, s iter.Seq2[Value, Value]) {
   284  			next, stop := iter.Pull2(s)
   285  			defer stop()
   286  			i := int64(0)
   287  			for j, s := range "12语言" {
   288  				v1, v2, ok := next()
   289  				if !ok {
   290  					t.Fatalf("should loop four times")
   291  				}
   292  				if v1.Int() != int64(j) {
   293  					t.Fatalf("got %d, want %d", v1.Int(), j)
   294  				}
   295  				if v2.Interface() != s {
   296  					t.Fatalf("got %v, want %v", v2.Interface(), s)
   297  				}
   298  				i++
   299  			}
   300  			if i != 4 {
   301  				t.Fatalf("should loop four times")
   302  			}
   303  		}},
   304  		{"map[string]int", ValueOf(m), func(t *testing.T, s iter.Seq2[Value, Value]) {
   305  			copy := maps.Clone(m)
   306  			for v1, v2 := range s {
   307  				v, ok := copy[v1.String()]
   308  				if !ok {
   309  					t.Fatalf("unexpected %v", v1.String())
   310  				}
   311  				if v != v2.Interface() {
   312  					t.Fatalf("got %v, want %d", v2.Interface(), v)
   313  				}
   314  				delete(copy, v1.String())
   315  			}
   316  			if len(copy) != 0 {
   317  				t.Fatalf("should loop four times")
   318  			}
   319  		}},
   320  		{"func", ValueOf(func(f func(int, int) bool) {
   321  			for i := range 4 {
   322  				f(i, i+1)
   323  			}
   324  		}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   325  			i := int64(0)
   326  			for v1, v2 := range s {
   327  				if v1.Int() != i {
   328  					t.Fatalf("got %d, want %d", v1.Int(), i)
   329  				}
   330  				i++
   331  				if v2.Int() != i {
   332  					t.Fatalf("got %d, want %d", v2.Int(), i)
   333  				}
   334  			}
   335  			if i != 4 {
   336  				t.Fatalf("should loop four times")
   337  			}
   338  		}},
   339  		{"method", ValueOf(methodIter2{}).MethodByName("Seq2"), func(t *testing.T, s iter.Seq2[Value, Value]) {
   340  			i := int64(0)
   341  			for v1, v2 := range s {
   342  				if v1.Int() != i {
   343  					t.Fatalf("got %d, want %d", v1.Int(), i)
   344  				}
   345  				i++
   346  				if v2.Int() != i {
   347  					t.Fatalf("got %d, want %d", v2.Int(), i)
   348  				}
   349  			}
   350  			if i != 4 {
   351  				t.Fatalf("should loop four times")
   352  			}
   353  		}},
   354  		{"[4]N", ValueOf([4]N{0, 1, 2, 3}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   355  			i := N(0)
   356  			for v1, v2 := range s {
   357  				if v1.Int() != int64(i) {
   358  					t.Fatalf("got %d, want %d", v1.Int(), i)
   359  				}
   360  				if v2.Int() != int64(i) {
   361  					t.Fatalf("got %d, want %d", v2.Int(), i)
   362  				}
   363  				i++
   364  				if v2.Type() != reflect.TypeOf(i) {
   365  					t.Fatalf("got %s, want %s", v2.Type(), reflect.TypeOf(i))
   366  				}
   367  			}
   368  			if i != 4 {
   369  				t.Fatalf("should loop four times")
   370  			}
   371  		}},
   372  		{"[]N", ValueOf([]N{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   373  			i := N(0)
   374  			for v1, v2 := range s {
   375  				if v1.Int() != int64(i) {
   376  					t.Fatalf("got %d, want %d", v1.Int(), i)
   377  				}
   378  				i++
   379  				if v2.Int() != int64(i) {
   380  					t.Fatalf("got %d, want %d", v2.Int(), i)
   381  				}
   382  				if v2.Type() != reflect.TypeOf(i) {
   383  					t.Fatalf("got %s, want %s", v2.Type(), reflect.TypeOf(i))
   384  				}
   385  			}
   386  			if i != 4 {
   387  				t.Fatalf("should loop four times")
   388  			}
   389  		}},
   390  	}
   391  	for _, tc := range tests {
   392  		seq := tc.val.Seq2()
   393  		tc.check(t, seq)
   394  	}
   395  }
   396  
   397  // methodIter is a type from which we can derive a method
   398  // value that is an iter.Seq.
   399  type methodIter struct{}
   400  
   401  func (methodIter) Seq(yield func(int) bool) {
   402  	for i := range 4 {
   403  		if !yield(i) {
   404  			return
   405  		}
   406  	}
   407  }
   408  
   409  // For Type.CanSeq test.
   410  func (methodIter) NonSeq(yield func(int)) {}
   411  
   412  // methodIter2 is a type from which we can derive a method
   413  // value that is an iter.Seq2.
   414  type methodIter2 struct{}
   415  
   416  func (methodIter2) Seq2(yield func(int, int) bool) {
   417  	for i := range 4 {
   418  		if !yield(i, i+1) {
   419  			return
   420  		}
   421  	}
   422  }
   423  
   424  // For Type.CanSeq2 test.
   425  func (methodIter2) NonSeq2(yield func(int, int)) {}
   426  
   427  func TestSeqRetNamedBool(t *testing.T) {
   428  	type Bool bool
   429  	// Note: Type.Name() == "bool" is a incorrect check,
   430  	// the named boolean type below will pass the incorrect check.
   431  	type bool Bool
   432  	v := ValueOf(func(func(int) bool) {})
   433  	if v.Type().CanSeq() {
   434  		t.Fatal("got true, want false")
   435  	}
   436  	shouldPanic("reflect: func(func(int) reflect_test.bool) cannot produce iter.Seq[Value]", func() { v.Seq() })
   437  	v2 := ValueOf(func(func(int, int) bool) {})
   438  	if v2.Type().CanSeq() {
   439  		t.Fatal("got true, want false")
   440  	}
   441  	shouldPanic("func(func(int, int) reflect_test.bool) cannot produce iter.Seq2[Value, Value]", func() { v2.Seq2() })
   442  }
   443  

View as plain text