github.com/ipld/go-ipld-prime@v0.21.0/node/tests/schemaLinks.go (about) 1 package tests 2 3 import ( 4 "bytes" 5 "fmt" 6 "testing" 7 8 qt "github.com/frankban/quicktest" 9 10 "github.com/ipfs/go-cid" 11 "github.com/ipld/go-ipld-prime/codec/dagjson" 12 "github.com/ipld/go-ipld-prime/datamodel" 13 "github.com/ipld/go-ipld-prime/fluent" 14 "github.com/ipld/go-ipld-prime/linking" 15 cidlink "github.com/ipld/go-ipld-prime/linking/cid" 16 "github.com/ipld/go-ipld-prime/node/basicnode" 17 "github.com/ipld/go-ipld-prime/schema" 18 "github.com/ipld/go-ipld-prime/storage/memstore" 19 "github.com/ipld/go-ipld-prime/traversal" 20 "github.com/ipld/go-ipld-prime/traversal/selector" 21 "github.com/ipld/go-ipld-prime/traversal/selector/builder" 22 ) 23 24 var store = memstore.Store{} 25 26 func encode(n datamodel.Node) (datamodel.Node, datamodel.Link) { 27 lp := cidlink.LinkPrototype{Prefix: cid.Prefix{ 28 Version: 1, 29 Codec: 0x0129, 30 MhType: 0x13, 31 MhLength: 4, 32 }} 33 lsys := cidlink.DefaultLinkSystem() 34 lsys.SetWriteStorage(&store) 35 36 lnk, err := lsys.Store(linking.LinkContext{}, lp, n) 37 if err != nil { 38 panic(err) 39 } 40 return n, lnk 41 } 42 43 func SchemaTestLinks(t *testing.T, engine Engine) { 44 ts := schema.TypeSystem{} 45 ts.Init() 46 ts.Accumulate(schema.SpawnInt("Int")) 47 ts.Accumulate(schema.SpawnString("String")) 48 ts.Accumulate(schema.SpawnList("ListOfStrings", "String", false)) 49 50 ts.Accumulate(schema.SpawnLink("Link")) // &Any 51 ts.Accumulate(schema.SpawnLinkReference("IntLink", "Int")) // &Int 52 ts.Accumulate(schema.SpawnLinkReference("StringLink", "String")) // &String 53 ts.Accumulate(schema.SpawnLinkReference("ListOfStringsLink", "ListOfStrings")) // &ListOfStrings 54 55 ts.Accumulate(schema.SpawnStruct("LinkStruct", 56 []schema.StructField{ 57 schema.SpawnStructField("any", "Link", false, false), 58 schema.SpawnStructField("int", "IntLink", false, false), 59 schema.SpawnStructField("str", "StringLink", false, false), 60 schema.SpawnStructField("strlist", "ListOfStringsLink", false, false), 61 }, 62 schema.SpawnStructRepresentationMap(map[string]string{}), 63 )) 64 65 engine.Init(t, ts) 66 67 t.Run("typed linkage traversal", func(t *testing.T) { 68 _, intNodeLnk := func() (datamodel.Node, datamodel.Link) { 69 np := engine.PrototypeByName("Int") 70 nb := np.NewBuilder() 71 nb.AssignInt(101) 72 return encode(nb.Build()) 73 }() 74 _, stringNodeLnk := encode(fluent.MustBuild(engine.PrototypeByName("String"), func(na fluent.NodeAssembler) { 75 na.AssignString("a string") 76 })) 77 _, listOfStringsNodeLnk := encode(fluent.MustBuildList(engine.PrototypeByName("ListOfStrings"), 3, func(la fluent.ListAssembler) { 78 la.AssembleValue().AssignString("s1") 79 la.AssembleValue().AssignString("s2") 80 la.AssembleValue().AssignString("s3") 81 })) 82 linkStructNode, _ := encode(fluent.MustBuildMap(engine.PrototypeByName("LinkStruct"), 4, func(ma fluent.MapAssembler) { 83 ma.AssembleEntry("any").AssignLink(stringNodeLnk) 84 ma.AssembleEntry("int").AssignLink(intNodeLnk) 85 ma.AssembleEntry("str").AssignLink(stringNodeLnk) 86 ma.AssembleEntry("strlist").AssignLink(listOfStringsNodeLnk) 87 })) 88 89 ssb := builder.NewSelectorSpecBuilder(basicnode.Prototype.Any) 90 ss := ssb.ExploreRecursive(selector.RecursionLimitDepth(3), ssb.ExploreUnion( 91 ssb.Matcher(), 92 ssb.ExploreAll(ssb.ExploreRecursiveEdge()), 93 )) 94 s, err := ss.Selector() 95 qt.Check(t, err, qt.IsNil) 96 97 var order int 98 lsys := cidlink.DefaultLinkSystem() 99 lsys.SetReadStorage(&store) 100 err = traversal.Progress{ 101 Cfg: &traversal.Config{ 102 LinkSystem: lsys, 103 LinkTargetNodePrototypeChooser: func(lnk datamodel.Link, lnkCtx linking.LinkContext) (datamodel.NodePrototype, error) { 104 if tlnkNd, ok := lnkCtx.LinkNode.(schema.TypedLinkNode); ok { 105 return tlnkNd.LinkTargetNodePrototype(), nil 106 } 107 return basicnode.Prototype.Any, nil 108 }, 109 }, 110 }.WalkMatching(linkStructNode, s, func(prog traversal.Progress, n datamodel.Node) error { 111 buf := new(bytes.Buffer) 112 dagjson.Encode(n, buf) 113 fmt.Printf("Walked %d: %v\n", order, buf.String()) 114 switch order { 115 case 0: // root 116 qt.Check(t, n.Prototype(), qt.Equals, engine.PrototypeByName("LinkStruct")) 117 case 1: // from an &Any 118 qt.Check(t, n.Prototype(), qt.Equals, basicnode.Prototype__String{}) 119 case 2: // &Int 120 qt.Check(t, n.Prototype(), qt.Equals, engine.PrototypeByName("Int")) 121 case 3: // &String 122 qt.Check(t, n.Prototype(), qt.Equals, engine.PrototypeByName("String")) 123 case 4: // &ListOfStrings 124 qt.Check(t, n.Prototype(), qt.Equals, engine.PrototypeByName("ListOfStrings")) 125 case 5: 126 fallthrough 127 case 6: 128 fallthrough 129 case 7: 130 qt.Check(t, n.Prototype(), qt.Equals, engine.PrototypeByName("String")) 131 } 132 order++ 133 return nil 134 }) 135 qt.Check(t, err, qt.IsNil) 136 qt.Check(t, order, qt.Equals, 8) 137 }) 138 }