How to use getFieldsPathFn method of td Package

Best Go-testdeep code snippet using td.getFieldsPathFn

td_smuggle.go

Source:td_smuggle.go Github

copy

Full Screen

...241 Value: vgot,242 }, nil243 }, nil244}245func getFieldsPathFn(fieldPath string) (reflect.Value, error) {246 smuggleFnsMu.Lock()247 defer smuggleFnsMu.Unlock()248 if vfn, ok := smuggleFns[fieldPath]; ok {249 return vfn, nil250 }251 fn, err := buildFieldsPathFn(fieldPath)252 if err != nil {253 return reflect.Value{}, err254 }255 vfn := reflect.ValueOf(fn)256 smuggleFns[fieldPath] = vfn257 return vfn, err258}259func getCaster(outType reflect.Type) reflect.Value {260 smuggleFnsMu.Lock()261 defer smuggleFnsMu.Unlock()262 if vfn, ok := smuggleFns[outType]; ok {263 return vfn264 }265 var fn reflect.Value266 switch outType.Kind() {267 case reflect.String:268 fn = buildCaster(outType, true)269 case reflect.Slice:270 if outType.Elem().Kind() == reflect.Uint8 {271 // Special case for slices of bytes: falls back on io.Reader if not []byte272 fn = buildCaster(outType, false)273 break274 }275 fallthrough276 default:277 // For all other types, take the received param and return278 // it. Smuggle already converted got to the type of param, so the279 // work is done.280 inOut := []reflect.Type{outType}281 fn = reflect.MakeFunc(282 reflect.FuncOf(inOut, inOut, false),283 func(args []reflect.Value) []reflect.Value { return args },284 )285 }286 smuggleFns[outType] = fn287 return fn288}289// buildCaster returns a function:290//291// func(in any) (out outType, err error)292//293// dynamically checks…294// - if useString is false, as outType is a slice of bytes:295// 1. in is a []byte or convertible to []byte296// 2. in implements io.Reader297// - if useString is true, as outType is a string:298// 1. in is a []byte or convertible to string299// 2. in implements io.Reader300func buildCaster(outType reflect.Type, useString bool) reflect.Value {301 zeroRet := reflect.New(outType).Elem()302 return reflect.MakeFunc(303 reflect.FuncOf(304 []reflect.Type{types.Interface},305 []reflect.Type{outType, types.Error},306 false,307 ),308 func(args []reflect.Value) []reflect.Value {309 if args[0].IsNil() {310 return []reflect.Value{311 zeroRet,312 reflect.ValueOf(&ctxerr.Error{313 Message: "incompatible parameter type",314 Got: types.RawString("nil"),315 Expected: types.RawString(outType.String() + " or convertible or io.Reader"),316 }),317 }318 }319 // 1st & only arg is always an interface320 args[0] = args[0].Elem()321 if ok, convertible := types.IsTypeOrConvertible(args[0], outType); ok {322 if convertible {323 return []reflect.Value{args[0].Convert(outType), nilError}324 }325 return []reflect.Value{args[0], nilError}326 }327 // Our caller encures Interface() can be called safely328 switch ta := args[0].Interface().(type) {329 case io.Reader:330 var b bytes.Buffer331 if _, err := b.ReadFrom(ta); err != nil {332 return []reflect.Value{333 zeroRet,334 reflect.ValueOf(&ctxerr.Error{335 Message: "an error occurred while reading from io.Reader",336 Summary: ctxerr.NewSummary(err.Error()),337 }),338 }339 }340 var buf any341 if useString {342 buf = b.String()343 } else {344 buf = b.Bytes()345 }346 return []reflect.Value{347 reflect.ValueOf(buf).Convert(outType),348 nilError,349 }350 default:351 return []reflect.Value{352 zeroRet,353 reflect.ValueOf(&ctxerr.Error{354 Message: "incompatible parameter type",355 Got: types.RawString(args[0].Type().String()),356 Expected: types.RawString(outType.String() + " or convertible or io.Reader"),357 }),358 }359 }360 })361}362// summary(Smuggle): changes data contents or mutates it into another363// type via a custom function or a struct fields-path before stepping364// down in favor of generic comparison process365// input(Smuggle): all366// Smuggle operator allows to change data contents or mutate it into367// another type before stepping down in favor of generic comparison368// process. Of course it is a smuggler operator. So fn is a function369// that must take one parameter whose type must be convertible to the370// type of the compared value.371//372// As convenient shortcuts, fn can be a string specifying a373// fields-path through structs, maps & slices, or any other type, in374// this case a simple cast is done (see below for details).375//376// fn must return at least one value. These value will be compared as is377// to expectedValue, here integer 28:378//379// td.Cmp(t, "0028",380// td.Smuggle(func(value string) int {381// num, _ := strconv.Atoi(value)382// return num383// }, 28),384// )385//386// or using an other [TestDeep] operator, here [Between](28, 30):387//388// td.Cmp(t, "0029",389// td.Smuggle(func(value string) int {390// num, _ := strconv.Atoi(value)391// return num392// }, td.Between(28, 30)),393// )394//395// fn can return a second boolean value, used to tell that a problem396// occurred and so stop the comparison:397//398// td.Cmp(t, "0029",399// td.Smuggle(func(value string) (int, bool) {400// num, err := strconv.Atoi(value)401// return num, err == nil402// }, td.Between(28, 30)),403// )404//405// fn can return a third string value which is used to describe the406// test when a problem occurred (false second boolean value):407//408// td.Cmp(t, "0029",409// td.Smuggle(func(value string) (int, bool, string) {410// num, err := strconv.Atoi(value)411// if err != nil {412// return 0, false, "string must contain a number"413// }414// return num, true, ""415// }, td.Between(28, 30)),416// )417//418// Instead of returning (X, bool) or (X, bool, string), fn can419// return (X, error). When a problem occurs, the returned error is420// non-nil, as in:421//422// td.Cmp(t, "0029",423// td.Smuggle(func(value string) (int, error) {424// num, err := strconv.Atoi(value)425// return num, err426// }, td.Between(28, 30)),427// )428//429// Which can be simplified to:430//431// td.Cmp(t, "0029", td.Smuggle(strconv.Atoi, td.Between(28, 30)))432//433// Imagine you want to compare that the Year of a date is between 2010434// and 2020:435//436// td.Cmp(t, time.Date(2015, time.May, 1, 1, 2, 3, 0, time.UTC),437// td.Smuggle(func(date time.Time) int { return date.Year() },438// td.Between(2010, 2020)),439// )440//441// In this case the data location forwarded to next test will be442// something like "DATA.MyTimeField<smuggled>", but you can act on it443// too by returning a [SmuggledGot] struct (by value or by address):444//445// td.Cmp(t, time.Date(2015, time.May, 1, 1, 2, 3, 0, time.UTC),446// td.Smuggle(func(date time.Time) SmuggledGot {447// return SmuggledGot{448// Name: "Year",449// Got: date.Year(),450// }451// }, td.Between(2010, 2020)),452// )453//454// then the data location forwarded to next test will be something like455// "DATA.MyTimeField.Year". The "." between the current path (here456// "DATA.MyTimeField") and the returned Name "Year" is automatically457// added when Name starts with a Letter.458//459// Note that [SmuggledGot] and [*SmuggledGot] returns are treated460// equally, and they are only used when fn has only one returned value461// or when the second boolean returned value is true.462//463// Of course, all cases can go together:464//465// // Accepts a "YYYY/mm/DD HH:MM:SS" string to produce a time.Time and tests466// // whether this date is contained between 2 hours before now and now.467// td.Cmp(t, "2020-01-25 12:13:14",468// td.Smuggle(func(date string) (*SmuggledGot, bool, string) {469// date, err := time.Parse("2006/01/02 15:04:05", date)470// if err != nil {471// return nil, false, `date must conform to "YYYY/mm/DD HH:MM:SS" format`472// }473// return &SmuggledGot{474// Name: "Date",475// Got: date,476// }, true, ""477// }, td.Between(time.Now().Add(-2*time.Hour), time.Now())),478// )479//480// or:481//482// // Accepts a "YYYY/mm/DD HH:MM:SS" string to produce a time.Time and tests483// // whether this date is contained between 2 hours before now and now.484// td.Cmp(t, "2020-01-25 12:13:14",485// td.Smuggle(func(date string) (*SmuggledGot, error) {486// date, err := time.Parse("2006/01/02 15:04:05", date)487// if err != nil {488// return nil, err489// }490// return &SmuggledGot{491// Name: "Date",492// Got: date,493// }, nil494// }, td.Between(time.Now().Add(-2*time.Hour), time.Now())),495// )496//497// Smuggle can also be used to access a struct field embedded in498// several struct layers.499//500// type A struct{ Num int }501// type B struct{ As map[string]*A }502// type C struct{ B B }503// got := C{B: B{As: map[string]*A{"foo": {Num: 12}}}}504//505// // Tests that got.B.A.Num is 12506// td.Cmp(t, got,507// td.Smuggle(func(c C) int {508// return c.B.As["foo"].Num509// }, 12))510//511// As brought up above, a fields-path can be passed as fn value512// instead of a function pointer. Using this feature, the [Cmp]513// call in the above example can be rewritten as follows:514//515// // Tests that got.B.As["foo"].Num is 12516// td.Cmp(t, got, td.Smuggle("B.As[foo].Num", 12))517//518// Contrary to [JSONPointer] operator, private fields can be519// followed. Arrays, slices and maps work using the index/key inside520// square brackets (e.g. [12] or [foo]). Maps work only for simple key521// types (string or numbers), without "" when using strings522// (e.g. [foo]).523//524// Behind the scenes, a temporary function is automatically created to525// achieve the same goal, but add some checks against nil values and526// auto-dereference interfaces and pointers, even on several levels,527// like in:528//529// type A struct{ N any }530// num := 12531// pnum := &num532// td.Cmp(t, A{N: &pnum}, td.Smuggle("N", 12))533//534// Last but not least, a simple type can be passed as fn to operate535// a cast, handling specifically strings and slices of bytes:536//537// td.Cmp(t, `{"foo":1}`, td.Smuggle(json.RawMessage{}, td.JSON(`{"foo":1}`)))538// // or equally539// td.Cmp(t, `{"foo":1}`, td.Smuggle(json.RawMessage(nil), td.JSON(`{"foo":1}`)))540//541// converts on the fly a string to a [json.RawMessage] so [JSON] operator542// can parse it as JSON. This is mostly a shortcut for:543//544// td.Cmp(t, `{"foo":1}`, td.Smuggle(545// func(r json.RawMessage) json.RawMessage { return r },546// td.JSON(`{"foo":1}`)))547//548// except that for strings and slices of bytes (like here), it accepts549// [io.Reader] interface too:550//551// var body io.Reader552// // …553// td.Cmp(t, body, td.Smuggle(json.RawMessage{}, td.JSON(`{"foo":1}`)))554// // or equally555// td.Cmp(t, body, td.Smuggle(json.RawMessage(nil), td.JSON(`{"foo":1}`)))556//557// This last example allows to easily inject body content into JSON558// operator.559//560// The difference between Smuggle and [Code] operators is that [Code]561// is used to do a final comparison while Smuggle transforms the data562// and then steps down in favor of generic comparison563// process. Moreover, the type accepted as input for the function is564// more lax to facilitate the writing of tests (e.g. the function can565// accept a float64 and the got value be an int). See examples. On the566// other hand, the output type is strict and must match exactly the567// expected value type. The fields-path string fn shortcut and the568// cast feature are not available with [Code] operator.569//570// TypeBehind method returns the [reflect.Type] of only parameter of571// fn. For the case where fn is a fields-path, it is always572// any, as the type can not be known in advance.573//574// See also [Code] and [JSONPointer].575//576// [json.RawMessage]: https://pkg.go.dev/encoding/json#RawMessage577func Smuggle(fn, expectedValue any) TestDeep {578 s := tdSmuggle{579 tdSmugglerBase: newSmugglerBase(expectedValue),580 }581 const usage = "(FUNC|FIELDS_PATH|ANY_TYPE, TESTDEEP_OPERATOR|EXPECTED_VALUE)"582 const fullUsage = "Smuggle" + usage583 var vfn reflect.Value584 switch rfn := fn.(type) {585 case reflect.Type:586 switch rfn.Kind() {587 case reflect.Func, reflect.Invalid, reflect.Interface:588 s.err = ctxerr.OpBad("Smuggle",589 "usage: Smuggle%s, ANY_TYPE reflect.Type cannot be Func nor Interface", usage)590 return &s591 default:592 vfn = getCaster(rfn)593 }594 case string:595 if rfn == "" {596 vfn = getCaster(reflect.TypeOf(fn))597 break598 }599 var err error600 vfn, err = getFieldsPathFn(rfn)601 if err != nil {602 s.err = ctxerr.OpBad("Smuggle", "Smuggle%s: %s", usage, err)603 return &s604 }605 default:606 vfn = reflect.ValueOf(fn)607 switch vfn.Kind() {608 case reflect.Func:609 // nothing to check610 case reflect.Invalid, reflect.Interface:611 s.err = ctxerr.OpBad("Smuggle",612 "usage: Smuggle%s, ANY_TYPE cannot be nil nor Interface", usage)613 return &s614 default:...

Full Screen

Full Screen

getFieldsPathFn

Using AI Code Generation

copy

Full Screen

1import "fmt"2type td struct {3}4func (t td) getFieldsPathFn() func() string {5 return func() string {6 }7}8func main() {9 t := td{name: "test", fields: []string{"a", "b", "c"}}

Full Screen

Full Screen

getFieldsPathFn

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 td := &TableData{}4 td.getFieldsPathFn()5}6import (7func main() {8 td := &TableData{}9 td.getFieldsPathFn()10}11import (12func main() {13 td := &TableData{}14 td.getFieldsPathFn()15}16import (17func main() {18 td := &TableData{}19 td.getFieldsPathFn()20}21import (22func main() {23 td := &TableData{}24 td.getFieldsPathFn()25}26import (27func main() {28 td := &TableData{}29 td.getFieldsPathFn()30}31import (32func main() {33 td := &TableData{}34 td.getFieldsPathFn()35}36import (37func main() {38 td := &TableData{}39 td.getFieldsPathFn()40}41import (42func main() {43 td := &TableData{}44 td.getFieldsPathFn()45}

Full Screen

Full Screen

getFieldsPathFn

Using AI Code Generation

copy

Full Screen

1func main() {2 td := NewTrieData()3 td.Add("a", "b", "c", "d")4 td.Add("a", "b", "c", "e")5 td.Add("a", "b", "c", "f")6 td.Add("a", "b", "c", "g")7 td.Add("a", "b", "c", "h")8 td.Add("a", "b", "c", "i")9 td.Add("a", "b", "c", "j")10 td.Add("a", "b", "c", "k")11 td.Add("a", "b", "c", "l")12 td.Add("a", "b", "c", "m")13 td.Add("a", "b", "c", "n")14 td.Add("a", "b", "c", "o")15 td.Add("a", "b", "c", "p")16 td.Add("a", "b", "c", "q")17 td.Add("a", "b", "c", "r")18 td.Add("a", "b", "c", "s")19 td.Add("a", "b", "c", "t")20 td.Add("a", "b", "c", "u")21 td.Add("a", "b", "c", "v")22 td.Add("a", "b", "c", "w")23 td.Add("a", "b", "c", "x")24 td.Add("a", "b", "c", "y")25 td.Add("a", "b", "c", "z")26 td.Add("a", "b", "c", "1")27 td.Add("a", "b", "c", "2")28 td.Add("a", "b", "c", "3")29 td.Add("a", "b", "c", "4")30 td.Add("a", "b", "c", "5")31 td.Add("a", "b", "c", "6")32 td.Add("a", "b", "c", "7")33 td.Add("a", "b", "c", "8")34 td.Add("a", "b", "c", "9")35 td.Add("a",

Full Screen

Full Screen

getFieldsPathFn

Using AI Code Generation

copy

Full Screen

1import (2type td struct {3}4func (t td) getFieldsPathFn() []string {5 tt := reflect.TypeOf(t)6 for i := 0; i < tt.NumField(); i++ {7 path = append(path, tt.Field(i).Name)8 }9}10func main() {11 t := td{A: 1, B: 2}12 fmt.Println(t.getFieldsPathFn())13}

Full Screen

Full Screen

getFieldsPathFn

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 td := NewTypeDescriptor(reflect.TypeOf(Example{}))4 example := Example{5 }6 fieldsPath := td.GetFieldsPath(example)7 fmt.Println(fieldsPath)8}9type Example struct {10}

Full Screen

Full Screen

getFieldsPathFn

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 tdObj := td.New()4 fields, err := tdObj.GetFieldsPathFn(path)5 if err != nil {6 fmt.Println("error in getting fields")7 }8 fmt.Println(fields)9}10Example 3: Get Fields in a given path (using tdlib package)11import (12func main() {13 tdObj := tdlib.New()14 fields, err := tdObj.GetFieldsPathFn(path)15 if err != nil {16 fmt.Println("error in getting fields")17 }18 fmt.Println(fields)19}20Example 4: Get Fields in a given path (using td package)21import (22func main() {23 tdObj := td.New()24 fields, err := tdObj.GetFieldsPathFn(path)25 if err != nil {26 fmt.Println("error in getting fields")27 }

Full Screen

Full Screen

getFieldsPathFn

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 getFieldsPathFn := func(fields ...string) func([]byte, []byte, jsonparser.ValueType, int) error {4 return func(data []byte, dataType []byte, offset int, err error) error {5 for _, field := range fields {6 data, dataType, offset, err = jsonparser.Get(data, field)7 if err != nil {8 }9 }10 fmt.Println(string(data))11 }12 }13 jsonData := []byte(`{14 "address": {15 },16 {17 },18 {19 }20 }`)21 jsonparser.ObjectEach(jsonData, getFieldsPathFn("name"))22 jsonparser.ObjectEach(jsonData, getFieldsPathFn("address", "street"))23 jsonparser.ObjectEach(jsonData, getFieldsPathFn("phoneNumbers", "0", "number"))24}25import (26func main() {27 getFieldsPathFn := func(fields ...string) func([]byte, []byte, jsonparser.Value

Full Screen

Full Screen

getFieldsPathFn

Using AI Code Generation

copy

Full Screen

1func main() {2 td := td.New()3 path := td.GetFieldsPathFn(&testStruct{})4 fmt.Println(path)5}6func main() {7 td := td.New()8 path := td.GetFieldsPathFn(&testStruct{})9 fmt.Println(path)10}11func main() {12 td := td.New()13 path := td.GetFieldsPathFn(&testStruct{})14 fmt.Println(path)15}16func main() {17 td := td.New()18 path := td.GetFieldsPathFn(&testStruct{})19 fmt.Println(path)20}21func main() {22 td := td.New()23 path := td.GetFieldsPathFn(&testStruct{})24 fmt.Println(path)25}26func main() {27 td := td.New()28 path := td.GetFieldsPathFn(&testStruct{})29 fmt.Println(path)30}

Full Screen

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Go-testdeep automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful