| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package fidlgen_cpp |
| |
| import ( |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| "go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgentest" |
| ) |
| |
| func TestCompileTypeNames(t *testing.T) { |
| root := compile(fidlgentest.EndToEndTest{T: t}.Single(` |
| library foo.bar; |
| |
| type U = union { |
| 1: a uint32; |
| }; |
| |
| protocol P { |
| M(resource struct { a array<U:optional, 3>; b vector<client_end:<P, optional>>; }); |
| }; |
| `), HeaderOptions{}) |
| p := onlyProtocol(t, root) |
| assertEqual(t, len(p.Methods), 1) |
| m := p.Methods[0] |
| assertEqual(t, len(m.RequestArgs), 2) |
| |
| ty := m.RequestArgs[0].Type |
| expectEqual(t, ty.Natural.String(), "::std::array<::std::unique_ptr<::foo::bar::U>, 3>") |
| expectEqual(t, ty.Wire.String(), "::fidl::Array<::foo_bar::wire::U, 3>") |
| expectEqual(t, ty.Unified.String(), "::std::array<::std::unique_ptr<::foo_bar::U>, 3>") |
| |
| ty = m.RequestArgs[1].Type |
| expectEqual(t, ty.Natural.String(), "::std::vector<::fidl::InterfaceHandle<::foo::bar::P>>") |
| expectEqual(t, ty.Wire.String(), "::fidl::VectorView<::fidl::ClientEnd<::foo_bar::P>>") |
| // TODO(fxbug.dev/72980): Switch to ClientEnd/ServerEnd and underscore namespace when |
| // corresponding endpoint types can easily convert into each other. |
| expectEqual(t, ty.Unified.String(), "::std::vector<::fidl::InterfaceHandle<::foo::bar::P>>") |
| } |
| |
| func makeTestName(s string) nameVariants { |
| return nameVariants{ |
| Natural: makeName("example::" + s), |
| Unified: makeName("example::" + s), |
| Wire: makeName("example::wire::" + s), |
| } |
| } |
| |
| func TestAnonymousLayoutAliases(t *testing.T) { |
| currentVariant = wireVariant |
| |
| cases := []struct { |
| desc string |
| fidl string |
| expected map[namingContextKey][]ScopedLayout |
| }{ |
| { |
| desc: "single struct", |
| fidl: "type Foo = struct { bar struct {}; };", |
| expected: map[namingContextKey][]ScopedLayout{ |
| "Foo": {{ |
| scopedName: stringNamePart("Bar"), |
| flattenedName: makeTestName("Bar"), |
| }}, |
| }, |
| }, |
| { |
| desc: "request", |
| fidl: ` |
| protocol MyProtocol { |
| MyMethod(struct { req_data struct {}; }); |
| }; |
| `, |
| expected: map[namingContextKey][]ScopedLayout{ |
| "MyMethodRequest": {{ |
| scopedName: stringNamePart("ReqData"), |
| flattenedName: makeTestName("ReqData"), |
| }}, |
| }, |
| }, |
| { |
| desc: "result", |
| fidl: ` |
| protocol MyProtocol { |
| MyMethod() -> (struct {}) error enum : uint32 { FOO = 1; }; |
| }; |
| `, |
| expected: map[namingContextKey][]ScopedLayout{ |
| "MyMethodResponse": {{ |
| scopedName: stringNamePart("Result"), |
| flattenedName: makeTestName("MyProtocolMyMethodResult"), |
| }}, |
| "MyProtocolMyMethodResult": { |
| { |
| scopedName: stringNamePart("Err"), |
| flattenedName: makeTestName("MyProtocolMyMethodError"), |
| }, |
| { |
| scopedName: stringNamePart("Response"), |
| flattenedName: makeTestName("MyProtocolMyMethodResponse"), |
| }, |
| }, |
| }, |
| }, |
| { |
| desc: "expression", |
| fidl: ` |
| type Expression = flexible union { |
| 1: value uint64; |
| 2: bin_op struct { |
| op flexible enum { |
| ADD = 1; |
| SUB = 2; |
| }; |
| left Expression:optional; |
| right Expression:optional; |
| }; |
| 3: flags bits { |
| FLAGS_A = 1; |
| }; |
| }; |
| `, |
| expected: map[namingContextKey][]ScopedLayout{ |
| "Expression": { |
| { |
| scopedName: stringNamePart("Flags"), |
| flattenedName: makeTestName("Flags"), |
| }, |
| { |
| scopedName: stringNamePart("BinOp"), |
| flattenedName: makeTestName("BinOp"), |
| }, |
| }, |
| "BinOp": {{ |
| scopedName: stringNamePart("Op"), |
| flattenedName: makeTestName("Op"), |
| }}, |
| }, |
| }, |
| } |
| for _, ex := range cases { |
| t.Run(ex.desc, func(t *testing.T) { |
| root := compile(fidlgentest.EndToEndTest{T: t}.Single("library example; "+ex.fidl), |
| HeaderOptions{}) |
| |
| layoutToChildren := make(map[namingContextKey][]ScopedLayout) |
| for _, decl := range root.Decls { |
| switch d := decl.(type) { |
| case Struct: |
| if len(d.AnonymousChildren) > 0 { |
| layoutToChildren[d.Name()] = d.AnonymousChildren |
| } |
| case Union: |
| if len(d.AnonymousChildren) > 0 { |
| layoutToChildren[d.Name()] = d.AnonymousChildren |
| } |
| case Table: |
| if len(d.AnonymousChildren) > 0 { |
| layoutToChildren[d.Name()] = d.AnonymousChildren |
| } |
| case Protocol: |
| for _, m := range d.Methods { |
| if len(m.RequestAnonymousChildren) > 0 { |
| layoutToChildren[m.Name()+"Request"] = m.RequestAnonymousChildren |
| } |
| if len(m.ResponseAnonymousChildren) > 0 { |
| layoutToChildren[m.Name()+"Response"] = m.ResponseAnonymousChildren |
| } |
| } |
| } |
| } |
| |
| if !cmp.Equal(layoutToChildren, ex.expected, cmp.Comparer(func(x, y ScopedLayout) bool { |
| return x.ScopedName() == y.ScopedName() && x.FlattenedName() == y.FlattenedName() |
| })) { |
| t.Error(cmp.Diff(layoutToChildren, ex.expected)) |
| } |
| }) |
| } |
| } |