// Find returns the node for the given ID. func (m *Map) Find(id uint64) (schema.Node, error) { if n := m.nodes[id]; n.IsValid() { return n, nil } data, err := m.registry().Find(id) if err != nil { return schema.Node{}, err } msg, err := capnp.Unmarshal(data) if err != nil { return schema.Node{}, err } req, err := schema.ReadRootCodeGeneratorRequest(msg) if err != nil { return schema.Node{}, err } nodes, err := req.Nodes() if err != nil { return schema.Node{}, err } if m.nodes == nil { m.nodes = make(map[uint64]schema.Node) } for i := 0; i < nodes.Len(); i++ { n := nodes.At(i) m.nodes[n.Id()] = n } return m.nodes[id], nil }
func TestDefaultFind(t *testing.T) { if s := schemas.Find(0xdeadbeef); s != nil { t.Errorf("schemas.Find(0xdeadbeef) = %d-byte slice; want nil", len(s)) } s := schemas.Find(capnp.Package) if s == nil { t.Fatalf("schemas.Find(%#x) = nil", capnp.Package) } msg, err := capnp.Unmarshal(s) if err != nil { t.Fatalf("capnp.Unmarshal(schemas.Find(%#x)) error: %v", capnp.Package, err) } req, err := schema.ReadRootCodeGeneratorRequest(msg) if err != nil { t.Fatalf("ReadRootCodeGeneratorRequest error: %v", err) } nodes, err := req.Nodes() if err != nil { t.Fatalf("req.Nodes() error: %v", err) } for i := 0; i < nodes.Len(); i++ { n := nodes.At(i) if n.Id() == capnp.Package { // Found if n.Which() != schema.Node_Which_annotation { t.Errorf("found node %#x which = %v; want annotation", capnp.Package, n.Which()) } return } } t.Fatalf("could not find node %#x in registry", capnp.Package) }
func mustReadGeneratorRequest(t *testing.T, name string) schema.CodeGeneratorRequest { data := mustReadTestFile(t, name) msg, err := capnp.Unmarshal(data) if err != nil { t.Fatalf("Unmarshaling %s: %v", name, err) } req, err := schema.ReadRootCodeGeneratorRequest(msg) if err != nil { t.Fatalf("Reading code generator request %s: %v", name, err) } return req }
func main() { var opts genoptions flag.BoolVar(&opts.promises, "promises", true, "generate code for promises") flag.BoolVar(&opts.schemas, "schemas", true, "embed schema information in generated code") flag.BoolVar(&opts.structStrings, "structstrings", true, "generate String() methods for structs (-schemas must be true)") flag.Parse() msg, err := capnp.NewDecoder(os.Stdin).Decode() if err != nil { fmt.Fprintln(os.Stderr, "capnpc-go: reading input:", err) os.Exit(1) } req, err := schema.ReadRootCodeGeneratorRequest(msg) if err != nil { fmt.Fprintln(os.Stderr, "capnpc-go: reading input:", err) os.Exit(1) } nodes, err := buildNodeMap(req) if err != nil { fmt.Fprintln(os.Stderr, "capnpc-go:", err) os.Exit(1) } success := true reqFiles, _ := req.RequestedFiles() for i := 0; i < reqFiles.Len(); i++ { reqf := reqFiles.At(i) err := generateFile(reqf, nodes, opts) if err != nil { fname, _ := reqf.Filename() fmt.Fprintf(os.Stderr, "capnpc-go: generating %s: %v\n", fname, err) success = false } } if !success { os.Exit(1) } }
func TestEncode(t *testing.T) { tests := []struct { constID uint64 text string }{ {0xc0b634e19e5a9a4e, `(key = "42", value = (int32 = -123))`}, {0x967c8fe21790b0fb, `(key = "float", value = (float64 = 3.14))`}, {0xdf35cb2e1f5ea087, `(key = "bool", value = (bool = false))`}, {0xb167974479102805, `(map = [(key = "foo", value = (void = void)), (key = "bar", value = (void = void))])`}, {0x81fdbfdc91779421, `(map = [])`}, {0x8e85252144f61858, `(data = "Hi\xde\xad\xbe\xef\xca\xfe")`}, {0xc21398a8474837ba, `(voidList = [void, void])`}, {0xde82c2eeb3a4b07c, `(boolList = [true, false, true, false])`}, {0xf9e3ffc179272aa2, `(int8List = [1, -2, 3])`}, {0xfc421b96ec6ad2b6, `(int64List = [1, -2, 3])`}, {0xb3034b89d02775a5, `(uint8List = [255, 0, 1])`}, {0x9246c307e46ad03b, `(uint64List = [1, 2, 3])`}, {0xd012128a1a9cb7fc, `(float32List = [0.5, 3.14, -2])`}, {0xf16c386c66d492e2, `(textList = ["foo", "bar", "baz"])`}, {0xe14f4d42aa55de8c, `(dataList = ["\xde\xad\xbe\xef", "\xca\xfe"])`}, {0xe88c91698f7f0b73, `(cheese = gouda)`}, {0x9c51b843b337490b, `(cheeseList = [gouda, cheddar])`}, {0x81e2aadb8bfb237b, `(matrix = [[1, 2, 3], [4, 5, 6]])`}, } data, err := readTestFile("txt.capnp.out") if err != nil { t.Fatal(err) } reg := new(schemas.Registry) err = reg.Register(&schemas.Schema{ Bytes: data, Nodes: []uint64{ 0x8df8bc5abdc060a6, 0xd3602730c572a43b, }, }) if err != nil { t.Fatalf("Adding to registry: %v", err) } msg, err := capnp.Unmarshal(data) if err != nil { t.Fatal("Unmarshaling txt.capnp.out:", err) } req, err := schema.ReadRootCodeGeneratorRequest(msg) if err != nil { t.Fatal("Reading code generator request txt.capnp.out:", err) } nodes, err := req.Nodes() if err != nil { t.Fatal(err) } nodeMap := make(map[uint64]schema.Node, nodes.Len()) for i := 0; i < nodes.Len(); i++ { n := nodes.At(i) nodeMap[n.Id()] = n } for _, test := range tests { c := nodeMap[test.constID] if !c.IsValid() { t.Errorf("Can't find node %#x; skipping", test.constID) continue } dn, _ := c.DisplayName() if c.Which() != schema.Node_Which_const { t.Errorf("%s @%#x is a %v, not const; skipping", dn, test.constID, c.Which()) continue } typ, err := c.Const().Type() if err != nil { t.Errorf("(%s @%#x).const.type: %v", dn, test.constID, err) continue } if typ.Which() != schema.Type_Which_structType { t.Errorf("(%s @%#x).const.type is a %v; want struct", dn, test.constID, typ.Which()) continue } tid := typ.StructType().TypeId() v, err := c.Const().Value() if err != nil { t.Errorf("(%s @%#x).const.value: %v", dn, test.constID, err) continue } if v.Which() != schema.Value_Which_structValue { t.Errorf("(%s @%#x).const.value is a %v; want struct", dn, test.constID, v.Which()) continue } sv, err := v.StructValuePtr() if err != nil { t.Errorf("(%s @%#x).const.value.struct: %v", dn, test.constID, err) continue } buf := new(bytes.Buffer) enc := NewEncoder(buf) enc.UseRegistry(reg) if err := enc.Encode(tid, sv.Struct()); err != nil { t.Errorf("Encode(%#x, (%s @%#x).const.value.struct): %v", tid, dn, test.constID, err) continue } if text := buf.String(); text != test.text { t.Errorf("Encode(%#x, (%s @%#x).const.value.struct) = %q; want %q", tid, dn, test.constID, text, test.text) continue } } }
func TestBuildNodeMap(t *testing.T) { tests := []struct { name string fileID uint64 fileNodes []uint64 }{ { name: "go.capnp.out", fileID: 0xd12a1c51fedd6c88, fileNodes: []uint64{ 0xbea97f1023792be0, 0xe130b601260e44b5, 0xc58ad6bd519f935e, 0xa574b41924caefc7, 0xc8768679ec52e012, 0xfa10659ae02f2093, 0xc2b96012172f8df1, }, }, { name: "group.capnp.out", fileID: 0x83c2b5818e83ab19, fileNodes: []uint64{ 0xd119fd352d8ea888, // the struct 0x822357857e5925d4, // the group }, }, } for _, test := range tests { data, err := readTestFile(test.name) if err != nil { t.Errorf("readTestFile(%q): %v", test.name, err) continue } msg, err := capnp.Unmarshal(data) if err != nil { t.Errorf("Unmarshaling %s: %v", test.name, err) continue } req, err := schema.ReadRootCodeGeneratorRequest(msg) if err != nil { t.Errorf("Reading code generator request %s: %v", test.name, err) continue } nodes, err := buildNodeMap(req) if err != nil { t.Errorf("%s: buildNodeMap: %v", test.name, err) } f := nodes[test.fileID] if f == nil { t.Errorf("%s: node map is missing file node @%#x", test.name, test.fileID) continue } if f.Id() != test.fileID { t.Errorf("%s: node map has ID @%#x for lookup of @%#x", test.name, f.Id(), test.fileID) } // Test node.nodes collection for _, id := range test.fileNodes { found := false for _, fn := range f.nodes { if fn.Id() == id { found = true break } } if !found { t.Errorf("%s: missing @%#x from file nodes", test.name, id) } } // Test map lookup for _, k := range test.fileNodes { n := nodes[k] if n == nil { t.Errorf("%s: missing @%#x from node map", test.name, k) } if n.Id() != k { t.Errorf("%s: node map has ID @%#x for lookup of @%#x", test.name, n.Id(), k) } } } }
func TestDefineFile(t *testing.T) { // Sanity check to make sure codegen produces parseable Go. const iterations = 3 defaultOptions := genoptions{ promises: true, schemas: true, structStrings: true, } tests := []struct { fileID uint64 fname string opts genoptions }{ {0x832bcc6686a26d56, "aircraft.capnp.out", defaultOptions}, {0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{ promises: false, schemas: false, structStrings: false, }}, {0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{ promises: true, schemas: false, structStrings: false, }}, {0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{ promises: false, schemas: true, structStrings: false, }}, {0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{ promises: true, schemas: true, structStrings: false, }}, {0x832bcc6686a26d56, "aircraft.capnp.out", genoptions{ promises: false, schemas: true, structStrings: true, }}, {0x83c2b5818e83ab19, "group.capnp.out", defaultOptions}, {0xb312981b2552a250, "rpc.capnp.out", defaultOptions}, {0xd68755941d99d05e, "scopes.capnp.out", defaultOptions}, {0xecd50d792c3d9992, "util.capnp.out", defaultOptions}, } for _, test := range tests { data, err := readTestFile(test.fname) if err != nil { t.Errorf("reading %s: %v", test.fname, err) continue } msg, err := capnp.Unmarshal(data) if err != nil { t.Errorf("Unmarshaling %s: %v", test.fname, err) continue } req, err := schema.ReadRootCodeGeneratorRequest(msg) if err != nil { t.Errorf("Reading code generator request %s: %v", test.fname, err) continue } nodes, err := buildNodeMap(req) if err != nil { t.Errorf("buildNodeMap %s: %v", test.fname, err) continue } g := newGenerator(test.fileID, nodes, test.opts) if err := g.defineFile(); err != nil { t.Errorf("defineFile %s %+v: %v", test.fname, test.opts, err) continue } src := g.generate() if _, err := parser.ParseFile(token.NewFileSet(), test.fname+".go", src, 0); err != nil { // TODO(light): log src t.Errorf("generate %s %+v failed to parse: %v", test.fname, test.opts, err) } // Generation should be deterministic between runs. for i := 0; i < iterations-1; i++ { g := newGenerator(test.fileID, nodes, test.opts) if err := g.defineFile(); err != nil { t.Errorf("defineFile %s %+v [iteration %d]: %v", test.fname, test.opts, i+2, err) continue } src2 := g.generate() if !bytes.Equal(src, src2) { t.Errorf("defineFile %s %+v [iteration %d] did not match iteration 1: non-deterministic", test.fname, test.opts, i+2) } } } }