github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/goutils/iterate/impl_test.go (about)

     1  /*
     2   * Copyright (c) 2021-present Sigma-Soft, Ltd.
     3   * @author: Nikolay Nikitin
     4   */
     5  
     6  package iterate
     7  
     8  import (
     9  	"errors"
    10  	"fmt"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  type (
    17  	ITested1 interface {
    18  		Fields(enum func(name string))
    19  	}
    20  	tested1 struct {
    21  		fields []string
    22  	}
    23  )
    24  
    25  func (s *tested1) Fields(enum func(name string)) {
    26  	for _, name := range s.fields {
    27  		enum(name)
    28  	}
    29  }
    30  
    31  func Test_ForEach(t *testing.T) {
    32  	require := require.New(t)
    33  
    34  	t.Run("test ForEach with interface method", func(t *testing.T) {
    35  		var tested ITested1 = &tested1{fields: []string{"a", "b", "c"}}
    36  
    37  		line := ""
    38  		ForEach(tested.Fields, func(d string) { line += d })
    39  
    40  		require.Equal("abc", line)
    41  	})
    42  
    43  	t.Run("test ForEach with structure method", func(t *testing.T) {
    44  		tested := tested1{fields: []string{"a", "b", "c"}}
    45  
    46  		line := ""
    47  		ForEach(tested.Fields, func(d string) { line += d })
    48  
    49  		require.Equal("abc", line)
    50  	})
    51  
    52  	t.Run("test ForEach with naked slice", func(t *testing.T) {
    53  		fields := []string{"a", "b", "c"}
    54  
    55  		line := ""
    56  		ForEach(Slice(fields), func(d string) { line += d })
    57  
    58  		require.Equal("abc", line)
    59  	})
    60  }
    61  
    62  func Test_FindFirst(t *testing.T) {
    63  	require := require.New(t)
    64  
    65  	t.Run("test FindFirst with interface method", func(t *testing.T) {
    66  		var tested ITested1 = &tested1{fields: []string{"a", "b", "c"}}
    67  
    68  		ok, data := FindFirst(tested.Fields, func(data string) bool { return data == "b" })
    69  		require.True(ok)
    70  		require.Equal("b", data)
    71  
    72  		ok, data = FindFirst(tested.Fields, func(data string) bool { return data == "impossible" })
    73  		require.False(ok)
    74  		require.Empty(data)
    75  	})
    76  
    77  	t.Run("test FindFirst with structure method", func(t *testing.T) {
    78  		tested := tested1{fields: []string{"a", "b", "c"}}
    79  
    80  		ok, data := FindFirst(tested.Fields, func(data string) bool { return data == "b" })
    81  		require.True(ok)
    82  		require.Equal("b", data)
    83  
    84  		ok, data = FindFirst(tested.Fields, func(data string) bool { return data == "impossible" })
    85  		require.False(ok)
    86  		require.Empty(data)
    87  	})
    88  
    89  	t.Run("test FindFirst with naked slice", func(t *testing.T) {
    90  		fields := []string{"a", "b", "c"}
    91  
    92  		ok, data := FindFirst(Slice(fields), func(data string) bool { return data == "b" })
    93  		require.True(ok)
    94  		require.Equal("b", data)
    95  
    96  		ok, data = FindFirst(Slice(fields), func(data string) bool { return data == "impossible" })
    97  		require.False(ok)
    98  		require.Empty(data)
    99  	})
   100  }
   101  
   102  func Test_FindData(t *testing.T) {
   103  	require := require.New(t)
   104  
   105  	t.Run("test FindFirstData with interface method", func(t *testing.T) {
   106  		var tested ITested1 = &tested1{fields: []string{"a", "b", "c"}}
   107  
   108  		ok, idx := FindFirstData(tested.Fields, "b")
   109  		require.True(ok)
   110  		require.Equal(1, idx)
   111  
   112  		ok, idx = FindFirstData(tested.Fields, "impossible")
   113  		require.False(ok)
   114  		require.Less(idx, 0)
   115  	})
   116  
   117  	t.Run("test FindFirstData with structure method", func(t *testing.T) {
   118  		tested := tested1{fields: []string{"a", "b", "c"}}
   119  
   120  		ok, idx := FindFirstData(tested.Fields, "b")
   121  		require.True(ok)
   122  		require.Equal(1, idx)
   123  
   124  		ok, idx = FindFirstData(tested.Fields, "impossible")
   125  		require.False(ok)
   126  		require.Less(idx, 0)
   127  	})
   128  
   129  	t.Run("test FindFirstData with naked slice", func(t *testing.T) {
   130  		fields := []string{"a", "b", "c"}
   131  
   132  		ok, idx := FindFirstData(Slice(fields), "b")
   133  		require.True(ok)
   134  		require.Equal(1, idx)
   135  
   136  		ok, idx = FindFirstData(Slice(fields), "impossible")
   137  		require.False(ok)
   138  		require.Less(idx, 0)
   139  	})
   140  }
   141  
   142  func Test_FindFirstError(t *testing.T) {
   143  	require := require.New(t)
   144  
   145  	t.Run("test FindFirstError with interface method", func(t *testing.T) {
   146  		var tested ITested1 = &tested1{fields: []string{"a", "b", "c"}}
   147  
   148  		data, err := FindFirstError(tested.Fields, func(data string) error {
   149  			if data == "b" {
   150  				return fmt.Errorf("error at %v", data)
   151  			}
   152  			return nil
   153  		})
   154  		require.Error(err)
   155  		require.Equal("b", data)
   156  
   157  		data, err = FindFirstError(tested.Fields, func(data string) error {
   158  			if data == "impossible" {
   159  				return fmt.Errorf("error at %v", data)
   160  			}
   161  			return nil
   162  		})
   163  		require.NoError(err)
   164  		require.Empty(data)
   165  	})
   166  
   167  	t.Run("test FindFirstError with structure method", func(t *testing.T) {
   168  		tested := tested1{fields: []string{"a", "b", "c"}}
   169  
   170  		data, err := FindFirstError(tested.Fields, func(data string) error {
   171  			if data == "b" {
   172  				return fmt.Errorf("error at %v", data)
   173  			}
   174  			return nil
   175  		})
   176  		require.Error(err)
   177  		require.Equal("b", data)
   178  
   179  		data, err = FindFirstError(tested.Fields, func(data string) error {
   180  			if data == "impossible" {
   181  				return fmt.Errorf("error at %v", data)
   182  			}
   183  			return nil
   184  		})
   185  		require.NoError(err)
   186  		require.Empty(data)
   187  	})
   188  
   189  	t.Run("test FindFirstError with naked slice", func(t *testing.T) {
   190  		fields := []string{"a", "b", "c"}
   191  
   192  		data, err := FindFirstError(Slice(fields), func(data string) error {
   193  			if data == "b" {
   194  				return fmt.Errorf("error at %v", data)
   195  			}
   196  			return nil
   197  		})
   198  		require.Error(err)
   199  		require.Equal("b", data)
   200  
   201  		data, err = FindFirstError(Slice(fields), func(data string) error {
   202  			if data == "impossible" {
   203  				return fmt.Errorf("error at %v", data)
   204  			}
   205  			return nil
   206  		})
   207  		require.NoError(err)
   208  		require.Empty(data)
   209  	})
   210  }
   211  
   212  type (
   213  	ITested2 interface {
   214  		Fields(enum func(name string, data int))
   215  	}
   216  	tested2 struct {
   217  		fields map[string]int
   218  	}
   219  )
   220  
   221  func (s *tested2) Fields(enum func(name string, data int)) {
   222  	for name, data := range s.fields {
   223  		enum(name, data)
   224  	}
   225  }
   226  
   227  func Test_ForEachMap(t *testing.T) {
   228  	require := require.New(t)
   229  
   230  	t.Run("test ForEachMap with interface method", func(t *testing.T) {
   231  		var tested ITested2 = &tested2{fields: map[string]int{"a": 1, "b": 2, "c": 3}}
   232  
   233  		keys, values := "", 0
   234  		ForEachMap(tested.Fields, func(k string, v int) { keys += k; values += v })
   235  
   236  		require.Len(keys, 3)
   237  		require.Contains(keys, "a")
   238  		require.Contains(keys, "b")
   239  		require.Contains(keys, "c")
   240  
   241  		require.Equal(1+2+3, values)
   242  	})
   243  
   244  	t.Run("test ForEachMap with structure method", func(t *testing.T) {
   245  		tested := tested2{fields: map[string]int{"a": 1, "b": 2, "c": 3}}
   246  
   247  		keys, values := "", 0
   248  		ForEachMap(tested.Fields, func(k string, v int) { keys += k; values += v })
   249  
   250  		require.Len(keys, 3)
   251  		require.Contains(keys, "a")
   252  		require.Contains(keys, "b")
   253  		require.Contains(keys, "c")
   254  
   255  		require.Equal(1+2+3, values)
   256  	})
   257  
   258  	t.Run("test ForEachMap with naked map", func(t *testing.T) {
   259  		tested := map[string]int{"a": 1, "b": 2, "c": 3}
   260  
   261  		keys, values := "", 0
   262  		ForEachMap(Map(tested), func(k string, v int) { keys += k; values += v })
   263  
   264  		require.Len(keys, 3)
   265  		require.Contains(keys, "a")
   266  		require.Contains(keys, "b")
   267  		require.Contains(keys, "c")
   268  
   269  		require.Equal(1+2+3, values)
   270  	})
   271  }
   272  
   273  func Test_FindFirstMap(t *testing.T) {
   274  	require := require.New(t)
   275  
   276  	t.Run("test FindFirstMap with interface method", func(t *testing.T) {
   277  		var tested ITested2 = &tested2{fields: map[string]int{"a": 1, "b": 2, "c": 3}}
   278  
   279  		ok, key, value := FindFirstMap(tested.Fields, func(k string, _ int) bool { return k == "b" })
   280  		require.True(ok)
   281  		require.Equal("b", key)
   282  		require.Equal(2, value)
   283  
   284  		ok, key, value = FindFirstMap(tested.Fields, func(k string, _ int) bool { return k == "impossible" })
   285  		require.False(ok)
   286  		require.Empty(key)
   287  		require.Empty(value)
   288  	})
   289  
   290  	t.Run("test FindFirstMap with structure method", func(t *testing.T) {
   291  		tested := tested2{fields: map[string]int{"a": 1, "b": 2, "c": 3}}
   292  
   293  		ok, key, value := FindFirstMap(tested.Fields, func(k string, _ int) bool { return k == "b" })
   294  		require.True(ok)
   295  		require.Equal("b", key)
   296  		require.Equal(2, value)
   297  
   298  		ok, key, value = FindFirstMap(tested.Fields, func(k string, _ int) bool { return k == "impossible" })
   299  		require.False(ok)
   300  		require.Empty(key)
   301  		require.Empty(value)
   302  	})
   303  
   304  	t.Run("test FindFirstMap with naked map", func(t *testing.T) {
   305  		fields := map[string]int{"a": 1, "b": 2, "c": 3}
   306  
   307  		ok, key, value := FindFirstMap(Map(fields), func(k string, _ int) bool { return k == "b" })
   308  		require.True(ok)
   309  		require.Equal("b", key)
   310  		require.Equal(2, value)
   311  
   312  		ok, key, value = FindFirstMap(Map(fields), func(k string, _ int) bool { return k == "impossible" })
   313  		require.False(ok)
   314  		require.Empty(key)
   315  		require.Empty(value)
   316  	})
   317  }
   318  
   319  func Test_FindFirstMapKey(t *testing.T) {
   320  	require := require.New(t)
   321  
   322  	t.Run("test FindFirstMapKey with interface method", func(t *testing.T) {
   323  		var tested ITested2 = &tested2{fields: map[string]int{"a": 1, "b": 2, "c": 3}}
   324  
   325  		ok, key, value := FindFirstMapKey(tested.Fields, "b")
   326  		require.True(ok)
   327  		require.Equal("b", key)
   328  		require.Equal(2, value)
   329  
   330  		ok, key, value = FindFirstMapKey(tested.Fields, "impossible")
   331  		require.False(ok)
   332  		require.Empty(key)
   333  		require.Empty(value)
   334  	})
   335  
   336  	t.Run("test FindFirstMapKey with structure method", func(t *testing.T) {
   337  		tested := tested2{fields: map[string]int{"a": 1, "b": 2, "c": 3}}
   338  
   339  		ok, key, value := FindFirstMapKey(tested.Fields, "b")
   340  		require.True(ok)
   341  		require.Equal("b", key)
   342  		require.Equal(2, value)
   343  
   344  		ok, key, value = FindFirstMapKey(tested.Fields, "impossible")
   345  		require.False(ok)
   346  		require.Empty(key)
   347  		require.Empty(value)
   348  	})
   349  
   350  	t.Run("test FindFirstMapKey with naked map", func(t *testing.T) {
   351  		fields := map[string]int{"a": 1, "b": 2, "c": 3}
   352  
   353  		ok, key, value := FindFirstMapKey(Map(fields), "b")
   354  		require.True(ok)
   355  		require.Equal("b", key)
   356  		require.Equal(2, value)
   357  
   358  		ok, key, value = FindFirstMapKey(Map(fields), "impossible")
   359  		require.False(ok)
   360  		require.Empty(key)
   361  		require.Empty(value)
   362  	})
   363  }
   364  
   365  func Test_FindFirstMapError(t *testing.T) {
   366  	require := require.New(t)
   367  
   368  	t.Run("test FindFirstMapError with interface method", func(t *testing.T) {
   369  		var tested ITested2 = &tested2{fields: map[string]int{"a": 1, "b": 2, "c": 3}}
   370  
   371  		key, value, err := FindFirstMapError(tested.Fields, func(k string, v int) error {
   372  			if k == "b" {
   373  				return fmt.Errorf("error at %v: %v", k, v)
   374  			}
   375  			return nil
   376  		})
   377  		require.Error(err)
   378  		require.Equal("b", key)
   379  		require.Equal(2, value)
   380  
   381  		key, value, err = FindFirstMapError(tested.Fields, func(k string, v int) error {
   382  			if k == "impossible" {
   383  				return fmt.Errorf("error at %v: %v", k, v)
   384  			}
   385  			return nil
   386  		})
   387  		require.NoError(err)
   388  		require.Empty(key)
   389  		require.Empty(value)
   390  	})
   391  
   392  	t.Run("test FindFirstMapError with structure method", func(t *testing.T) {
   393  		tested := tested2{fields: map[string]int{"a": 1, "b": 2, "c": 3}}
   394  
   395  		key, value, err := FindFirstMapError(tested.Fields, func(k string, v int) error {
   396  			if k == "b" {
   397  				return fmt.Errorf("error at %v: %v", k, v)
   398  			}
   399  			return nil
   400  		})
   401  		require.Error(err)
   402  		require.Equal("b", key)
   403  		require.Equal(2, value)
   404  
   405  		key, value, err = FindFirstMapError(tested.Fields, func(k string, v int) error {
   406  			if k == "impossible" {
   407  				return fmt.Errorf("error at %v: %v", k, v)
   408  			}
   409  			return nil
   410  		})
   411  		require.NoError(err)
   412  		require.Empty(key)
   413  		require.Empty(value)
   414  	})
   415  
   416  	t.Run("test FindFirstMapError with naked map", func(t *testing.T) {
   417  		tested := map[string]int{"a": 1, "b": 2, "c": 3}
   418  
   419  		key, value, err := FindFirstMapError(Map(tested), func(k string, v int) error {
   420  			if k == "b" {
   421  				return fmt.Errorf("error at %v: %v", k, v)
   422  			}
   423  			return nil
   424  		})
   425  		require.Error(err)
   426  		require.Equal("b", key)
   427  		require.Equal(2, value)
   428  
   429  		key, value, err = FindFirstMapError(Map(tested), func(k string, v int) error {
   430  			if k == "impossible" {
   431  				return fmt.Errorf("error at %v: %v", k, v)
   432  			}
   433  			return nil
   434  		})
   435  		require.NoError(err)
   436  		require.Empty(key)
   437  		require.Empty(value)
   438  	})
   439  }
   440  
   441  func TestForEachError(t *testing.T) {
   442  	require := require.New(t)
   443  
   444  	t.Run("no error", func(t *testing.T) {
   445  		err := ForEachError(func(enum func(str string)) {
   446  			enum("1")
   447  		}, func(s string) error {
   448  			require.Equal("1", s)
   449  			return nil
   450  		})
   451  		require.NoError(err)
   452  	})
   453  
   454  	t.Run("error", func(t *testing.T) {
   455  		testErr := errors.New("test error")
   456  		expected := ""
   457  		err := ForEachError(func(enum func(str string)) {
   458  			enum("1")
   459  			enum("2")
   460  			enum("3")
   461  			enum("4")
   462  		}, func(s string) error {
   463  			if s == "3" {
   464  				return testErr
   465  			}
   466  			expected += s
   467  			return nil
   468  		})
   469  		require.ErrorIs(err, testErr)
   470  		require.Equal("12", expected)
   471  	})
   472  }
   473  
   474  func TestForEachError1Arg(t *testing.T) {
   475  	require := require.New(t)
   476  	expectedArg1 := "expected str"
   477  
   478  	t.Run("no error", func(t *testing.T) {
   479  		err := ForEachError1Arg(func(arg1 string, enum func(str string)) {
   480  			enum("1")
   481  			require.Equal(expectedArg1, arg1)
   482  		}, expectedArg1, func(s string) error {
   483  			require.Equal("1", s)
   484  			return nil
   485  		})
   486  		require.NoError(err)
   487  	})
   488  
   489  	t.Run("error", func(t *testing.T) {
   490  		testErr := errors.New("test error")
   491  		expected := ""
   492  		err := ForEachError1Arg(func(arg1 string, enum func(str string)) {
   493  			enum("1")
   494  			enum("2")
   495  			enum("3")
   496  			enum("4")
   497  			require.Equal(expectedArg1, arg1)
   498  		}, expectedArg1, func(s string) error {
   499  			if s == "3" {
   500  				return testErr
   501  			}
   502  			expected += s
   503  			return nil
   504  		})
   505  		require.ErrorIs(err, testErr)
   506  		require.Equal("12", expected)
   507  	})
   508  }
   509  
   510  func TestForEachError2Values(t *testing.T) {
   511  	require := require.New(t)
   512  
   513  	t.Run("no error", func(t *testing.T) {
   514  		err := ForEachError2Values(func(enum func(v1 string, v2 int)) {
   515  			enum("str1", 42)
   516  		}, func(s string, i int) error {
   517  			require.Equal("str1", s)
   518  			require.Equal(42, i)
   519  			return nil
   520  		})
   521  		require.NoError(err)
   522  	})
   523  
   524  	t.Run("error", func(t *testing.T) {
   525  		testErr := errors.New("test error")
   526  		expectedSum := 0
   527  		err := ForEachError2Values(func(enum func(v1 string, v2 int)) {
   528  			enum("str1", 1)
   529  			enum("str2", 2)
   530  			enum("str3", 3)
   531  			enum("str4", 4)
   532  		}, func(s string, i int) error {
   533  			if i == 3 {
   534  				return testErr
   535  			}
   536  			require.Equal(fmt.Sprintf("str%d", i), s)
   537  			expectedSum += i
   538  			return nil
   539  		})
   540  		require.ErrorIs(err, testErr)
   541  		require.Equal(3, expectedSum)
   542  	})
   543  }