Best Go-testdeep code snippet using td.Between
td_json_test.go
Source:td_json_test.go  
...49			"Bob", 42, "male")) // raw values50	checkOK(t, got,51		td.JSON(`{"name":"$1","age":$2,"gender":"$3"}`,52			td.Re(`^Bob`),53			td.Between(40, 45),54			td.NotEmpty()))55	// Same using Flatten56	checkOK(t, got,57		td.JSON(`{"name":"$1","age":$2,"gender":"$3"}`,58			td.Re(`^Bob`),59			td.Flatten([]td.TestDeep{td.Between(40, 45), td.NotEmpty()}),60		))61	// Operators are not JSON marshallable62	checkOK(t, got,63		td.JSON(`$1`, map[string]any{64			"name":   td.Re(`^Bob`),65			"age":    42,66			"gender": td.NotEmpty(),67		}))68	// Placeholder + unmarshal before comparison69	checkOK(t, json.RawMessage(`[1,2,3]`), td.JSON(`$1`, []int{1, 2, 3}))70	checkOK(t, json.RawMessage(`{"foo":[1,2,3]}`),71		td.JSON(`{"foo":$1}`, []int{1, 2, 3}))72	checkOK(t, json.RawMessage(`[1,2,3]`),73		td.JSON(`$1`, []any{1, td.Between(1, 3), 3}))74	// Tag placeholders75	checkOK(t, got,76		td.JSON(`{"name":"$name","age":$age,"gender":$gender}`,77			// raw values78			td.Tag("name", "Bob"), td.Tag("age", 42), td.Tag("gender", "male")))79	checkOK(t, got,80		td.JSON(`{"name":"$name","age":$age,"gender":"$gender"}`,81			td.Tag("name", td.Re(`^Bo`)),82			td.Tag("age", td.Between(40, 45)),83			td.Tag("gender", td.NotEmpty())))84	// Tag placeholders + operators are not JSON marshallable85	checkOK(t, got,86		td.JSON(`$all`, td.Tag("all", map[string]any{87			"name":   td.Re(`^Bob`),88			"age":    42,89			"gender": td.NotEmpty(),90		})))91	// Tag placeholders + nil92	checkOK(t, nil, td.JSON(`$all`, td.Tag("all", nil)))93	// Mixed placeholders + operator94	for _, op := range []string{95		"NotEmpty",96		"NotEmpty()",97		"$^NotEmpty",98		"$^NotEmpty()",99		`"$^NotEmpty"`,100		`"$^NotEmpty()"`,101		`r<$^NotEmpty>`,102		`r<$^NotEmpty()>`,103	} {104		checkOK(t, got,105			td.JSON(`{"name":"$name","age":$1,"gender":`+op+`}`,106				td.Tag("age", td.Between(40, 45)),107				td.Tag("name", td.Re(`^Bob`))),108			"using operator %s", op)109	}110	checkOK(t, got,111		td.JSON(`{"name":Re("^Bo\\w"),"age":Between(40,45),"gender":NotEmpty()}`))112	checkOK(t, got,113		td.JSON(`114{115  "name":   All(Re("^Bo\\w"), HasPrefix("Bo"), HasSuffix("ob")),116  "age":    Between(40,45),117  "gender": NotEmpty()118}`))119	checkOK(t, got,120		td.JSON(`121{122  "name":   All(Re("^Bo\\w"), HasPrefix("Bo"), HasSuffix("ob")),123  "age":    Between(40,45),124  "gender": NotEmpty125}`))126	// Same but operators in strings using "$^"127	checkOK(t, got,128		td.JSON(`{"name":Re("^Bo\\w"),"age":"$^Between(40,45)","gender":"$^NotEmpty()"}`))129	checkOK(t, got, // using classic "" string, so each \ has to be escaped130		td.JSON(`131{132  "name":   "$^All(Re(\"^Bo\\\\w\"), HasPrefix(\"Bo\"), HasSuffix(\"ob\"))",133  "age":    "$^Between(40,45)",134  "gender": "$^NotEmpty()",135}`))136	checkOK(t, got, // using raw strings, no escape needed137		td.JSON(`138{139  "name":   "$^All(Re(r(^Bo\\w)), HasPrefix(r{Bo}), HasSuffix(r'ob'))",140  "age":    "$^Between(40,45)",141  "gender": "$^NotEmpty()",142}`))143	// â¦with commentsâ¦144	checkOK(t, got,145		td.JSON(`146// This should be the JSON representation of MyStruct struct147{148  // A person:149  "name":   "$name",   // The name of this person150  "age":    $1,        /* The age of this person:151                          - placeholder unquoted, but could be without152                            any change153                          - to demonstrate a multi-lines comment */154  "gender": $^NotEmpty // Operator NotEmpty155}`,156			td.Tag("age", td.Between(40, 45)),157			td.Tag("name", td.Re(`^Bob`))))158	before := time.Now()159	timeGot := map[string]time.Time{"created_at": time.Now()}160	checkOK(t, timeGot,161		td.JSON(`{"created_at": Between($1, $2)}`, before, time.Now()))162	checkOK(t, timeGot,163		td.JSON(`{"created_at": $1}`, td.Between(before, time.Now())))164	// Len165	checkOK(t, []int{1, 2, 3}, td.JSON(`Len(3)`))166	//167	// []byte168	checkOK(t, got,169		td.JSON([]byte(`{"name":"$name","age":$1,"gender":"male"}`),170			td.Tag("age", td.Between(40, 45)),171			td.Tag("name", td.Re(`^Bob`))))172	//173	// nil++174	checkOK(t, nil, td.JSON(`$1`, nil))175	checkOK(t, (*int)(nil), td.JSON(`$1`, td.Nil()))176	checkOK(t, nil, td.JSON(`$x`, td.Tag("x", nil)))177	checkOK(t, (*int)(nil), td.JSON(`$x`, td.Tag("x", nil)))178	checkOK(t, json.RawMessage(`{"foo": null}`), td.JSON(`{"foo": null}`))179	checkOK(t,180		json.RawMessage(`{"foo": null}`),181		td.JSON(`{"foo": $1}`, nil))182	checkOK(t,183		json.RawMessage(`{"foo": null}`),184		td.JSON(`{"foo": $1}`, td.Nil()))185	checkOK(t,186		json.RawMessage(`{"foo": null}`),187		td.JSON(`{"foo": $x}`, td.Tag("x", nil)))188	checkOK(t,189		json.RawMessage(`{"foo": null}`),190		td.JSON(`{"foo": $x}`, td.Tag("x", td.Nil())))191	//192	// Loading a file193	tmpDir := t.TempDir()194	filename := tmpDir + "/test.json"195	err := os.WriteFile(196		filename, []byte(`{"name":$name,"age":$1,"gender":$^NotEmpty}`), 0644)197	if err != nil {198		t.Fatal(err)199	}200	checkOK(t, got,201		td.JSON(filename,202			td.Tag("age", td.Between(40, 45)),203			td.Tag("name", td.Re(`^Bob`))))204	//205	// Reading (a file)206	tmpfile, err := os.Open(filename)207	if err != nil {208		t.Fatal(err)209	}210	checkOK(t, got,211		td.JSON(tmpfile,212			td.Tag("age", td.Between(40, 45)),213			td.Tag("name", td.Re(`^Bob`))))214	tmpfile.Close()215	//216	// Escaping $ in strings217	checkOK(t, "$test", td.JSON(`"$$test"`))218	//219	// Errors220	checkError(t, func() {}, td.JSON(`null`),221		expectedError{222			Message: mustBe("json.Marshal failed"),223			Summary: mustContain("json: unsupported type"),224		})225	checkError(t, map[string]string{"zip": "pipo"},226		td.All(td.JSON(`SuperMapOf({"zip":$1})`, "bingo")),227		expectedError{228			Path:    mustBe(`DATA`),229			Message: mustBe("compared (part 1 of 1)"),230			Got: mustBe(`(map[string]string) (len=1) {231 (string) (len=3) "zip": (string) (len=4) "pipo"232}`),233			Expected: mustBe(`JSON(SuperMapOf(map[string]interface {}{234       "zip": "bingo",235     }))`),236			Origin: &expectedError{237				Path:     mustBe(`DATA<All#1/1>["zip"]`),238				Message:  mustBe(`values differ`),239				Got:      mustBe(`"pipo"`),240				Expected: mustBe(`"bingo"`),241			},242		})243	//244	// Fatal errors245	checkError(t, "never tested",246		td.JSON("uNkNoWnFiLe.json"),247		expectedError{248			Message: mustBe("bad usage of JSON operator"),249			Path:    mustBe("DATA"),250			Summary: mustContain("JSON file uNkNoWnFiLe.json cannot be read: "),251		})252	checkError(t, "never tested",253		td.JSON(42),254		expectedError{255			Message: mustBe("bad usage of JSON operator"),256			Path:    mustBe("DATA"),257			Summary: mustBe("usage: JSON(STRING_JSON|STRING_FILENAME|[]byte|io.Reader, ...), but received int as 1st parameter"),258		})259	checkError(t, "never tested",260		td.JSON(errReader{}),261		expectedError{262			Message: mustBe("bad usage of JSON operator"),263			Path:    mustBe("DATA"),264			Summary: mustBe("JSON read error: an error occurred"),265		})266	checkError(t, "never tested",267		td.JSON(`pipo`),268		expectedError{269			Message: mustBe("bad usage of JSON operator"),270			Path:    mustBe("DATA"),271			Summary: mustContain("JSON unmarshal error: "),272		})273	checkError(t, "never tested",274		td.JSON(`[$foo]`,275			td.Tag("foo", td.Ignore()),276			td.Tag("foo", td.Ignore())),277		expectedError{278			Message: mustBe("bad usage of JSON operator"),279			Path:    mustBe("DATA"),280			Summary: mustBe(`2 params have the same tag "foo"`),281		})282	checkError(t, []int{42},283		td.JSON(`[$1]`, func() {}),284		expectedError{285			Message: mustBe("an error occurred while unmarshalling JSON into func()"),286			Path:    mustBe("DATA[0]"),287			Summary: mustBe("json: cannot unmarshal number into Go value of type func()"),288		})289	checkError(t, []int{42},290		td.JSON(`[$foo]`, td.Tag("foo", func() {})),291		expectedError{292			Message: mustBe("an error occurred while unmarshalling JSON into func()"),293			Path:    mustBe("DATA[0]"),294			Summary: mustBe("json: cannot unmarshal number into Go value of type func()"),295		})296	// numeric placeholders297	checkError(t, "never tested",298		td.JSON(`[1, "$123bad"]`),299		expectedError{300			Message: mustBe("bad usage of JSON operator"),301			Path:    mustBe("DATA"),302			Summary: mustBe(`JSON unmarshal error: invalid numeric placeholder at line 1:5 (pos 5)`),303		})304	checkError(t, "never tested",305		td.JSON(`[1, $000]`),306		expectedError{307			Message: mustBe("bad usage of JSON operator"),308			Path:    mustBe("DATA"),309			Summary: mustBe(`JSON unmarshal error: invalid numeric placeholder "$000", it should start at "$1" at line 1:4 (pos 4)`),310		})311	checkError(t, "never tested",312		td.JSON(`[1, $1]`),313		expectedError{314			Message: mustBe("bad usage of JSON operator"),315			Path:    mustBe("DATA"),316			Summary: mustBe(`JSON unmarshal error: numeric placeholder "$1", but no params given at line 1:4 (pos 4)`),317		})318	checkError(t, "never tested",319		td.JSON(`[1, 2, $3]`, td.Ignore()),320		expectedError{321			Message: mustBe("bad usage of JSON operator"),322			Path:    mustBe("DATA"),323			Summary: mustBe(`JSON unmarshal error: numeric placeholder "$3", but only one param given at line 1:7 (pos 7)`),324		})325	// $^Operator326	checkError(t, "never tested",327		td.JSON(`[1, $^bad%]`),328		expectedError{329			Message: mustBe("bad usage of JSON operator"),330			Path:    mustBe("DATA"),331			Summary: mustBe(`JSON unmarshal error: $^ must be followed by an operator name at line 1:4 (pos 4)`),332		})333	checkError(t, "never tested",334		td.JSON(`[1, "$^bad%"]`),335		expectedError{336			Message: mustBe("bad usage of JSON operator"),337			Path:    mustBe("DATA"),338			Summary: mustBe(`JSON unmarshal error: $^ must be followed by an operator name at line 1:5 (pos 5)`),339		})340	// named placeholders341	checkError(t, "never tested",342		td.JSON(`[343  1,344  "$bad%"345]`),346		expectedError{347			Message: mustBe("bad usage of JSON operator"),348			Path:    mustBe("DATA"),349			Summary: mustBe(`JSON unmarshal error: bad placeholder "$bad%" at line 3:3 (pos 10)`),350		})351	checkError(t, "never tested",352		td.JSON(`[1, $unknown]`),353		expectedError{354			Message: mustBe("bad usage of JSON operator"),355			Path:    mustBe("DATA"),356			Summary: mustBe(`JSON unmarshal error: unknown placeholder "$unknown" at line 1:4 (pos 4)`),357		})358	//359	// Stringification360	test.EqualStr(t, td.JSON(`1`).String(),361		`JSON(1)`)362	test.EqualStr(t, td.JSON(`[ 1, 2, 3 ]`).String(),363		`364JSON([365       1,366       2,367       3368     ])`[1:])369	test.EqualStr(t, td.JSON(` null `).String(), `JSON(null)`)370	test.EqualStr(t,371		td.JSON(`[ $1, $name, $2, Nil(), $nil, 26, Between(5, 6), Len(34), Len(Between(5, 6)), 28 ]`,372			td.Between(12, 20),373			"test",374			td.Tag("name", td.Code(func(s string) bool { return len(s) > 0 })),375			td.Tag("nil", nil),376			14,377		).String(),378		`379JSON([380       "$1" /* 12 ⤠got ⤠20 */,381       "$name" /* Code(func(string) bool) */,382       "test",383       nil,384       null,385       26,386       5.0 ⤠got ⤠6.0,387       len=34,388       len: 5.0 ⤠got ⤠6.0,389       28390     ])`[1:])391	test.EqualStr(t,392		td.JSON(`[ $1, $name, $2, $^Nil, $nil ]`,393			td.Between(12, 20),394			"test",395			td.Tag("name", td.Code(func(s string) bool { return len(s) > 0 })),396			td.Tag("nil", nil),397		).String(),398		`399JSON([400       "$1" /* 12 ⤠got ⤠20 */,401       "$name" /* Code(func(string) bool) */,402       "test",403       nil,404       null405     ])`[1:])406	test.EqualStr(t,407		td.JSON(`{"label": $value, "zip": $^NotZero}`,408			td.Tag("value", td.Bag(409				td.JSON(`{"name": $1,"age":$2,"surname":$3}`,410					td.HasPrefix("Bob"),411					td.Between(12, 24),412					"captain",413				),414				td.JSON(`{"name": $1}`, td.HasPrefix("Alice")),415			)),416		).String(),417		`418JSON({419       "label": "$value" /* Bag(JSON({420                                       "age": "$2" /* 12 ⤠got ⤠24 */,421                                       "name": "$1" /* HasPrefix("Bob") */,422                                       "surname": "captain"423                                     }),424                                JSON({425                                       "name": "$1" /* HasPrefix("Alice") */426                                     })) */,427       "zip": NotZero()428     })`[1:])429	test.EqualStr(t,430		td.JSON(`431{432  "label": {"name": HasPrefix("Bob"), "age": Between(12,24)},433  "zip":   NotZero()434}`).String(),435		`436JSON({437       "label": {438                  "age": 12.0 ⤠got ⤠24.0,439                  "name": HasPrefix("Bob")440                },441       "zip": NotZero()442     })`[1:])443	// Erroneous op444	test.EqualStr(t, td.JSON(`[`).String(), "JSON(<ERROR>)")445}446func TestJSONInside(t *testing.T) {447	// Between448	t.Run("Between", func(t *testing.T) {449		got := map[string]int{"val1": 1, "val2": 2}450		checkOK(t, got,451			td.JSON(`{"val1": Between(0, 2), "val2": Between(2, 3, "[[")}`))452		checkOK(t, got,453			td.JSON(`{"val1": Between(0, 2), "val2": Between(2, 3, "BoundsInOut")}`))454		for _, bounds := range []string{"[[", "BoundsInOut"} {455			checkError(t, got,456				td.JSON(`{"val1": Between(0, 2), "val2": Between(1, 2, $1)}`, bounds),457				expectedError{458					Message:  mustBe("values differ"),459					Path:     mustBe(`DATA["val2"]`),460					Got:      mustBe("2.0"),461					Expected: mustBe("1.0 ⤠got < 2.0"),462				})463		}464		checkOK(t, got,465			td.JSON(`{"val1": Between(1, 1), "val2": Between(2, 2, "[]")}`))466		checkOK(t, got,467			td.JSON(`{"val1": Between(1, 1), "val2": Between(2, 2, "BoundsInIn")}`))468		checkOK(t, got,469			td.JSON(`{"val1": Between(0, 1, "]]"), "val2": Between(1, 3, "][")}`))470		checkOK(t, got,471			td.JSON(`{"val1": Between(0, 1, "BoundsOutIn"), "val2": Between(1, 3, "BoundsOutOut")}`))472		for _, bounds := range []string{"]]", "BoundsOutIn"} {473			checkError(t, got,474				td.JSON(`{"val1": 1, "val2": Between(2, 3, $1)}`, bounds),475				expectedError{476					Message:  mustBe("values differ"),477					Path:     mustBe(`DATA["val2"]`),478					Got:      mustBe("2.0"),479					Expected: mustBe("2.0 < got ⤠3.0"),480				})481		}482		for _, bounds := range []string{"][", "BoundsOutOut"} {483			checkError(t, got,484				td.JSON(`{"val1": 1, "val2": Between(2, 3, $1)}`, bounds),485				expectedError{486					Message:  mustBe("values differ"),487					Path:     mustBe(`DATA["val2"]`),488					Got:      mustBe("2.0"),489					Expected: mustBe("2.0 < got < 3.0"),490				},491				"using bounds %q", bounds)492			checkError(t, got,493				td.JSON(`{"val1": 1, "val2": Between(1, 2, $1)}`, bounds),494				expectedError{495					Message:  mustBe("values differ"),496					Path:     mustBe(`DATA["val2"]`),497					Got:      mustBe("2.0"),498					Expected: mustBe("1.0 < got < 2.0"),499				},500				"using bounds %q", bounds)501		}502		// Bad 3rd parameter503		checkError(t, "never tested",504			td.JSON(`{505  "val2": Between(1, 2, "<>")506}`),507			expectedError{508				Message: mustBe("bad usage of JSON operator"),509				Path:    mustBe("DATA"),510				Summary: mustBe(`JSON unmarshal error: Between() bad 3rd parameter, use "[]", "[[", "]]" or "][" at line 2:10 (pos 12)`),511			})512		checkError(t, "never tested",513			td.JSON(`{514  "val2": Between(1, 2, 125)515}`),516			expectedError{517				Message: mustBe("bad usage of JSON operator"),518				Path:    mustBe("DATA"),519				Summary: mustBe(`JSON unmarshal error: Between() bad 3rd parameter, use "[]", "[[", "]]" or "][" at line 2:10 (pos 12)`),520			})521		checkError(t, "never tested",522			td.JSON(`{"val2": Between(1)}`),523			expectedError{524				Message: mustBe("bad usage of JSON operator"),525				Path:    mustBe("DATA"),526				Summary: mustBe(`JSON unmarshal error: Between() requires 2 or 3 parameters at line 1:9 (pos 9)`),527			})528		checkError(t, "never tested",529			td.JSON(`{"val2": Between(1,2,3,4)}`),530			expectedError{531				Message: mustBe("bad usage of JSON operator"),532				Path:    mustBe("DATA"),533				Summary: mustBe(`JSON unmarshal error: Between() requires 2 or 3 parameters at line 1:9 (pos 9)`),534			})535	})536	// N537	t.Run("N", func(t *testing.T) {538		got := map[string]float32{"val": 2.1}539		checkOK(t, got, td.JSON(`{"val": N(2.1)}`))540		checkOK(t, got, td.JSON(`{"val": N(2, 0.1)}`))541		checkError(t, "never tested",542			td.JSON(`{"val2": N()}`),543			expectedError{544				Message: mustBe("bad usage of JSON operator"),545				Path:    mustBe("DATA"),546				Summary: mustBe(`JSON unmarshal error: N() requires 1 or 2 parameters at line 1:9 (pos 9)`),547			})548		checkError(t, "never tested",549			td.JSON(`{"val2": N(1,2,3)}`),550			expectedError{551				Message: mustBe("bad usage of JSON operator"),552				Path:    mustBe("DATA"),553				Summary: mustBe(`JSON unmarshal error: N() requires 1 or 2 parameters at line 1:9 (pos 9)`),554			})555	})556	// Re557	t.Run("Re", func(t *testing.T) {558		got := map[string]string{"val": "Foo bar"}559		checkOK(t, got, td.JSON(`{"val": Re("^Foo")}`))560		checkOK(t, got, td.JSON(`{"val": Re("^(\\w+)", ["Foo"])}`))561		checkOK(t, got, td.JSON(`{"val": Re("^(\\w+)", Bag("Foo"))}`))562		checkError(t, "never tested",563			td.JSON(`{"val2": Re()}`),564			expectedError{565				Message: mustBe("bad usage of JSON operator"),566				Path:    mustBe("DATA"),567				Summary: mustBe(`JSON unmarshal error: Re() requires 1 or 2 parameters at line 1:9 (pos 9)`),568			})569		checkError(t, "never tested",570			td.JSON(`{"val2": Re(1,2,3)}`),571			expectedError{572				Message: mustBe("bad usage of JSON operator"),573				Path:    mustBe("DATA"),574				Summary: mustBe(`JSON unmarshal error: Re() requires 1 or 2 parameters at line 1:9 (pos 9)`),575			})576	})577	// SubMapOf578	t.Run("SubMapOf", func(t *testing.T) {579		got := []map[string]int{{"val1": 1, "val2": 2}}580		checkOK(t, got, td.JSON(`[ SubMapOf({"val1":1, "val2":2, "xxx": "yyy"}) ]`))581		checkError(t, "never tested",582			td.JSON(`[ SubMapOf() ]`),583			expectedError{584				Message: mustBe("bad usage of JSON operator"),585				Path:    mustBe("DATA"),586				Summary: mustBe(`JSON unmarshal error: SubMapOf() requires only one parameter at line 1:2 (pos 2)`),587			})588		checkError(t, "never tested",589			td.JSON(`[ SubMapOf(1, 2) ]`),590			expectedError{591				Message: mustBe("bad usage of JSON operator"),592				Path:    mustBe("DATA"),593				Summary: mustBe(`JSON unmarshal error: SubMapOf() requires only one parameter at line 1:2 (pos 2)`),594			})595	})596	// SuperMapOf597	t.Run("SuperMapOf", func(t *testing.T) {598		got := []map[string]int{{"val1": 1, "val2": 2}}599		checkOK(t, got, td.JSON(`[ SuperMapOf({"val1":1}) ]`))600		checkError(t, "never tested",601			td.JSON(`[ SuperMapOf() ]`),602			expectedError{603				Message: mustBe("bad usage of JSON operator"),604				Path:    mustBe("DATA"),605				Summary: mustBe(`JSON unmarshal error: SuperMapOf() requires only one parameter at line 1:2 (pos 2)`),606			})607		checkError(t, "never tested",608			td.JSON(`[ SuperMapOf(1, 2) ]`),609			expectedError{610				Message: mustBe("bad usage of JSON operator"),611				Path:    mustBe("DATA"),612				Summary: mustBe(`JSON unmarshal error: SuperMapOf() requires only one parameter at line 1:2 (pos 2)`),613			})614	})615	// errors616	t.Run("Errors", func(t *testing.T) {617		checkError(t, "never tested",618			td.JSON(`[ UnknownOp() ]`),619			expectedError{620				Message: mustBe("bad usage of JSON operator"),621				Path:    mustBe("DATA"),622				Summary: mustBe(`JSON unmarshal error: unknown operator UnknownOp() at line 1:2 (pos 2)`),623			})624		checkError(t, "never tested",625			td.JSON(`[ Catch() ]`),626			expectedError{627				Message: mustBe("bad usage of JSON operator"),628				Path:    mustBe("DATA"),629				Summary: mustBe(`JSON unmarshal error: Catch() is not usable in JSON() at line 1:2 (pos 2)`),630			})631		checkError(t, "never tested",632			td.JSON(`[ JSON() ]`),633			expectedError{634				Message: mustBe("bad usage of JSON operator"),635				Path:    mustBe("DATA"),636				Summary: mustBe(`JSON unmarshal error: JSON() is not usable in JSON(), use literal JSON instead at line 1:2 (pos 2)`),637			})638		checkError(t, "never tested",639			td.JSON(`[ All() ]`),640			expectedError{641				Message: mustBe("bad usage of JSON operator"),642				Path:    mustBe("DATA"),643				Summary: mustBe(`JSON unmarshal error: All() requires at least one parameter at line 1:2 (pos 2)`),644			})645		checkError(t, "never tested",646			td.JSON(`[ Empty(12) ]`),647			expectedError{648				Message: mustBe("bad usage of JSON operator"),649				Path:    mustBe("DATA"),650				Summary: mustBe(`JSON unmarshal error: Empty() requires no parameters at line 1:2 (pos 2)`),651			})652		checkError(t, "never tested",653			td.JSON(`[ HasPrefix() ]`),654			expectedError{655				Message: mustBe("bad usage of JSON operator"),656				Path:    mustBe("DATA"),657				Summary: mustBe(`JSON unmarshal error: HasPrefix() requires only one parameter at line 1:2 (pos 2)`),658			})659		checkError(t, "never tested",660			td.JSON(`[ JSONPointer(1, 2, 3) ]`),661			expectedError{662				Message: mustBe("bad usage of JSON operator"),663				Path:    mustBe("DATA"),664				Summary: mustBe(`JSON unmarshal error: JSONPointer() requires 2 parameters at line 1:2 (pos 2)`),665			})666		checkError(t, "never tested",667			td.JSON(`[ JSONPointer(1, 2) ]`),668			expectedError{669				Message: mustBe("bad usage of JSON operator"),670				Path:    mustBe("DATA"),671				Summary: mustBe(`JSON unmarshal error: JSONPointer() bad #1 parameter type: string required but float64 received at line 1:2 (pos 2)`),672			})673		// This one is not caught by JSON, but by Re itself, as the number674		// of parameters is correct675		checkError(t, json.RawMessage(`"never tested"`),676			td.JSON(`Re(1)`),677			expectedError{678				Message: mustBe("bad usage of Re operator"),679				Path:    mustBe("DATA"),680				Summary: mustBe(`usage: Re(STRING|*regexp.Regexp[, NON_NIL_CAPTURE]), but received float64 as 1st parameter`),681			})682	})683}684func TestJSONTypeBehind(t *testing.T) {685	equalTypes(t, td.JSON(`false`), true)686	equalTypes(t, td.JSON(`"foo"`), "")687	equalTypes(t, td.JSON(`42`), float64(0))688	equalTypes(t, td.JSON(`[1,2,3]`), ([]any)(nil))689	equalTypes(t, td.JSON(`{"a":12}`), (map[string]any)(nil))690	// operator at the root â delegate it TypeBehind() call691	equalTypes(t, td.JSON(`$1`, td.SuperMapOf(map[string]any{"x": 1}, nil)), (map[string]any)(nil))692	equalTypes(t, td.JSON(`SuperMapOf({"x":1})`), (map[string]any)(nil))693	equalTypes(t, td.JSON(`$1`, 123), 42)694	nullType := td.JSON(`null`).TypeBehind()695	if nullType != reflect.TypeOf((*any)(nil)).Elem() {696		t.Errorf("Failed test: got %s intead of interface {}", nullType)697	}698	// Erroneous op699	equalTypes(t, td.JSON(`[`), nil)700}701func TestSubJSONOf(t *testing.T) {702	type MyStruct struct {703		Name   string `json:"name"`704		Age    uint   `json:"age"`705		Gender string `json:"gender"`706	}707	//708	// struct709	//710	got := MyStruct{Name: "Bob", Age: 42, Gender: "male"}711	// No placeholder712	checkOK(t, got,713		td.SubJSONOf(`714{715  "name":    "Bob",716  "age":     42,717  "gender":  "male",718  "details": {  // â we don't want to test this field719    "city": "Test City",720    "zip":  666721  }722}`))723	// Numeric placeholders724	checkOK(t, got,725		td.SubJSONOf(`{"name":"$1","age":$2,"gender":$3,"details":{}}`,726			"Bob", 42, "male")) // raw values727	checkOK(t, got,728		td.SubJSONOf(`{"name":"$1","age":$2,"gender":$3,"details":{}}`,729			td.Re(`^Bob`),730			td.Between(40, 45),731			td.NotEmpty()))732	// Same using Flatten733	checkOK(t, got,734		td.SubJSONOf(`{"name":"$1","age":$2,"gender":$3,"details":{}}`,735			td.Re(`^Bob`),736			td.Flatten([]td.TestDeep{td.Between(40, 45), td.NotEmpty()}),737		))738	// Tag placeholders739	checkOK(t, got,740		td.SubJSONOf(741			`{"name":"$name","age":$age,"gender":"$gender","details":{}}`,742			td.Tag("name", td.Re(`^Bob`)),743			td.Tag("age", td.Between(40, 45)),744			td.Tag("gender", td.NotEmpty())))745	// Mixed placeholders + operator746	for _, op := range []string{747		"NotEmpty",748		"NotEmpty()",749		"$^NotEmpty",750		"$^NotEmpty()",751		`"$^NotEmpty"`,752		`"$^NotEmpty()"`,753		`r<$^NotEmpty>`,754		`r<$^NotEmpty()>`,755	} {756		checkOK(t, got,757			td.SubJSONOf(758				`{"name":"$name","age":$1,"gender":`+op+`,"details":{}}`,759				td.Tag("age", td.Between(40, 45)),760				td.Tag("name", td.Re(`^Bob`))),761			"using operator %s", op)762	}763	//764	// Errors765	checkError(t, func() {}, td.SubJSONOf(`{}`),766		expectedError{767			Message: mustBe("json.Marshal failed"),768			Summary: mustContain("json: unsupported type"),769		})770	for i, n := range []any{771		nil,772		(map[string]any)(nil),773		(map[string]bool)(nil),774		([]int)(nil),775	} {776		checkError(t, n, td.SubJSONOf(`{}`),777			expectedError{778				Message:  mustBe("values differ"),779				Got:      mustBe("null"),780				Expected: mustBe("non-null"),781			},782			"nil test #%d", i)783	}784	//785	// Fatal errors786	checkError(t, "never tested",787		td.SubJSONOf(`[1, "$123bad"]`),788		expectedError{789			Message: mustBe("bad usage of SubJSONOf operator"),790			Path:    mustBe("DATA"),791			Summary: mustBe(`JSON unmarshal error: invalid numeric placeholder at line 1:5 (pos 5)`),792		})793	checkError(t, "never tested",794		td.SubJSONOf(`[1, $000]`),795		expectedError{796			Message: mustBe("bad usage of SubJSONOf operator"),797			Path:    mustBe("DATA"),798			Summary: mustBe(`JSON unmarshal error: invalid numeric placeholder "$000", it should start at "$1" at line 1:4 (pos 4)`),799		})800	checkError(t, "never tested",801		td.SubJSONOf(`[1, $1]`),802		expectedError{803			Message: mustBe("bad usage of SubJSONOf operator"),804			Path:    mustBe("DATA"),805			Summary: mustBe(`JSON unmarshal error: numeric placeholder "$1", but no params given at line 1:4 (pos 4)`),806		})807	checkError(t, "never tested",808		td.SubJSONOf(`[1, 2, $3]`, td.Ignore()),809		expectedError{810			Message: mustBe("bad usage of SubJSONOf operator"),811			Path:    mustBe("DATA"),812			Summary: mustBe(`JSON unmarshal error: numeric placeholder "$3", but only one param given at line 1:7 (pos 7)`),813		})814	// $^Operator815	checkError(t, "never tested",816		td.SubJSONOf(`[1, $^bad%]`),817		expectedError{818			Message: mustBe("bad usage of SubJSONOf operator"),819			Path:    mustBe("DATA"),820			Summary: mustBe(`JSON unmarshal error: $^ must be followed by an operator name at line 1:4 (pos 4)`),821		})822	checkError(t, "never tested",823		td.SubJSONOf(`[1, "$^bad%"]`),824		expectedError{825			Message: mustBe("bad usage of SubJSONOf operator"),826			Path:    mustBe("DATA"),827			Summary: mustBe(`JSON unmarshal error: $^ must be followed by an operator name at line 1:5 (pos 5)`),828		})829	// named placeholders830	checkError(t, "never tested",831		td.SubJSONOf(`[1, "$bad%"]`),832		expectedError{833			Message: mustBe("bad usage of SubJSONOf operator"),834			Path:    mustBe("DATA"),835			Summary: mustBe(`JSON unmarshal error: bad placeholder "$bad%" at line 1:5 (pos 5)`),836		})837	checkError(t, "never tested",838		td.SubJSONOf(`[1, $unknown]`),839		expectedError{840			Message: mustBe("bad usage of SubJSONOf operator"),841			Path:    mustBe("DATA"),842			Summary: mustBe(`JSON unmarshal error: unknown placeholder "$unknown" at line 1:4 (pos 4)`),843		})844	checkError(t, "never tested",845		td.SubJSONOf("null"),846		expectedError{847			Message: mustBe("bad usage of SubJSONOf operator"),848			Path:    mustBe("DATA"),849			Summary: mustBe("SubJSONOf() only accepts JSON objects {â¦}"),850		})851	//852	// Stringification853	test.EqualStr(t, td.SubJSONOf(`{}`).String(), `SubJSONOf({})`)854	test.EqualStr(t, td.SubJSONOf(`{"foo":1, "bar":2}`).String(),855		`856SubJSONOf({857            "bar": 2,858            "foo": 1859          })`[1:])860	test.EqualStr(t,861		td.SubJSONOf(`{"label": $value, "zip": $^NotZero}`,862			td.Tag("value", td.Bag(863				td.SubJSONOf(`{"name": $1,"age":$2}`,864					td.HasPrefix("Bob"),865					td.Between(12, 24),866				),867				td.SubJSONOf(`{"name": $1}`, td.HasPrefix("Alice")),868			)),869		).String(),870		`871SubJSONOf({872            "label": "$value" /* Bag(SubJSONOf({873                                                 "age": "$2" /* 12 ⤠got ⤠24 */,874                                                 "name": "$1" /* HasPrefix("Bob") */875                                               }),876                                     SubJSONOf({877                                                 "name": "$1" /* HasPrefix("Alice") */878                                               })) */,879            "zip": NotZero()880          })`[1:])881	// Erroneous op882	test.EqualStr(t, td.SubJSONOf(`123`).String(), "SubJSONOf(<ERROR>)")883}884func TestSubJSONOfTypeBehind(t *testing.T) {885	equalTypes(t, td.SubJSONOf(`{"a":12}`), (map[string]any)(nil))886	// Erroneous op887	equalTypes(t, td.SubJSONOf(`123`), nil)888}889func TestSuperJSONOf(t *testing.T) {890	type MyStruct struct {891		Name    string `json:"name"`892		Age     uint   `json:"age"`893		Gender  string `json:"gender"`894		Details string `json:"details"`895	}896	//897	// struct898	//899	got := MyStruct{Name: "Bob", Age: 42, Gender: "male", Details: "Nice"}900	// No placeholder901	checkOK(t, got, td.SuperJSONOf(`{"name": "Bob"}`))902	// Numeric placeholders903	checkOK(t, got,904		td.SuperJSONOf(`{"name":"$1","age":$2}`,905			"Bob", 42)) // raw values906	checkOK(t, got,907		td.SuperJSONOf(`{"name":"$1","age":$2}`,908			td.Re(`^Bob`),909			td.Between(40, 45)))910	// Same using Flatten911	checkOK(t, got,912		td.SuperJSONOf(`{"name":"$1","age":$2}`,913			td.Flatten([]td.TestDeep{td.Re(`^Bob`), td.Between(40, 45)}),914		))915	// Tag placeholders916	checkOK(t, got,917		td.SuperJSONOf(`{"name":"$name","gender":"$gender"}`,918			td.Tag("name", td.Re(`^Bob`)),919			td.Tag("gender", td.NotEmpty())))920	// Mixed placeholders + operator921	for _, op := range []string{922		"NotEmpty",923		"NotEmpty()",924		"$^NotEmpty",925		"$^NotEmpty()",926		`"$^NotEmpty"`,927		`"$^NotEmpty()"`,928		`r<$^NotEmpty>`,929		`r<$^NotEmpty()>`,930	} {931		checkOK(t, got,932			td.SuperJSONOf(933				`{"name":"$name","age":$1,"gender":`+op+`}`,934				td.Tag("age", td.Between(40, 45)),935				td.Tag("name", td.Re(`^Bob`))),936			"using operator %s", op)937	}938	// â¦with commentsâ¦939	checkOK(t, got,940		td.SuperJSONOf(`941// This should be the JSON representation of MyStruct struct942{943  // A person:944  "name":   "$name",   // The name of this person945  "age":    $1,        /* The age of this person:946                          - placeholder unquoted, but could be without947                            any change948                          - to demonstrate a multi-lines comment */949  "gender": $^NotEmpty // Shortcut to operator NotEmpty950}`,951			td.Tag("age", td.Between(40, 45)),952			td.Tag("name", td.Re(`^Bob`))))953	//954	// Errors955	checkError(t, func() {}, td.SuperJSONOf(`{}`),956		expectedError{957			Message: mustBe("json.Marshal failed"),958			Summary: mustContain("json: unsupported type"),959		})960	for i, n := range []any{961		nil,962		(map[string]any)(nil),963		(map[string]bool)(nil),964		([]int)(nil),965	} {966		checkError(t, n, td.SuperJSONOf(`{}`),967			expectedError{968				Message:  mustBe("values differ"),969				Got:      mustBe("null"),970				Expected: mustBe("non-null"),971			},972			"nil test #%d", i)973	}974	//975	// Fatal errors976	checkError(t, "never tested",977		td.SuperJSONOf(`[1, "$123bad"]`),978		expectedError{979			Message: mustBe("bad usage of SuperJSONOf operator"),980			Path:    mustBe("DATA"),981			Summary: mustBe(`JSON unmarshal error: invalid numeric placeholder at line 1:5 (pos 5)`),982		})983	checkError(t, "never tested",984		td.SuperJSONOf(`[1, $000]`),985		expectedError{986			Message: mustBe("bad usage of SuperJSONOf operator"),987			Path:    mustBe("DATA"),988			Summary: mustBe(`JSON unmarshal error: invalid numeric placeholder "$000", it should start at "$1" at line 1:4 (pos 4)`),989		})990	checkError(t, "never tested",991		td.SuperJSONOf(`[1, $1]`),992		expectedError{993			Message: mustBe("bad usage of SuperJSONOf operator"),994			Path:    mustBe("DATA"),995			Summary: mustBe(`JSON unmarshal error: numeric placeholder "$1", but no params given at line 1:4 (pos 4)`),996		})997	checkError(t, "never tested",998		td.SuperJSONOf(`[1, 2, $3]`, td.Ignore()),999		expectedError{1000			Message: mustBe("bad usage of SuperJSONOf operator"),1001			Path:    mustBe("DATA"),1002			Summary: mustBe(`JSON unmarshal error: numeric placeholder "$3", but only one param given at line 1:7 (pos 7)`),1003		})1004	// $^Operator1005	checkError(t, "never tested",1006		td.SuperJSONOf(`[1, $^bad%]`),1007		expectedError{1008			Message: mustBe("bad usage of SuperJSONOf operator"),1009			Path:    mustBe("DATA"),1010			Summary: mustBe(`JSON unmarshal error: $^ must be followed by an operator name at line 1:4 (pos 4)`),1011		})1012	checkError(t, "never tested",1013		td.SuperJSONOf(`[1, "$^bad%"]`),1014		expectedError{1015			Message: mustBe("bad usage of SuperJSONOf operator"),1016			Path:    mustBe("DATA"),1017			Summary: mustBe(`JSON unmarshal error: $^ must be followed by an operator name at line 1:5 (pos 5)`),1018		})1019	// named placeholders1020	checkError(t, "never tested",1021		td.SuperJSONOf(`[1, "$bad%"]`),1022		expectedError{1023			Message: mustBe("bad usage of SuperJSONOf operator"),1024			Path:    mustBe("DATA"),1025			Summary: mustBe(`JSON unmarshal error: bad placeholder "$bad%" at line 1:5 (pos 5)`),1026		})1027	checkError(t, "never tested",1028		td.SuperJSONOf(`[1, $unknown]`),1029		expectedError{1030			Message: mustBe("bad usage of SuperJSONOf operator"),1031			Path:    mustBe("DATA"),1032			Summary: mustBe(`JSON unmarshal error: unknown placeholder "$unknown" at line 1:4 (pos 4)`),1033		})1034	checkError(t, "never tested",1035		td.SuperJSONOf("null"),1036		expectedError{1037			Message: mustBe("bad usage of SuperJSONOf operator"),1038			Path:    mustBe("DATA"),1039			Summary: mustBe("SuperJSONOf() only accepts JSON objects {â¦}"),1040		})1041	//1042	// Stringification1043	test.EqualStr(t, td.SuperJSONOf(`{}`).String(), `SuperJSONOf({})`)1044	test.EqualStr(t, td.SuperJSONOf(`{"foo":1, "bar":2}`).String(),1045		`1046SuperJSONOf({1047              "bar": 2,1048              "foo": 11049            })`[1:])1050	test.EqualStr(t,1051		td.SuperJSONOf(`{"label": $value, "zip": $^NotZero}`,1052			td.Tag("value", td.Bag(1053				td.SuperJSONOf(`{"name": $1,"age":$2}`,1054					td.HasPrefix("Bob"),1055					td.Between(12, 24),1056				),1057				td.SuperJSONOf(`{"name": $1}`, td.HasPrefix("Alice")),1058			)),1059		).String(),1060		`1061SuperJSONOf({1062              "label": "$value" /* Bag(SuperJSONOf({1063                                                     "age": "$2" /* 12 ⤠got ⤠24 */,1064                                                     "name": "$1" /* HasPrefix("Bob") */1065                                                   }),1066                                       SuperJSONOf({1067                                                     "name": "$1" /* HasPrefix("Alice") */1068                                                   })) */,1069              "zip": NotZero()...td_between_test.go
Source:td_between_test.go  
...11	"time"12	"github.com/maxatome/go-testdeep/internal/test"13	"github.com/maxatome/go-testdeep/td"14)15func TestBetween(t *testing.T) {16	checkOK(t, 12, td.Between(9, 13))17	checkOK(t, 12, td.Between(13, 9))18	checkOK(t, 12, td.Between(9, 12, td.BoundsOutIn))19	checkOK(t, 12, td.Between(12, 13, td.BoundsInOut))20	checkError(t, 10, td.Between(10, 15, td.BoundsOutIn),21		expectedError{22			Message:  mustBe("values differ"),23			Path:     mustBe("DATA"),24			Got:      mustBe("10"),25			Expected: mustBe("10 < got ⤠15"),26		})27	checkError(t, 10, td.Between(10, 15, td.BoundsOutOut),28		expectedError{29			Message:  mustBe("values differ"),30			Path:     mustBe("DATA"),31			Got:      mustBe("10"),32			Expected: mustBe("10 < got < 15"),33		})34	checkError(t, 15, td.Between(10, 15, td.BoundsInOut),35		expectedError{36			Message:  mustBe("values differ"),37			Path:     mustBe("DATA"),38			Got:      mustBe("15"),39			Expected: mustBe("10 ⤠got < 15"),40		})41	checkError(t, 15, td.Between(10, 15, td.BoundsOutOut),42		expectedError{43			Message:  mustBe("values differ"),44			Path:     mustBe("DATA"),45			Got:      mustBe("15"),46			Expected: mustBe("10 < got < 15"),47		})48	checkError(t, 15, td.Between(uint(10), uint(15), td.BoundsOutOut),49		expectedError{50			Message:  mustBe("type mismatch"),51			Path:     mustBe("DATA"),52			Got:      mustBe("int"),53			Expected: mustBe("uint"),54		})55	checkOK(t, uint16(12), td.Between(uint16(9), uint16(13)))56	checkOK(t, uint16(12), td.Between(uint16(13), uint16(9)))57	checkOK(t, uint16(12),58		td.Between(uint16(9), uint16(12), td.BoundsOutIn))59	checkOK(t, uint16(12),60		td.Between(uint16(12), uint16(13), td.BoundsInOut))61	checkOK(t, 12.1, td.Between(9.5, 13.1))62	checkOK(t, 12.1, td.Between(13.1, 9.5))63	checkOK(t, 12.1, td.Between(9.5, 12.1, td.BoundsOutIn))64	checkOK(t, 12.1, td.Between(12.1, 13.1, td.BoundsInOut))65	checkOK(t, "abc", td.Between("aaa", "bbb"))66	checkOK(t, "abc", td.Between("bbb", "aaa"))67	checkOK(t, "abc", td.Between("aaa", "abc", td.BoundsOutIn))68	checkOK(t, "abc", td.Between("abc", "bbb", td.BoundsInOut))69	checkOK(t, 12*time.Hour, td.Between(60*time.Second, 24*time.Hour))70	//71	// Bad usage72	checkError(t, "never tested",73		td.Between([]byte("test"), []byte("test")),74		expectedError{75			Message: mustBe("bad usage of Between operator"),76			Path:    mustBe("DATA"),77			Summary: mustBe("usage: Between(NUM|STRING|TIME, NUM|STRING|TIME/DURATION[, BOUNDS_KIND]), but received []uint8 (slice) as 1st parameter"),78		})79	checkError(t, "never tested",80		td.Between(12, "test"),81		expectedError{82			Message: mustBe("bad usage of Between operator"),83			Path:    mustBe("DATA"),84			Summary: mustBe("Between(FROM, TO): FROM and TO must have the same type: int â  string"),85		})86	checkError(t, "never tested",87		td.Between("test", 12),88		expectedError{89			Message: mustBe("bad usage of Between operator"),90			Path:    mustBe("DATA"),91			Summary: mustBe("Between(FROM, TO): FROM and TO must have the same type: string â  int"),92		})93	checkError(t, "never tested",94		td.Between(1, 2, td.BoundsInIn, td.BoundsInOut),95		expectedError{96			Message: mustBe("bad usage of Between operator"),97			Path:    mustBe("DATA"),98			Summary: mustBe("usage: Between(NUM|STRING|TIME, NUM|STRING|TIME/DURATION[, BOUNDS_KIND]), too many parameters"),99		})100	type notTime struct{}101	checkError(t, "never tested",102		td.Between(notTime{}, notTime{}),103		expectedError{104			Message: mustBe("bad usage of Between operator"),105			Path:    mustBe("DATA"),106			Summary: mustBe("usage: Between(NUM|STRING|TIME, NUM|STRING|TIME/DURATION[, BOUNDS_KIND]), but received td_test.notTime (struct) as 1st parameter"),107		})108	// Erroneous op109	test.EqualStr(t, td.Between("test", 12).String(), "Between(<ERROR>)")110}111func TestN(t *testing.T) {112	//113	// Unsigned114	checkOK(t, uint(12), td.N(uint(12)))115	checkOK(t, uint(11), td.N(uint(12), uint(1)))116	checkOK(t, uint(13), td.N(uint(12), uint(1)))117	checkError(t, 10, td.N(uint(12), uint(1)),118		expectedError{119			Message:  mustBe("type mismatch"),120			Path:     mustBe("DATA"),121			Got:      mustBe("int"),122			Expected: mustBe("uint"),123		})124	checkOK(t, uint8(12), td.N(uint8(12)))125	checkOK(t, uint8(11), td.N(uint8(12), uint8(1)))126	checkOK(t, uint8(13), td.N(uint8(12), uint8(1)))127	checkError(t, 10, td.N(uint8(12), uint8(1)),128		expectedError{129			Message:  mustBe("type mismatch"),130			Path:     mustBe("DATA"),131			Got:      mustBe("int"),132			Expected: mustBe("uint8"),133		})134	checkOK(t, uint16(12), td.N(uint16(12)))135	checkOK(t, uint16(11), td.N(uint16(12), uint16(1)))136	checkOK(t, uint16(13), td.N(uint16(12), uint16(1)))137	checkError(t, 10, td.N(uint16(12), uint16(1)),138		expectedError{139			Message:  mustBe("type mismatch"),140			Path:     mustBe("DATA"),141			Got:      mustBe("int"),142			Expected: mustBe("uint16"),143		})144	checkOK(t, uint32(12), td.N(uint32(12)))145	checkOK(t, uint32(11), td.N(uint32(12), uint32(1)))146	checkOK(t, uint32(13), td.N(uint32(12), uint32(1)))147	checkError(t, 10, td.N(uint32(12), uint32(1)),148		expectedError{149			Message:  mustBe("type mismatch"),150			Path:     mustBe("DATA"),151			Got:      mustBe("int"),152			Expected: mustBe("uint32"),153		})154	checkOK(t, uint64(12), td.N(uint64(12)))155	checkOK(t, uint64(11), td.N(uint64(12), uint64(1)))156	checkOK(t, uint64(13), td.N(uint64(12), uint64(1)))157	checkError(t, 10, td.N(uint64(12), uint64(1)),158		expectedError{159			Message:  mustBe("type mismatch"),160			Path:     mustBe("DATA"),161			Got:      mustBe("int"),162			Expected: mustBe("uint64"),163		})164	checkOK(t, uint64(math.MaxUint64),165		td.N(uint64(math.MaxUint64), uint64(2)))166	checkError(t, uint64(0), td.N(uint64(math.MaxUint64), uint64(2)),167		expectedError{168			Message: mustBe("values differ"),169			Path:    mustBe("DATA"),170			Got:     mustBe("(uint64) 0"),171			Expected: mustBe(fmt.Sprintf("(uint64) %v ⤠got ⤠(uint64) %v",172				uint64(math.MaxUint64)-2, uint64(math.MaxUint64))),173		})174	checkOK(t, uint64(0), td.N(uint64(0), uint64(2)))175	checkError(t, uint64(math.MaxUint64), td.N(uint64(0), uint64(2)),176		expectedError{177			Message:  mustBe("values differ"),178			Path:     mustBe("DATA"),179			Got:      mustBe(fmt.Sprintf("(uint64) %v", uint64(math.MaxUint64))),180			Expected: mustBe("(uint64) 0 ⤠got ⤠(uint64) 2"),181		})182	//183	// Signed184	checkOK(t, 12, td.N(12))185	checkOK(t, 11, td.N(12, 1))186	checkOK(t, 13, td.N(12, 1))187	checkError(t, 10, td.N(12, 1),188		expectedError{189			Message:  mustBe("values differ"),190			Path:     mustBe("DATA"),191			Got:      mustBe("10"),192			Expected: mustBe("11 ⤠got ⤠13"),193		})194	checkError(t, 10, td.N(12, 0),195		expectedError{196			Message:  mustBe("values differ"),197			Path:     mustBe("DATA"),198			Got:      mustBe("10"),199			Expected: mustBe("12 ⤠got ⤠12"),200		})201	checkOK(t, int8(12), td.N(int8(12)))202	checkOK(t, int8(11), td.N(int8(12), int8(1)))203	checkOK(t, int8(13), td.N(int8(12), int8(1)))204	checkError(t, 10, td.N(int8(12), int8(1)),205		expectedError{206			Message:  mustBe("type mismatch"),207			Path:     mustBe("DATA"),208			Got:      mustBe("int"),209			Expected: mustBe("int8"),210		})211	checkOK(t, int16(12), td.N(int16(12)))212	checkOK(t, int16(11), td.N(int16(12), int16(1)))213	checkOK(t, int16(13), td.N(int16(12), int16(1)))214	checkError(t, 10, td.N(int16(12), int16(1)),215		expectedError{216			Message:  mustBe("type mismatch"),217			Path:     mustBe("DATA"),218			Got:      mustBe("int"),219			Expected: mustBe("int16"),220		})221	checkOK(t, int32(12), td.N(int32(12)))222	checkOK(t, int32(11), td.N(int32(12), int32(1)))223	checkOK(t, int32(13), td.N(int32(12), int32(1)))224	checkError(t, 10, td.N(int32(12), int32(1)),225		expectedError{226			Message:  mustBe("type mismatch"),227			Path:     mustBe("DATA"),228			Got:      mustBe("int"),229			Expected: mustBe("int32"),230		})231	checkOK(t, int64(12), td.N(int64(12)))232	checkOK(t, int64(11), td.N(int64(12), int64(1)))233	checkOK(t, int64(13), td.N(int64(12), int64(1)))234	checkError(t, 10, td.N(int64(12), int64(1)),235		expectedError{236			Message:  mustBe("type mismatch"),237			Path:     mustBe("DATA"),238			Got:      mustBe("int"),239			Expected: mustBe("int64"),240		})241	checkOK(t, int64(math.MaxInt64), td.N(int64(math.MaxInt64), int64(2)))242	checkError(t, int64(0), td.N(int64(math.MaxInt64), int64(2)),243		expectedError{244			Message: mustBe("values differ"),245			Path:    mustBe("DATA"),246			Got:     mustBe("(int64) 0"),247			Expected: mustBe(fmt.Sprintf("(int64) %v ⤠got ⤠(int64) %v",248				int64(math.MaxInt64)-2, int64(math.MaxInt64))),249		})250	checkOK(t, int64(math.MinInt64), td.N(int64(math.MinInt64), int64(2)))251	checkError(t, int64(0), td.N(int64(math.MinInt64), int64(2)),252		expectedError{253			Message: mustBe("values differ"),254			Path:    mustBe("DATA"),255			Got:     mustBe("(int64) 0"),256			Expected: mustBe(fmt.Sprintf("(int64) %v ⤠got ⤠(int64) %v",257				int64(math.MinInt64), int64(math.MinInt64)+2)),258		})259	//260	// Float261	checkOK(t, 12.1, td.N(12.1))262	checkOK(t, 11.9, td.N(12.0, 0.1))263	checkOK(t, 12.1, td.N(12.0, 0.1))264	checkError(t, 11.8, td.N(12.0, 0.1),265		expectedError{266			Message:  mustBe("values differ"),267			Path:     mustBe("DATA"),268			Got:      mustBe("11.8"),269			Expected: mustBe("11.9 ⤠got ⤠12.1"),270		})271	checkOK(t, float32(12.1), td.N(float32(12.1)))272	checkOK(t, float32(11.9), td.N(float32(12), float32(0.1)))273	checkOK(t, float32(12.1), td.N(float32(12), float32(0.1)))274	checkError(t, 11.8, td.N(float32(12), float32(0.1)),275		expectedError{276			Message:  mustBe("type mismatch"),277			Path:     mustBe("DATA"),278			Got:      mustBe("float64"),279			Expected: mustBe("float32"),280		})281	floatTol := 10e304282	checkOK(t, float64(math.MaxFloat64),283		td.N(float64(math.MaxFloat64), floatTol))284	checkError(t, float64(0), td.N(float64(math.MaxFloat64), floatTol),285		expectedError{286			Message: mustBe("values differ"),287			Path:    mustBe("DATA"),288			Got:     mustBe("0.0"),289			Expected: mustBe(fmt.Sprintf("%v ⤠got ⤠+Inf",290				float64(math.MaxFloat64)-floatTol)),291		})292	checkOK(t, -float64(math.MaxFloat64),293		td.N(-float64(math.MaxFloat64), float64(2)))294	checkError(t, float64(0), td.N(-float64(math.MaxFloat64), floatTol),295		expectedError{296			Message: mustBe("values differ"),297			Path:    mustBe("DATA"),298			Got:     mustBe("0.0"),299			Expected: mustBe(fmt.Sprintf("-Inf ⤠got ⤠%v",300				-float64(math.MaxFloat64)+floatTol)),301		})302	//303	// Bad usage304	checkError(t, "never tested",305		td.N("test"),306		expectedError{307			Message: mustBe("bad usage of N operator"),308			Path:    mustBe("DATA"),309			Summary: mustBe("usage: N({,U}INT{,8,16,32,64}|FLOAT{32,64}[, TOLERANCE]), but received string as 1st parameter"),310		})311	checkError(t, "never tested",312		td.N(10, 1, 2),313		expectedError{314			Message: mustBe("bad usage of N operator"),315			Path:    mustBe("DATA"),316			Summary: mustBe("usage: N({,U}INT{,8,16,32,64}|FLOAT{32,64}[, TOLERANCE]), too many parameters"),317		})318	checkError(t, "never tested",319		td.N(10, "test"),320		expectedError{321			Message: mustBe("bad usage of N operator"),322			Path:    mustBe("DATA"),323			Summary: mustBe("N(NUM, TOLERANCE): NUM and TOLERANCE must have the same type: int â  string"),324		})325	// Erroneous op326	test.EqualStr(t, td.N(10, 1, 2).String(), "N(<ERROR>)")327}328func TestLGt(t *testing.T) {329	checkOK(t, 12, td.Gt(11))330	checkOK(t, 12, td.Gte(12))331	checkOK(t, 12, td.Lt(13))332	checkOK(t, 12, td.Lte(12))333	checkOK(t, uint16(12), td.Gt(uint16(11)))334	checkOK(t, uint16(12), td.Gte(uint16(12)))335	checkOK(t, uint16(12), td.Lt(uint16(13)))336	checkOK(t, uint16(12), td.Lte(uint16(12)))337	checkOK(t, 12.3, td.Gt(12.2))338	checkOK(t, 12.3, td.Gte(12.3))339	checkOK(t, 12.3, td.Lt(12.4))340	checkOK(t, 12.3, td.Lte(12.3))341	checkOK(t, "abc", td.Gt("abb"))342	checkOK(t, "abc", td.Gte("abc"))343	checkOK(t, "abc", td.Lt("abd"))344	checkOK(t, "abc", td.Lte("abc"))345	checkError(t, 12, td.Gt(12),346		expectedError{347			Message:  mustBe("values differ"),348			Path:     mustBe("DATA"),349			Got:      mustBe("12"),350			Expected: mustBe("> 12"),351		})352	checkError(t, 12, td.Lt(12),353		expectedError{354			Message:  mustBe("values differ"),355			Path:     mustBe("DATA"),356			Got:      mustBe("12"),357			Expected: mustBe("< 12"),358		})359	checkError(t, 12, td.Gte(13),360		expectedError{361			Message:  mustBe("values differ"),362			Path:     mustBe("DATA"),363			Got:      mustBe("12"),364			Expected: mustBe("⥠13"),365		})366	checkError(t, 12, td.Lte(11),367		expectedError{368			Message:  mustBe("values differ"),369			Path:     mustBe("DATA"),370			Got:      mustBe("12"),371			Expected: mustBe("⤠11"),372		})373	checkError(t, "abc", td.Gt("abc"),374		expectedError{375			Message:  mustBe("values differ"),376			Path:     mustBe("DATA"),377			Got:      mustBe(`"abc"`),378			Expected: mustBe(`> "abc"`),379		})380	checkError(t, "abc", td.Lt("abc"),381		expectedError{382			Message:  mustBe("values differ"),383			Path:     mustBe("DATA"),384			Got:      mustBe(`"abc"`),385			Expected: mustBe(`< "abc"`),386		})387	checkError(t, "abc", td.Gte("abd"),388		expectedError{389			Message:  mustBe("values differ"),390			Path:     mustBe("DATA"),391			Got:      mustBe(`"abc"`),392			Expected: mustBe(`⥠"abd"`),393		})394	checkError(t, "abc", td.Lte("abb"),395		expectedError{396			Message:  mustBe("values differ"),397			Path:     mustBe("DATA"),398			Got:      mustBe(`"abc"`),399			Expected: mustBe(`⤠"abb"`),400		})401	gotDate := time.Date(2018, time.March, 4, 1, 2, 3, 0, time.UTC)402	expectedDate := gotDate403	checkOK(t, gotDate, td.Gte(expectedDate))404	checkOK(t, gotDate, td.Lte(expectedDate))405	checkError(t, gotDate, td.Gt(expectedDate),406		expectedError{407			Message:  mustBe("values differ"),408			Path:     mustBe("DATA"),409			Got:      mustBe("(time.Time) 2018-03-04 01:02:03 +0000 UTC"),410			Expected: mustBe("> (time.Time) 2018-03-04 01:02:03 +0000 UTC"),411		})412	checkError(t, gotDate, td.Lt(expectedDate),413		expectedError{414			Message:  mustBe("values differ"),415			Path:     mustBe("DATA"),416			Got:      mustBe("(time.Time) 2018-03-04 01:02:03 +0000 UTC"),417			Expected: mustBe("< (time.Time) 2018-03-04 01:02:03 +0000 UTC"),418		})419	//420	// Bad usage421	checkError(t, "never tested",422		td.Gt([]byte("test")),423		expectedError{424			Message: mustBe("bad usage of Gt operator"),425			Path:    mustBe("DATA"),426			Summary: mustBe("usage: Gt(NUM|STRING|TIME), but received []uint8 (slice) as 1st parameter"),427		})428	checkError(t, "never tested",429		td.Gte([]byte("test")),430		expectedError{431			Message: mustBe("bad usage of Gte operator"),432			Path:    mustBe("DATA"),433			Summary: mustBe("usage: Gte(NUM|STRING|TIME), but received []uint8 (slice) as 1st parameter"),434		})435	checkError(t, "never tested",436		td.Lt([]byte("test")),437		expectedError{438			Message: mustBe("bad usage of Lt operator"),439			Path:    mustBe("DATA"),440			Summary: mustBe("usage: Lt(NUM|STRING|TIME), but received []uint8 (slice) as 1st parameter"),441		})442	checkError(t, "never tested",443		td.Lte([]byte("test")),444		expectedError{445			Message: mustBe("bad usage of Lte operator"),446			Path:    mustBe("DATA"),447			Summary: mustBe("usage: Lte(NUM|STRING|TIME), but received []uint8 (slice) as 1st parameter"),448		})449	// Erroneous op450	test.EqualStr(t, td.Gt([]byte("test")).String(), "Gt(<ERROR>)")451	test.EqualStr(t, td.Gte([]byte("test")).String(), "Gte(<ERROR>)")452	test.EqualStr(t, td.Lt([]byte("test")).String(), "Lt(<ERROR>)")453	test.EqualStr(t, td.Lte([]byte("test")).String(), "Lte(<ERROR>)")454}455func TestBetweenTime(t *testing.T) {456	type MyTime time.Time457	now := time.Now()458	checkOK(t, now, td.Between(now, now))459	checkOK(t, now, td.Between(now.Add(-time.Second), now.Add(time.Second)))460	checkOK(t, now, td.Between(now.Add(time.Second), now.Add(-time.Second)))461	// (TIME, DURATION)462	checkOK(t, now, td.Between(now.Add(-time.Second), 2*time.Second))463	checkOK(t, now, td.Between(now.Add(time.Second), -2*time.Second))464	checkOK(t, MyTime(now),465		td.Between(466			MyTime(now.Add(-time.Second)),467			MyTime(now.Add(time.Second))))468	// (TIME, DURATION)469	checkOK(t, MyTime(now),470		td.Between(471			MyTime(now.Add(-time.Second)),472			2*time.Second))473	checkOK(t, MyTime(now),474		td.Between(475			MyTime(now.Add(time.Second)),476			-2*time.Second))477	// Lax mode478	checkOK(t, MyTime(now),479		td.Lax(td.Between(480			now.Add(time.Second),481			now.Add(-time.Second))))482	checkOK(t, now,483		td.Lax(td.Between(484			MyTime(now.Add(time.Second)),485			MyTime(now.Add(-time.Second)))))486	checkOK(t, MyTime(now),487		td.Lax(td.Between(488			now.Add(-time.Second),489			2*time.Second)))490	checkOK(t, now,491		td.Lax(td.Between(492			MyTime(now.Add(-time.Second)),493			2*time.Second)))494	date := time.Date(2018, time.March, 4, 0, 0, 0, 0, time.UTC)495	checkError(t, date,496		td.Between(date.Add(-2*time.Second), date.Add(-time.Second)),497		expectedError{498			Message: mustBe("values differ"),499			Path:    mustBe("DATA"),500			Got:     mustBe("(time.Time) 2018-03-04 00:00:00 +0000 UTC"),501			Expected: mustBe("(time.Time) 2018-03-03 23:59:58 +0000 UTC" +502				" ⤠got ⤠" +503				"(time.Time) 2018-03-03 23:59:59 +0000 UTC"),504		})505	checkError(t, date,506		td.Between(date.Add(-2*time.Second), date, td.BoundsInOut),507		expectedError{508			Message: mustBe("values differ"),509			Path:    mustBe("DATA"),510			Got:     mustBe("(time.Time) 2018-03-04 00:00:00 +0000 UTC"),511			Expected: mustBe("(time.Time) 2018-03-03 23:59:58 +0000 UTC" +512				" ⤠got < " +513				"(time.Time) 2018-03-04 00:00:00 +0000 UTC"),514		})515	checkError(t, date,516		td.Between(date, date.Add(2*time.Second), td.BoundsOutIn),517		expectedError{518			Message: mustBe("values differ"),519			Path:    mustBe("DATA"),520			Got:     mustBe("(time.Time) 2018-03-04 00:00:00 +0000 UTC"),521			Expected: mustBe("(time.Time) 2018-03-04 00:00:00 +0000 UTC" +522				" < got ⤠" +523				"(time.Time) 2018-03-04 00:00:02 +0000 UTC"),524		})525	checkError(t, "string",526		td.Between(date, date.Add(2*time.Second), td.BoundsOutIn),527		expectedError{528			Message:  mustBe("type mismatch"),529			Path:     mustBe("DATA"),530			Got:      mustBe("string"),531			Expected: mustBe("time.Time"),532		})533	checkError(t, "string",534		td.Between(MyTime(date), MyTime(date.Add(2*time.Second)), td.BoundsOutIn),535		expectedError{536			Message:  mustBe("type mismatch"),537			Path:     mustBe("DATA"),538			Got:      mustBe("string"),539			Expected: mustBe("td_test.MyTime"),540		})541	checkError(t, "never tested",542		td.Between(date, 12), // (Time, Time) or (Time, Duration)543		expectedError{544			Message: mustBe("bad usage of Between operator"),545			Path:    mustBe("DATA"),546			Summary: mustBe("Between(FROM, TO): when FROM type is time.Time, TO must have the same type or time.Duration: int â  time.Time|time.Duration"),547		})548	checkError(t, "never tested",549		td.Between(MyTime(date), 12), // (MyTime, MyTime) or (MyTime, Duration)550		expectedError{551			Message: mustBe("bad usage of Between operator"),552			Path:    mustBe("DATA"),553			Summary: mustBe("Between(FROM, TO): when FROM type is td_test.MyTime, TO must have the same type or time.Duration: int â  td_test.MyTime|time.Duration"),554		})555	checkOK(t, now, td.Gt(now.Add(-time.Second)))556	checkOK(t, now, td.Lt(now.Add(time.Second)))557}558type compareType int559func (i compareType) Compare(j compareType) int {560	if i < j {561		return -1562	}563	if i > j {564		return 1565	}566	return 0567}568type lessType int569func (i lessType) Less(j lessType) bool {570	return i < j571}572func TestBetweenCmp(t *testing.T) {573	t.Run("compareType", func(t *testing.T) {574		checkOK(t, compareType(5), td.Between(compareType(4), compareType(6)))575		checkOK(t, compareType(5), td.Between(compareType(6), compareType(4)))576		checkOK(t, compareType(5), td.Between(compareType(5), compareType(6)))577		checkOK(t, compareType(5), td.Between(compareType(4), compareType(5)))578		checkOK(t, compareType(5),579			td.Between(compareType(4), compareType(6), td.BoundsOutOut))580		checkError(t, compareType(5),581			td.Between(compareType(5), compareType(6), td.BoundsOutIn),582			expectedError{583				Message:  mustBe("values differ"),584				Path:     mustBe("DATA"),585				Got:      mustBe("(td_test.compareType) 5"),586				Expected: mustBe("(td_test.compareType) 5 < got ⤠(td_test.compareType) 6"),587			})588		checkError(t, compareType(5),589			td.Between(compareType(4), compareType(5), td.BoundsInOut),590			expectedError{591				Message:  mustBe("values differ"),592				Path:     mustBe("DATA"),593				Got:      mustBe("(td_test.compareType) 5"),594				Expected: mustBe("(td_test.compareType) 4 ⤠got < (td_test.compareType) 5"),595			})596		// Other between forms597		checkOK(t, compareType(5), td.Gt(compareType(4)))598		checkOK(t, compareType(5), td.Gte(compareType(5)))599		checkOK(t, compareType(5), td.Lt(compareType(6)))600		checkOK(t, compareType(5), td.Lte(compareType(5)))601		// BeLax or not BeLax602		for i, op := range []td.TestDeep{603			td.Between(compareType(4), compareType(6)),604			td.Gt(compareType(4)),605			td.Gte(compareType(5)),606			td.Lt(compareType(6)),607			td.Lte(compareType(5)),608		} {609			// Type mismatch if BeLax not enabled610			checkError(t, 5, op,611				expectedError{612					Message:  mustBe("type mismatch"),613					Path:     mustBe("DATA"),614					Got:      mustBe("int"),615					Expected: mustBe("td_test.compareType"),616				},617				"Op #%d", i)618			// BeLax enabled is OK619			checkOK(t, 5, td.Lax(op), "Op #%d", i)620		}621		// In a private field622		type private struct {623			num compareType624		}625		checkOK(t, private{num: 5},626			td.Struct(private{},627				td.StructFields{628					"num": td.Between(compareType(4), compareType(6)),629				}))630	})631	t.Run("lessType", func(t *testing.T) {632		checkOK(t, lessType(5), td.Between(lessType(4), lessType(6)))633		checkOK(t, lessType(5), td.Between(lessType(6), lessType(4)))634		checkOK(t, lessType(5), td.Between(lessType(5), lessType(6)))635		checkOK(t, lessType(5), td.Between(lessType(4), lessType(5)))636		checkOK(t, lessType(5),637			td.Between(lessType(4), lessType(6), td.BoundsOutOut))638		checkError(t, lessType(5),639			td.Between(lessType(5), lessType(6), td.BoundsOutIn),640			expectedError{641				Message:  mustBe("values differ"),642				Path:     mustBe("DATA"),643				Got:      mustBe("(td_test.lessType) 5"),644				Expected: mustBe("(td_test.lessType) 5 < got ⤠(td_test.lessType) 6"),645			})646		checkError(t, lessType(5),647			td.Between(lessType(4), lessType(5), td.BoundsInOut),648			expectedError{649				Message:  mustBe("values differ"),650				Path:     mustBe("DATA"),651				Got:      mustBe("(td_test.lessType) 5"),652				Expected: mustBe("(td_test.lessType) 4 ⤠got < (td_test.lessType) 5"),653			})654		// Other between forms655		checkOK(t, lessType(5), td.Gt(lessType(4)))656		checkOK(t, lessType(5), td.Gte(lessType(5)))657		checkOK(t, lessType(5), td.Lt(lessType(6)))658		checkOK(t, lessType(5), td.Lte(lessType(5)))659		// BeLax or not BeLax660		for i, op := range []td.TestDeep{661			td.Between(lessType(4), lessType(6)),662			td.Gt(lessType(4)),663			td.Gte(lessType(5)),664			td.Lt(lessType(6)),665			td.Lte(lessType(5)),666		} {667			// Type mismatch if BeLax not enabled668			checkError(t, 5, op,669				expectedError{670					Message:  mustBe("type mismatch"),671					Path:     mustBe("DATA"),672					Got:      mustBe("int"),673					Expected: mustBe("td_test.lessType"),674				},675				"Op #%d", i)676			// BeLax enabled is OK677			checkOK(t, 5, td.Lax(op), "Op #%d", i)678		}679		// In a private field680		type private struct {681			num lessType682		}683		checkOK(t, private{num: 5},684			td.Struct(private{},685				td.StructFields{686					"num": td.Between(lessType(4), lessType(6)),687				}))688	})689}690func TestBetweenTypeBehind(t *testing.T) {691	type MyTime time.Time692	for _, typ := range []any{693		10,694		int64(23),695		int32(23),696		time.Time{},697		MyTime{},698		compareType(0),699		lessType(0),700	} {701		equalTypes(t, td.Between(typ, typ), typ)702		equalTypes(t, td.Gt(typ), typ)703		equalTypes(t, td.Gte(typ), typ)704		equalTypes(t, td.Lt(typ), typ)705		equalTypes(t, td.Lte(typ), typ)706	}707	equalTypes(t, td.N(int64(23), int64(5)), int64(0))708	// Erroneous op709	equalTypes(t, td.Between("test", 12), nil)710	equalTypes(t, td.N(10, 1, 2), nil)711	equalTypes(t, td.Gt([]byte("test")), nil)712	equalTypes(t, td.Gte([]byte("test")), nil)713	equalTypes(t, td.Lt([]byte("test")), nil)714	equalTypes(t, td.Lte([]byte("test")), nil)715}...td_between.go
Source:td_between.go  
...18	boundNone boundCmp = iota19	boundIn20	boundOut21)22type tdBetween struct {23	base24	expectedMin reflect.Value25	expectedMax reflect.Value26	minBound boundCmp27	maxBound boundCmp28}29var _ TestDeep = &tdBetween{}30// BoundsKind type qualifies the [Between] bounds.31type BoundsKind uint832const (33	_            BoundsKind = (iota - 1) & 334	BoundsInIn              // allows to match between "from" and "to" both included.35	BoundsInOut             // allows to match between "from" included and "to" excluded.36	BoundsOutIn             // allows to match between "from" excluded and "to" included.37	BoundsOutOut            // allows to match between "from" and "to" both excluded.38)39type tdBetweenTime struct {40	tdBetween41	expectedType reflect.Type42	mustConvert  bool43}44var _ TestDeep = &tdBetweenTime{}45type tdBetweenCmp struct {46	tdBetween47	expectedType reflect.Type48	cmp          func(a, b reflect.Value) int49}50// summary(Between): checks that a number, string or time.Time is51// between two bounds52// input(Between): str,int,float,cplx(todo),struct(time.Time)53// Between operator checks that data is between from and54// to. from and to can be any numeric, string, [time.Time] (or55// assignable) value or implement at least one of the two following56// methods:57//58//	func (a T) Less(b T) bool   // returns true if a < b59//	func (a T) Compare(b T) int // returns -1 if a < b, 1 if a > b, 0 if a == b60//61// from and to must be the same type as the compared value, except62// if BeLax config flag is true. [time.Duration] type is accepted as63// to when from is [time.Time] or convertible. bounds allows to64// specify whether bounds are included or not:65//   - [BoundsInIn] (default): between from and to both included66//   - [BoundsInOut]: between from included and to excluded67//   - [BoundsOutIn]: between from excluded and to included68//   - [BoundsOutOut]: between from and to both excluded69//70// If bounds is missing, it defaults to [BoundsInIn].71//72//	tc.Cmp(t, 17, td.Between(17, 20))               // succeeds, BoundsInIn by default73//	tc.Cmp(t, 17, td.Between(10, 17, BoundsInOut))  // fails74//	tc.Cmp(t, 17, td.Between(10, 17, BoundsOutIn))  // succeeds75//	tc.Cmp(t, 17, td.Between(17, 20, BoundsOutOut)) // fails76//	tc.Cmp(t,                                       // succeeds77//	  netip.MustParse("127.0.0.1"),78//	  td.Between(netip.MustParse("127.0.0.0"), netip.MustParse("127.255.255.255")))79//80// TypeBehind method returns the [reflect.Type] of from.81func Between(from, to any, bounds ...BoundsKind) TestDeep {82	b := tdBetween{83		base:        newBase(3),84		expectedMin: reflect.ValueOf(from),85		expectedMax: reflect.ValueOf(to),86	}87	const usage = "(NUM|STRING|TIME, NUM|STRING|TIME/DURATION[, BOUNDS_KIND])"88	if len(bounds) > 0 {89		if len(bounds) > 1 {90			b.err = ctxerr.OpTooManyParams("Between", usage)91			return &b92		}93		if bounds[0] == BoundsInIn || bounds[0] == BoundsInOut {94			b.minBound = boundIn95		} else {96			b.minBound = boundOut97		}98		if bounds[0] == BoundsInIn || bounds[0] == BoundsOutIn {99			b.maxBound = boundIn100		} else {101			b.maxBound = boundOut102		}103	} else {104		b.minBound = boundIn105		b.maxBound = boundIn106	}107	if b.expectedMax.Type() == b.expectedMin.Type() {108		return b.initBetween(usage)109	}110	// Special case for (TIME, DURATION)111	ok, convertible := types.IsTypeOrConvertible(b.expectedMin, types.Time)112	if ok {113		if d, ok := to.(time.Duration); ok {114			if convertible {115				b.expectedMax = reflect.ValueOf(116					b.expectedMin.117						Convert(types.Time).118						Interface().(time.Time).119						Add(d)).120					Convert(b.expectedMin.Type())121			} else {122				b.expectedMax = reflect.ValueOf(from.(time.Time).Add(d))123			}124			return b.initBetween(usage)125		}126		b.err = ctxerr.OpBad("Between",127			"Between(FROM, TO): when FROM type is %[1]s, TO must have the same type or time.Duration: %[2]s â  %[1]s|time.Duration",128			b.expectedMin.Type(),129			b.expectedMax.Type(),130		)131		return &b132	}133	b.err = ctxerr.OpBad("Between",134		"Between(FROM, TO): FROM and TO must have the same type: %s â  %s",135		b.expectedMin.Type(),136		b.expectedMax.Type(),137	)138	return &b139}140func (b *tdBetween) initBetween(usage string) TestDeep {141	if !b.expectedMax.IsValid() {142		b.expectedMax = b.expectedMin143	}144	// Is any of:145	// (T) Compare(T) int146	// or147	// (T) Less(T) bool148	// available?149	if cmp := types.NewOrder(b.expectedMin.Type()); cmp != nil {150		if order := cmp(b.expectedMin, b.expectedMax); order > 0 {151			b.expectedMin, b.expectedMax = b.expectedMax, b.expectedMin152		}153		return &tdBetweenCmp{154			tdBetween:    *b,155			expectedType: b.expectedMin.Type(),156			cmp:          cmp,157		}158	}159	switch b.expectedMin.Kind() {160	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:161		if b.expectedMin.Int() > b.expectedMax.Int() {162			b.expectedMin, b.expectedMax = b.expectedMax, b.expectedMin163		}164		return b165	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:166		if b.expectedMin.Uint() > b.expectedMax.Uint() {167			b.expectedMin, b.expectedMax = b.expectedMax, b.expectedMin168		}169		return b170	case reflect.Float32, reflect.Float64:171		if b.expectedMin.Float() > b.expectedMax.Float() {172			b.expectedMin, b.expectedMax = b.expectedMax, b.expectedMin173		}174		return b175	case reflect.String:176		if b.expectedMin.String() > b.expectedMax.String() {177			b.expectedMin, b.expectedMax = b.expectedMax, b.expectedMin178		}179		return b180	case reflect.Struct:181		ok, convertible := types.IsTypeOrConvertible(b.expectedMin, types.Time)182		if !ok {183			break184		}185		var bt tdBetweenTime186		if convertible {187			bt = tdBetweenTime{188				tdBetween:    *b,189				expectedType: b.expectedMin.Type(),190				mustConvert:  true,191			}192			bt.expectedMin = b.expectedMin.Convert(types.Time)193			bt.expectedMax = b.expectedMax.Convert(types.Time)194		} else {195			bt = tdBetweenTime{196				tdBetween:    *b,197				expectedType: types.Time,198			}199		}200		if bt.expectedMin.Interface().(time.Time).201			After(bt.expectedMax.Interface().(time.Time)) {202			bt.expectedMin, bt.expectedMax = bt.expectedMax, bt.expectedMin203		}204		return &bt205	}206	b.err = ctxerr.OpBadUsage(b.GetLocation().Func,207		usage, b.expectedMin.Interface(), 1, true)208	return b209}210func (b *tdBetween) nInt(tolerance reflect.Value) {211	if diff := tolerance.Int(); diff != 0 {212		expectedBase := b.expectedMin.Int()213		max := expectedBase + diff214		if max < expectedBase {215			max = math.MaxInt64216		}217		min := expectedBase - diff218		if min > expectedBase {219			min = math.MinInt64220		}221		b.expectedMin = reflect.New(tolerance.Type()).Elem()222		b.expectedMin.SetInt(min)223		b.expectedMax = reflect.New(tolerance.Type()).Elem()224		b.expectedMax.SetInt(max)225	}226}227func (b *tdBetween) nUint(tolerance reflect.Value) {228	if diff := tolerance.Uint(); diff != 0 {229		base := b.expectedMin.Uint()230		max := base + diff231		if max < base {232			max = math.MaxUint64233		}234		min := base - diff235		if min > base {236			min = 0237		}238		b.expectedMin = reflect.New(tolerance.Type()).Elem()239		b.expectedMin.SetUint(min)240		b.expectedMax = reflect.New(tolerance.Type()).Elem()241		b.expectedMax.SetUint(max)242	}243}244func (b *tdBetween) nFloat(tolerance reflect.Value) {245	if diff := tolerance.Float(); diff != 0 {246		base := b.expectedMin.Float()247		b.expectedMin = reflect.New(tolerance.Type()).Elem()248		b.expectedMin.SetFloat(base - diff)249		b.expectedMax = reflect.New(tolerance.Type()).Elem()250		b.expectedMax.SetFloat(base + diff)251	}252}253// summary(N): compares a number with a tolerance value254// input(N): int,float,cplx(todo)255// N operator compares a numeric data against num ± tolerance. If256// tolerance is missing, it defaults to 0. num and tolerance257// must be the same type as the compared value, except if BeLax config258// flag is true.259//260//	td.Cmp(t, 12.2, td.N(12., 0.3)) // succeeds261//	td.Cmp(t, 12.2, td.N(12., 0.1)) // fails262//263// TypeBehind method returns the [reflect.Type] of num.264func N(num any, tolerance ...any) TestDeep {265	n := tdBetween{266		base:        newBase(3),267		expectedMin: reflect.ValueOf(num),268		minBound:    boundIn,269		maxBound:    boundIn,270	}271	const usage = "({,U}INT{,8,16,32,64}|FLOAT{32,64}[, TOLERANCE])"272	switch n.expectedMin.Kind() {273	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,274		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,275		reflect.Float32, reflect.Float64:276	default:277		n.err = ctxerr.OpBadUsage("N", usage, num, 1, true)278		return &n279	}280	n.expectedMax = n.expectedMin281	if len(tolerance) > 0 {282		if len(tolerance) > 1 {283			n.err = ctxerr.OpTooManyParams("N", usage)284			return &n285		}286		tol := reflect.ValueOf(tolerance[0])287		if tol.Type() != n.expectedMin.Type() {288			n.err = ctxerr.OpBad("N",289				"N(NUM, TOLERANCE): NUM and TOLERANCE must have the same type: %s â  %s",290				n.expectedMin.Type(), tol.Type())291			return &n292		}293		switch tol.Kind() {294		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:295			n.nInt(tol)296		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,297			reflect.Uint64:298			n.nUint(tol)299		default: // case reflect.Float32, reflect.Float64:300			n.nFloat(tol)301		}302	}303	return &n304}305// summary(Gt): checks that a number, string or time.Time is306// greater than a value307// input(Gt): str,int,float,cplx(todo),struct(time.Time)308// Gt operator checks that data is greater than309// minExpectedValue. minExpectedValue can be any numeric, string,310// [time.Time] (or assignable) value or implements at least one of the311// two following methods:312//313//	func (a T) Less(b T) bool   // returns true if a < b314//	func (a T) Compare(b T) int // returns -1 if a < b, 1 if a > b, 0 if a == b315//316// minExpectedValue must be the same type as the compared value,317// except if BeLax config flag is true.318//319//	td.Cmp(t, 17, td.Gt(15))320//	before := time.Now()321//	td.Cmp(t, time.Now(), td.Gt(before))322//323// TypeBehind method returns the [reflect.Type] of minExpectedValue.324func Gt(minExpectedValue any) TestDeep {325	b := &tdBetween{326		base:        newBase(3),327		expectedMin: reflect.ValueOf(minExpectedValue),328		minBound:    boundOut,329	}330	return b.initBetween("(NUM|STRING|TIME)")331}332// summary(Gte): checks that a number, string or time.Time is333// greater or equal than a value334// input(Gte): str,int,float,cplx(todo),struct(time.Time)335// Gte operator checks that data is greater or equal than336// minExpectedValue. minExpectedValue can be any numeric, string,337// [time.Time] (or assignable) value or implements at least one of the338// two following methods:339//340//	func (a T) Less(b T) bool   // returns true if a < b341//	func (a T) Compare(b T) int // returns -1 if a < b, 1 if a > b, 0 if a == b342//343// minExpectedValue must be the same type as the compared value,344// except if BeLax config flag is true.345//346//	td.Cmp(t, 17, td.Gte(17))347//	before := time.Now()348//	td.Cmp(t, time.Now(), td.Gte(before))349//350// TypeBehind method returns the [reflect.Type] of minExpectedValue.351func Gte(minExpectedValue any) TestDeep {352	b := &tdBetween{353		base:        newBase(3),354		expectedMin: reflect.ValueOf(minExpectedValue),355		minBound:    boundIn,356	}357	return b.initBetween("(NUM|STRING|TIME)")358}359// summary(Lt): checks that a number, string or time.Time is360// lesser than a value361// input(Lt): str,int,float,cplx(todo),struct(time.Time)362// Lt operator checks that data is lesser than363// maxExpectedValue. maxExpectedValue can be any numeric, string,364// [time.Time] (or assignable) value or implements at least one of the365// two following methods:366//367//	func (a T) Less(b T) bool   // returns true if a < b368//	func (a T) Compare(b T) int // returns -1 if a < b, 1 if a > b, 0 if a == b369//370// maxExpectedValue must be the same type as the compared value,371// except if BeLax config flag is true.372//373//	td.Cmp(t, 17, td.Lt(19))374//	before := time.Now()375//	td.Cmp(t, before, td.Lt(time.Now()))376//377// TypeBehind method returns the [reflect.Type] of maxExpectedValue.378func Lt(maxExpectedValue any) TestDeep {379	b := &tdBetween{380		base:        newBase(3),381		expectedMin: reflect.ValueOf(maxExpectedValue),382		maxBound:    boundOut,383	}384	return b.initBetween("(NUM|STRING|TIME)")385}386// summary(Lte): checks that a number, string or time.Time is387// lesser or equal than a value388// input(Lte): str,int,float,cplx(todo),struct(time.Time)389// Lte operator checks that data is lesser or equal than390// maxExpectedValue. maxExpectedValue can be any numeric, string,391// [time.Time] (or assignable) value or implements at least one of the392// two following methods:393//394//	func (a T) Less(b T) bool   // returns true if a < b395//	func (a T) Compare(b T) int // returns -1 if a < b, 1 if a > b, 0 if a == b396//397// maxExpectedValue must be the same type as the compared value,398// except if BeLax config flag is true.399//400//	td.Cmp(t, 17, td.Lte(17))401//	before := time.Now()402//	td.Cmp(t, before, td.Lt(time.Now()))403//404// TypeBehind method returns the [reflect.Type] of maxExpectedValue.405func Lte(maxExpectedValue any) TestDeep {406	b := &tdBetween{407		base:        newBase(3),408		expectedMin: reflect.ValueOf(maxExpectedValue),409		maxBound:    boundIn,410	}411	return b.initBetween("(NUM|STRING|TIME)")412}413func (b *tdBetween) matchInt(got reflect.Value) (ok bool) {414	switch b.minBound {415	case boundIn:416		ok = got.Int() >= b.expectedMin.Int()417	case boundOut:418		ok = got.Int() > b.expectedMin.Int()419	default:420		ok = true421	}422	if ok {423		switch b.maxBound {424		case boundIn:425			ok = got.Int() <= b.expectedMax.Int()426		case boundOut:427			ok = got.Int() < b.expectedMax.Int()428		default:429			ok = true430		}431	}432	return433}434func (b *tdBetween) matchUint(got reflect.Value) (ok bool) {435	switch b.minBound {436	case boundIn:437		ok = got.Uint() >= b.expectedMin.Uint()438	case boundOut:439		ok = got.Uint() > b.expectedMin.Uint()440	default:441		ok = true442	}443	if ok {444		switch b.maxBound {445		case boundIn:446			ok = got.Uint() <= b.expectedMax.Uint()447		case boundOut:448			ok = got.Uint() < b.expectedMax.Uint()449		default:450			ok = true451		}452	}453	return454}455func (b *tdBetween) matchFloat(got reflect.Value) (ok bool) {456	switch b.minBound {457	case boundIn:458		ok = got.Float() >= b.expectedMin.Float()459	case boundOut:460		ok = got.Float() > b.expectedMin.Float()461	default:462		ok = true463	}464	if ok {465		switch b.maxBound {466		case boundIn:467			ok = got.Float() <= b.expectedMax.Float()468		case boundOut:469			ok = got.Float() < b.expectedMax.Float()470		default:471			ok = true472		}473	}474	return475}476func (b *tdBetween) matchString(got reflect.Value) (ok bool) {477	switch b.minBound {478	case boundIn:479		ok = got.String() >= b.expectedMin.String()480	case boundOut:481		ok = got.String() > b.expectedMin.String()482	default:483		ok = true484	}485	if ok {486		switch b.maxBound {487		case boundIn:488			ok = got.String() <= b.expectedMax.String()489		case boundOut:490			ok = got.String() < b.expectedMax.String()491		default:492			ok = true493		}494	}495	return496}497func (b *tdBetween) Match(ctx ctxerr.Context, got reflect.Value) *ctxerr.Error {498	if b.err != nil {499		return ctx.CollectError(b.err)500	}501	if got.Type() != b.expectedMin.Type() {502		if ctx.BeLax && types.IsConvertible(b.expectedMin, got.Type()) {503			nb := *b504			nb.expectedMin = b.expectedMin.Convert(got.Type())505			nb.expectedMax = b.expectedMax.Convert(got.Type())506			b = &nb507		} else {508			if ctx.BooleanError {509				return ctxerr.BooleanError510			}511			return ctx.CollectError(ctxerr.TypeMismatch(got.Type(), b.expectedMin.Type()))512		}513	}514	var ok bool515	switch got.Kind() {516	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:517		ok = b.matchInt(got)518	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:519		ok = b.matchUint(got)520	case reflect.Float32, reflect.Float64:521		ok = b.matchFloat(got)522	case reflect.String:523		ok = b.matchString(got)524	}525	if ok {526		return nil527	}528	if ctx.BooleanError {529		return ctxerr.BooleanError530	}531	return ctx.CollectError(&ctxerr.Error{532		Message:  "values differ",533		Got:      got,534		Expected: types.RawString(b.String()),535	})536}537func (b *tdBetween) String() string {538	if b.err != nil {539		return b.stringError()540	}541	var (542		min, max       any543		minStr, maxStr string544	)545	if b.minBound != boundNone {546		min = b.expectedMin.Interface()547		minStr = util.ToString(min)548	}549	if b.maxBound != boundNone {550		max = b.expectedMax.Interface()551		maxStr = util.ToString(max)552	}553	if min != nil {554		if max != nil {555			return fmt.Sprintf("%s %c got %c %s",556				minStr,557				util.TernRune(b.minBound == boundIn, 'â¤', '<'),558				util.TernRune(b.maxBound == boundIn, 'â¤', '<'),559				maxStr)560		}561		return fmt.Sprintf("%c %s",562			util.TernRune(b.minBound == boundIn, 'â¥', '>'), minStr)563	}564	return fmt.Sprintf("%c %s",565		util.TernRune(b.maxBound == boundIn, 'â¤', '<'), maxStr)566}567func (b *tdBetween) TypeBehind() reflect.Type {568	if b.err != nil {569		return nil570	}571	return b.expectedMin.Type()572}573var _ TestDeep = &tdBetweenTime{}574func (b *tdBetweenTime) Match(ctx ctxerr.Context, got reflect.Value) *ctxerr.Error {575	// b.err != nil is not possible here, as when a *tdBetweenTime is576	// built, there is never an error577	if got.Type() != b.expectedType {578		if ctx.BeLax && types.IsConvertible(got, b.expectedType) {579			got = got.Convert(b.expectedType)580		} else {581			if ctx.BooleanError {582				return ctxerr.BooleanError583			}584			return ctx.CollectError(ctxerr.TypeMismatch(got.Type(), b.expectedType))585		}586	}587	cmpGot, err := getTime(ctx, got, b.mustConvert)588	if err != nil {589		return ctx.CollectError(err)590	}591	var ok bool592	if b.minBound != boundNone {593		min := b.expectedMin.Interface().(time.Time)594		if b.minBound == boundIn {595			ok = !min.After(cmpGot)596		} else {597			ok = cmpGot.After(min)598		}599	} else {600		ok = true601	}602	if ok && b.maxBound != boundNone {603		max := b.expectedMax.Interface().(time.Time)604		if b.maxBound == boundIn {605			ok = !max.Before(cmpGot)606		} else {607			ok = cmpGot.Before(max)608		}609	}610	if ok {611		return nil612	}613	if ctx.BooleanError {614		return ctxerr.BooleanError615	}616	return ctx.CollectError(&ctxerr.Error{617		Message:  "values differ",618		Got:      got,619		Expected: types.RawString(b.String()),620	})621}622func (b *tdBetweenTime) TypeBehind() reflect.Type {623	// b.err != nil is not possible here, as when a *tdBetweenTime is624	// built, there is never an error625	return b.expectedType626}627var _ TestDeep = &tdBetweenCmp{}628func (b *tdBetweenCmp) Match(ctx ctxerr.Context, got reflect.Value) *ctxerr.Error {629	// b.err != nil is not possible here, as when a *tdBetweenCmp is630	// built, there is never an error631	if got.Type() != b.expectedType {632		if ctx.BeLax && types.IsConvertible(got, b.expectedType) {633			got = got.Convert(b.expectedType)634		} else {635			if ctx.BooleanError {636				return ctxerr.BooleanError637			}638			return ctx.CollectError(ctxerr.TypeMismatch(got.Type(), b.expectedType))639		}640	}641	var ok bool642	if b.minBound != boundNone {643		order := b.cmp(got, b.expectedMin)644		if b.minBound == boundIn {645			ok = order >= 0646		} else {647			ok = order > 0648		}649	} else {650		ok = true651	}652	if ok && b.maxBound != boundNone {653		order := b.cmp(got, b.expectedMax)654		if b.maxBound == boundIn {655			ok = order <= 0656		} else {657			ok = order < 0658		}659	}660	if ok {661		return nil662	}663	if ctx.BooleanError {664		return ctxerr.BooleanError665	}666	return ctx.CollectError(&ctxerr.Error{667		Message:  "values differ",668		Got:      got,669		Expected: types.RawString(b.String()),670	})671}672func (b *tdBetweenCmp) TypeBehind() reflect.Type {673	// b.err != nil is not possible here, as when a *tdBetweenCmp is674	// built, there is never an error675	return b.expectedType676}...Between
Using AI Code Generation
1import (2func main() {3	td := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)4	fmt.Println(td.Between(time.Date(2009, time.November, 10, 0, 0, 0, 0, time.UTC), time.Date(2009, time.November, 11, 0, 0, 0, 0, time.UTC)))5}6func (t Time) Between(start, end Time) bool7import (8func main() {9	td := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)10	fmt.Println(td.Equal(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)))11}12func (t Time) Equal(u Time) bool13import (14func main() {15	td := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)16	fmt.Println(td.Format("2006-01-02 15:04:05"))17}Between
Using AI Code Generation
1import (2func main() {3    xlFile, err := xlsx.OpenFile("test.xlsx")4    if err != nil {5        panic(err)6    }7    for _, sheet := range xlFile.Sheets {8        for _, row := range sheet.Rows {9            for _, cell := range row.Cells {10                fmt.Printf("%s\n", cell.String())11            }12        }13    }14}15import (16func main() {17    xlFile, err := xlsx.OpenFile("test.xlsx")18    if err != nil {19        panic(err)20    }21    for _, sheet := range xlFile.Sheets {22        for _, row := range sheet.Rows {23            for _, cell := range row.Cells {24                fmt.Printf("%s\n", cell.String())25            }26        }27    }28}29import (30func main() {31    xlFile, err := xlsx.OpenFile("test.xlsx")32    if err != nil {33        panic(err)34    }35    for _, sheet := range xlFile.Sheets {36        for _, row := range sheet.Rows {37            for _, cell := range row.Cells {38                fmt.Printf("%s\n", cell.String())39            }40        }41    }42}43import (44func main() {45    xlFile, err := xlsx.OpenFile("test.xlsx")46    if err != nil {47        panic(err)48    }49    for _, sheet := range xlFile.Sheets {50        for _, row := range sheet.Rows {51            for _, cell := range row.Cells {52                fmt.Printf("%s\n", cell.String())53            }54        }55    }56}57import (58func main() {59    xlFile, err := xlsx.OpenFile("test.xlsx")Between
Using AI Code Generation
1import "fmt"2func main() {3    fmt.Println(td.Between(5, 10, 15))4    fmt.Println(td.Between(5, 10, 10))5    fmt.Println(td.Between(5, 10, 5))6}7import "fmt"8func main() {9    fmt.Println(td.Between(5, 10, 15))10    fmt.Println(td.Between(5, 10, 10))11    fmt.Println(td.Between(5, 10, 5))12}13import "fmt"14func main() {15    fmt.Println(td.Between(5, 10, 15))16    fmt.Println(td.Between(5, 10, 10))17    fmt.Println(td.Between(5, 10, 5))18}19import "fmt"20func main() {21    fmt.Println(td.Between(5, 10, 15))22    fmt.Println(td.Between(5, 10, 10))23    fmt.Println(td.Between(5, 10, 5))24}25import "fmt"26func main() {27    fmt.Println(td.Between(5, 10, 15))28    fmt.Println(td.Between(5, 10, 10))29    fmt.Println(td.Between(5, 10, 5))30}31import "fmt"32func main() {33    fmt.Println(td.Between(5, 10, 15))34    fmt.Println(td.Between(5, 10, 10))35    fmt.Println(td.Between(5, 10, 5))36}Between
Using AI Code Generation
1import (2func main() {3}4import (5func main() {6}7import (8func main() {9}10import (11func main() {12}13import (14func main() {15}16import (17func main() {18}19import (20func main() {21}Between
Using AI Code Generation
1import (2func main() {3	xlFile, err := xlsx.OpenFile("1.xlsx")4	if err != nil {5		fmt.Printf("Error: %s6	}7	f, _ := strconv.ParseFloat(val, 64)8	fmt.Println(f)9	fmt.Println(cell.Between(0, 100))10}11import (12func main() {13	xlFile, err := xlsx.OpenFile("1.xlsx")14	if err != nil {15		fmt.Printf("Error: %s16	}17	s := cell.String()18	fmt.Println(val)19	fmt.Println(s)20}21import (22func main() {23	xlFile, err := xlsx.OpenFile("1.xlsx")24	if err != nil {25		fmt.Printf("Error: %s26	}Between
Using AI Code Generation
1import (2func main() {3	xlFile, err := xlsx.OpenFile("Book1.xlsx")4	if err != nil {5		panic(err)6	}7	for _, row := range sheet.Rows {8		if row != nil {9			for _, cell := range row.Cells {10				if cell != nil {11					value, _ := cell.String()12					fmt.Println(value)13					if td.Between(value, "A", "D") {14						fmt.Println("Value between A and D")15					}16					if td.Between(value, "1", "3") {17						fmt.Println("Value between 1 and 3")18					}19					if td.Between(value, "a", "d") {20						fmt.Println("Value between a and d")21					}22					if td.Between(value, "!", "@") {23						fmt.Println("Value between ! and @")24					}25					if td.Between(value, "a", "A") {26						fmt.Println("Value between a and A")27					}28					if td.Between(value, "0", "9") {29						fmt.Println("Value between 0 and 9")30					}31					if td.Between(value, "0", "9") {32						fmt.Println("Value between 0 and 9")33					}34					if td.Between(value, "0", "9") {35						fmt.Println("Value between 0 and 9")36					}37					if td.Between(value, "0", "9") {38						fmt.Println("Value between 0 and 9")39					}Between
Using AI Code Generation
1import (2func main() {3	t := time.Now()4	td := t.Sub(time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC))5	fmt.Printf("td: %v6	fmt.Printf("td.Between(time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)): %v7", td.Between(time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)))8}9td.Between(time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)): true10td.Between(time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)): trueBetween
Using AI Code Generation
1import "fmt"2import "time"3func main() {4  d1 := time.Date(2017, 8, 15, 0, 0, 0, 0, time.UTC)5  d2 := time.Date(2017, 8, 30, 0, 0, 0, 0, time.UTC)6  diff := td.Between(d1, d2)7  fmt.Println(diff)8}9import "fmt"10import "time"11func main() {12  d1 := time.Date(2017, 8, 15, 0, 0, 0, 0, time.UTC)13  d2 := time.Date(2017, 8, 15, 2, 0, 0, 0, time.UTC)14  diff := td.Between(d1, d2, td.Hours())15  fmt.Println(diff)16}17import "fmt"18import "time"19func main() {20  d1 := time.Date(2017, 8, 15, 0, 0, 0, 0, time.UTC)21  d2 := time.Date(2017, 8, 15, 0, 2, 0, 0, time.UTC)22  diff := td.Between(d1, d2, td.Minutes())23  fmt.Println(diff)24}25import "fmt"26import "time"27func main() {Between
Using AI Code Generation
1import (2func main() {3	fmt.Println("Enter a string:")4	fmt.Scanln(&s)5	fmt.Println("Enter a number:")6	fmt.Scanln(&n)7	fmt.Println("Enter a number:")8	fmt.Scanln(&m)9	fmt.Println(t.Between(s, n, m))10}11import (12func main() {13	fmt.Println("Enter a string:")14	fmt.Scanln(&s)15	fmt.Println("Enter a number:")16	fmt.Scanln(&n)17	fmt.Println("Enter a number:")18	fmt.Scanln(&m)19	fmt.Println(t.Remove(s, n, m))20}21import (22func main() {23	fmt.Println("Enter a string:")24	fmt.Scanln(&s)25	fmt.Println("Enter a number:")26	fmt.Scanln(&n)27	fmt.Println("Enter a string:")28	fmt.Scanln(&m)29	fmt.Println(t.Insert(s, n, m))30}31import (32func main() {33	fmt.Println("Enter a string:")34	fmt.Scanln(&s)35	fmt.Println("Enter a number:")36	fmt.Scanln(&n)37	fmt.Println("Enter a string:")38	fmt.Scanln(&m)39	fmt.Println(t.Replace(s, n, m))40}Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
