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  		{"[4]int", ValueOf([4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq[Value]) {
    95  			i := int64(0)
    96  			for v := range s {
    97  				if v.Int() != i {
    98  					t.Fatalf("got %d, want %d", v.Int(), i)
    99  				}
   100  				i++
   101  			}
   102  			if i != 4 {
   103  				t.Fatalf("should loop four times")
   104  			}
   105  		}},
   106  		{"[]int", ValueOf([]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq[Value]) {
   107  			i := int64(0)
   108  			for v := range s {
   109  				if v.Int() != i {
   110  					t.Fatalf("got %d, want %d", v.Int(), i)
   111  				}
   112  				i++
   113  			}
   114  			if i != 4 {
   115  				t.Fatalf("should loop four times")
   116  			}
   117  		}},
   118  		{"string", ValueOf("12语言"), func(t *testing.T, s iter.Seq[Value]) {
   119  			i := int64(0)
   120  			indexes := []int64{0, 1, 2, 5}
   121  			for v := range s {
   122  				if v.Int() != indexes[i] {
   123  					t.Fatalf("got %d, want %d", v.Int(), indexes[i])
   124  				}
   125  				i++
   126  			}
   127  			if i != 4 {
   128  				t.Fatalf("should loop four times")
   129  			}
   130  		}},
   131  		{"map[string]int", ValueOf(m), func(t *testing.T, s iter.Seq[Value]) {
   132  			copy := maps.Clone(m)
   133  			for v := range s {
   134  				if _, ok := copy[v.String()]; !ok {
   135  					t.Fatalf("unexpected %v", v.Interface())
   136  				}
   137  				delete(copy, v.String())
   138  			}
   139  			if len(copy) != 0 {
   140  				t.Fatalf("should loop four times")
   141  			}
   142  		}},
   143  		{"chan int", ValueOf(c), func(t *testing.T, s iter.Seq[Value]) {
   144  			i := 0
   145  			m := map[int64]bool{
   146  				0: false,
   147  				1: false,
   148  				2: false,
   149  			}
   150  			for v := range s {
   151  				if b, ok := m[v.Int()]; !ok || b {
   152  					t.Fatalf("unexpected %v", v.Interface())
   153  				}
   154  				m[v.Int()] = true
   155  				i++
   156  			}
   157  			if i != 3 {
   158  				t.Fatalf("should loop three times")
   159  			}
   160  		}},
   161  		{"func", ValueOf(func(yield func(int) bool) {
   162  			for i := range 4 {
   163  				if !yield(i) {
   164  					return
   165  				}
   166  			}
   167  		}), func(t *testing.T, s iter.Seq[Value]) {
   168  			i := int64(0)
   169  			for v := range s {
   170  				if v.Int() != i {
   171  					t.Fatalf("got %d, want %d", v.Int(), i)
   172  				}
   173  				i++
   174  			}
   175  			if i != 4 {
   176  				t.Fatalf("should loop four times")
   177  			}
   178  		}},
   179  		{"method", ValueOf(methodIter{}).Method(0), func(t *testing.T, s iter.Seq[Value]) {
   180  			i := int64(0)
   181  			for v := range s {
   182  				if v.Int() != i {
   183  					t.Fatalf("got %d, want %d", v.Int(), i)
   184  				}
   185  				i++
   186  			}
   187  			if i != 4 {
   188  				t.Fatalf("should loop four times")
   189  			}
   190  		}},
   191  		{"type N int8", ValueOf(N(4)), func(t *testing.T, s iter.Seq[Value]) {
   192  			i := N(0)
   193  			for v := range s {
   194  				if v.Int() != int64(i) {
   195  					t.Fatalf("got %d, want %d", v.Int(), i)
   196  				}
   197  				i++
   198  				if v.Type() != reflect.TypeOf(i) {
   199  					t.Fatalf("got %s, want %s", v.Type(), reflect.TypeOf(i))
   200  				}
   201  			}
   202  			if i != 4 {
   203  				t.Fatalf("should loop four times")
   204  			}
   205  		}},
   206  	}
   207  	for _, tc := range tests {
   208  		seq := tc.val.Seq()
   209  		tc.check(t, seq)
   210  	}
   211  }
   212  
   213  func TestValueSeq2(t *testing.T) {
   214  	m := map[string]int{
   215  		"1": 1,
   216  		"2": 2,
   217  		"3": 3,
   218  		"4": 4,
   219  	}
   220  	tests := []struct {
   221  		name  string
   222  		val   Value
   223  		check func(*testing.T, iter.Seq2[Value, Value])
   224  	}{
   225  		{"*[4]int", ValueOf(&[4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   226  			i := int64(0)
   227  			for v1, v2 := range s {
   228  				if v1.Int() != i {
   229  					t.Fatalf("got %d, want %d", v1.Int(), i)
   230  				}
   231  				i++
   232  				if v2.Int() != i {
   233  					t.Fatalf("got %d, want %d", v2.Int(), i)
   234  				}
   235  			}
   236  			if i != 4 {
   237  				t.Fatalf("should loop four times")
   238  			}
   239  		}},
   240  		{"[4]int", ValueOf([4]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   241  			i := int64(0)
   242  			for v1, v2 := range s {
   243  				if v1.Int() != i {
   244  					t.Fatalf("got %d, want %d", v1.Int(), i)
   245  				}
   246  				i++
   247  				if v2.Int() != i {
   248  					t.Fatalf("got %d, want %d", v2.Int(), i)
   249  				}
   250  			}
   251  			if i != 4 {
   252  				t.Fatalf("should loop four times")
   253  			}
   254  		}},
   255  		{"[]int", ValueOf([]int{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   256  			i := int64(0)
   257  			for v1, v2 := range s {
   258  				if v1.Int() != i {
   259  					t.Fatalf("got %d, want %d", v1.Int(), i)
   260  				}
   261  				i++
   262  				if v2.Int() != i {
   263  					t.Fatalf("got %d, want %d", v2.Int(), i)
   264  				}
   265  			}
   266  			if i != 4 {
   267  				t.Fatalf("should loop four times")
   268  			}
   269  		}},
   270  		{"string", ValueOf("12语言"), func(t *testing.T, s iter.Seq2[Value, Value]) {
   271  			next, stop := iter.Pull2(s)
   272  			defer stop()
   273  			i := int64(0)
   274  			for j, s := range "12语言" {
   275  				v1, v2, ok := next()
   276  				if !ok {
   277  					t.Fatalf("should loop four times")
   278  				}
   279  				if v1.Int() != int64(j) {
   280  					t.Fatalf("got %d, want %d", v1.Int(), j)
   281  				}
   282  				if v2.Interface() != s {
   283  					t.Fatalf("got %v, want %v", v2.Interface(), s)
   284  				}
   285  				i++
   286  			}
   287  			if i != 4 {
   288  				t.Fatalf("should loop four times")
   289  			}
   290  		}},
   291  		{"map[string]int", ValueOf(m), func(t *testing.T, s iter.Seq2[Value, Value]) {
   292  			copy := maps.Clone(m)
   293  			for v1, v2 := range s {
   294  				v, ok := copy[v1.String()]
   295  				if !ok {
   296  					t.Fatalf("unexpected %v", v1.String())
   297  				}
   298  				if v != v2.Interface() {
   299  					t.Fatalf("got %v, want %d", v2.Interface(), v)
   300  				}
   301  				delete(copy, v1.String())
   302  			}
   303  			if len(copy) != 0 {
   304  				t.Fatalf("should loop four times")
   305  			}
   306  		}},
   307  		{"func", ValueOf(func(f func(int, int) bool) {
   308  			for i := range 4 {
   309  				f(i, i+1)
   310  			}
   311  		}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   312  			i := int64(0)
   313  			for v1, v2 := range s {
   314  				if v1.Int() != i {
   315  					t.Fatalf("got %d, want %d", v1.Int(), i)
   316  				}
   317  				i++
   318  				if v2.Int() != i {
   319  					t.Fatalf("got %d, want %d", v2.Int(), i)
   320  				}
   321  			}
   322  			if i != 4 {
   323  				t.Fatalf("should loop four times")
   324  			}
   325  		}},
   326  		{"method", ValueOf(methodIter2{}).Method(0), func(t *testing.T, s iter.Seq2[Value, Value]) {
   327  			i := int64(0)
   328  			for v1, v2 := range s {
   329  				if v1.Int() != i {
   330  					t.Fatalf("got %d, want %d", v1.Int(), i)
   331  				}
   332  				i++
   333  				if v2.Int() != i {
   334  					t.Fatalf("got %d, want %d", v2.Int(), i)
   335  				}
   336  			}
   337  			if i != 4 {
   338  				t.Fatalf("should loop four times")
   339  			}
   340  		}},
   341  		{"[4]N", ValueOf([4]N{0, 1, 2, 3}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   342  			i := N(0)
   343  			for v1, v2 := range s {
   344  				if v1.Int() != int64(i) {
   345  					t.Fatalf("got %d, want %d", v1.Int(), i)
   346  				}
   347  				if v2.Int() != int64(i) {
   348  					t.Fatalf("got %d, want %d", v2.Int(), i)
   349  				}
   350  				i++
   351  				if v2.Type() != reflect.TypeOf(i) {
   352  					t.Fatalf("got %s, want %s", v2.Type(), reflect.TypeOf(i))
   353  				}
   354  			}
   355  			if i != 4 {
   356  				t.Fatalf("should loop four times")
   357  			}
   358  		}},
   359  		{"[]N", ValueOf([]N{1, 2, 3, 4}), func(t *testing.T, s iter.Seq2[Value, Value]) {
   360  			i := N(0)
   361  			for v1, v2 := range s {
   362  				if v1.Int() != int64(i) {
   363  					t.Fatalf("got %d, want %d", v1.Int(), i)
   364  				}
   365  				i++
   366  				if v2.Int() != int64(i) {
   367  					t.Fatalf("got %d, want %d", v2.Int(), i)
   368  				}
   369  				if v2.Type() != reflect.TypeOf(i) {
   370  					t.Fatalf("got %s, want %s", v2.Type(), reflect.TypeOf(i))
   371  				}
   372  			}
   373  			if i != 4 {
   374  				t.Fatalf("should loop four times")
   375  			}
   376  		}},
   377  	}
   378  	for _, tc := range tests {
   379  		seq := tc.val.Seq2()
   380  		tc.check(t, seq)
   381  	}
   382  }
   383  
   384  // methodIter is a type from which we can derive a method
   385  // value that is an iter.Seq.
   386  type methodIter struct{}
   387  
   388  func (methodIter) Seq(yield func(int) bool) {
   389  	for i := range 4 {
   390  		if !yield(i) {
   391  			return
   392  		}
   393  	}
   394  }
   395  
   396  // methodIter2 is a type from which we can derive a method
   397  // value that is an iter.Seq2.
   398  type methodIter2 struct{}
   399  
   400  func (methodIter2) Seq2(yield func(int, int) bool) {
   401  	for i := range 4 {
   402  		if !yield(i, i+1) {
   403  			return
   404  		}
   405  	}
   406  }
   407  

View as plain text