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)): true
Between
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!!