blob: 82606646c256c6895f1e9c70d79ed246896d7e2c [file] [log] [blame]
// 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 summarize
import (
"io"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgen"
"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgentest"
)
var (
// zxLibrary is a shortened version of zx_common.fidl, for tests.
zxLibrary = `
library zx;
type obj_type = enum : uint32 {
CHANNEL = 4;
};
resource_definition handle : uint32 {
properties {
subtype obj_type;
};
};
`
// l2Library is a sample dependency taken in by some tests.
l2Library = `library l2; type T = struct {};`
)
type summaryTestCase struct {
name string
fidl string
dep string
expected string
}
func TestWrite(t *testing.T) {
tests := []summaryTestCase{
{
name: "library only",
fidl: `library l;`,
expected: `library l
`,
},
{
name: "primitives 1",
fidl: `
library l;
const OFFSET int8 = -33;
const ENABLED_FLAG bool = true;
`,
expected: `const l/ENABLED_FLAG bool true
const l/OFFSET int8 -33
library l
`,
},
{
// Same as above, except reordered.
name: "primitives 2",
fidl: `
library l;
const ENABLED_FLAG bool = true;
const OFFSET int8 = -33;
`,
expected: `const l/ENABLED_FLAG bool true
const l/OFFSET int8 -33
library l
`,
},
{
name: "primitives 3",
fidl: `
library l;
const ANSWER uint16 = 42;
const ANSWER_IN_BINARY uint16 = 0b101010;
`,
expected: `const l/ANSWER uint16 42
const l/ANSWER_IN_BINARY uint16 42
library l
`,
},
{
name: "primitives 4",
fidl: `
library l;
const ENABLED_FLAG bool = true;
const OFFSET int8 = -33;
const ANSWER uint16 = 42;
const ANSWER_IN_BINARY uint16 = 0b101010;
const POPULATION_USA_2018 uint32 = 330000000;
const DIAMOND uint64 = 0x183c7effff7e3c18;
const FUCHSIA uint64 = 4054509061583223046;
const USERNAME string = "squeenze";
const MIN_TEMP float32 = -273.15;
const CONVERSION_FACTOR float64 = 1.41421358;
`,
expected: `const l/ANSWER uint16 42
const l/ANSWER_IN_BINARY uint16 42
const l/CONVERSION_FACTOR float64 1.41421
const l/DIAMOND uint64 1746410393481133080
const l/ENABLED_FLAG bool true
const l/FUCHSIA uint64 4054509061583223046
const l/MIN_TEMP float32 -273.15
const l/OFFSET int8 -33
const l/POPULATION_USA_2018 uint32 330000000
const l/USERNAME string "squeenze"
library l
`,
},
{
name: "primitives 5, binary operator",
fidl: `
library l;
const FOO uint8 = 1;
const BAR uint8 = 2;
const BAZ uint8 = FOO | BAR;
`,
expected: `const l/BAR uint8 2
const l/BAZ uint8 3
const l/FOO uint8 1
library l
`,
},
{
name: "bits",
fidl: `
library l;
type Bits1 = strict bits {
BIT1 = 0x01;
BIT2 = 0x02;
};
`,
expected: `bits/member l/Bits1.BIT1 1
bits/member l/Bits1.BIT2 2
strict bits l/Bits1 uint32
library l
`,
},
{
name: "bits 2",
fidl: `
library l;
type Bits1 = strict bits {
BIT1 = 0x01;
BIT2 = 0x02;
};
type Bits2 = strict bits {
BIT1 = 0x01;
BIT2 = 0x02;
};
`,
expected: `bits/member l/Bits1.BIT1 1
bits/member l/Bits1.BIT2 2
strict bits l/Bits1 uint32
bits/member l/Bits2.BIT1 1
bits/member l/Bits2.BIT2 2
strict bits l/Bits2 uint32
library l
`,
},
{
name: "bits 3",
fidl: `
library l;
type Bits = flexible bits : uint8 {
BIT1 = 0x01;
BIT2 = 0x02;
};
`,
expected: `bits/member l/Bits.BIT1 1
bits/member l/Bits.BIT2 2
flexible bits l/Bits uint8
library l
`,
},
{
name: "enums",
fidl: `
library l;
type Beverage = flexible enum : uint8 {
WATER = 0;
COFFEE = 1;
TEA = 2;
WHISKEY = 3;
};
// Underlying type is assumed to be uint32.
type Vessel = strict enum {
CUP = 0;
BOWL = 1;
TUREEN = 2;
JUG = 3;
};
`,
expected: `enum/member l/Beverage.COFFEE 1
enum/member l/Beverage.TEA 2
enum/member l/Beverage.WATER 0
enum/member l/Beverage.WHISKEY 3
flexible enum l/Beverage uint8
enum/member l/Vessel.BOWL 1
enum/member l/Vessel.CUP 0
enum/member l/Vessel.JUG 3
enum/member l/Vessel.TUREEN 2
strict enum l/Vessel uint32
library l
`,
},
{
name: "struct as precondition for arrays",
fidl: `
library l;
type S = struct {
x float32;
};
`,
expected: `struct/member l/S.x float32
struct l/S
library l
`,
},
{
name: "struct with an element with default value",
fidl: `
library l;
const VALUE string = "booyah!";
type S = struct {
x float32 = 0.314159;
foo string = "huzzah";
bar bool = true;
baz string = VALUE;
};
`,
expected: `struct/member l/S.bar bool true
struct/member l/S.baz string "booyah!"
struct/member l/S.foo string "huzzah"
struct/member l/S.x float32 0.314159
struct l/S
const l/VALUE string "booyah!"
library l
`,
},
{
name: "struct with an element with default value",
fidl: `
library l;
const VALUE string = "booyah!";
type S = struct {
x float32 = 0.314159;
foo string = "huzzah";
bar bool = true;
baz string = VALUE;
};
`,
expected: `struct/member l/S.bar bool true
struct/member l/S.baz string "booyah!"
struct/member l/S.foo string "huzzah"
struct/member l/S.x float32 0.314159
struct l/S
const l/VALUE string "booyah!"
library l
`,
},
{
name: "arrays",
fidl: `
library l;
type Arrays = struct {
form array<float32, 16>;
matrix array<array<string, 4>, 10>;
};
`,
expected: `struct/member l/Arrays.form array<float32,16>
struct/member l/Arrays.matrix array<array<string,4>,10>
struct l/Arrays
library l
`,
},
{
name: "strings",
fidl: `
library l;
type Document = struct {
title string:40;
description string:optional;
};
`,
expected: `struct/member l/Document.description string:optional
struct/member l/Document.title string:40
struct l/Document
library l
`,
},
{
name: "vectors",
fidl: `
library l;
type Vectors = struct {
params vector<int32>:10;
blob bytes;
nullable_vector_of_strings vector<string>:<24, optional>;
vector_of_nullable_strings vector<string:optional>;
complex vector<vector<array<float32, 16>>>;
};
`,
expected: `struct/member l/Vectors.blob vector<uint8>
struct/member l/Vectors.complex vector<vector<array<float32,16>>>
struct/member l/Vectors.nullable_vector_of_strings vector<string>:<24,optional>
struct/member l/Vectors.params vector<int32>:10
struct/member l/Vectors.vector_of_nullable_strings vector<string:optional>
struct l/Vectors
library l
`,
},
{
name: "handles",
dep: zxLibrary,
fidl: `
library l;
using zx;
type Handles = resource struct {
h zx.handle;
c zx.handle:<CHANNEL, optional>;
};
`,
expected: `struct/member l/Handles.c zx/handle:<CHANNEL,optional>
struct/member l/Handles.h zx/handle
resource struct l/Handles
library l
`,
},
{
name: "struct local type reference",
fidl: `
library l;
type A = struct {};
type B = struct {
a A;
};
`,
expected: `struct l/A
struct/member l/B.a l/A
struct l/B
library l
`,
},
{
name: "structs 2",
fidl: `
library l;
type CirclePoint = struct {
x float32;
y float32;
};
type Color = struct {
r float32;
g float32;
b float32;
};
type Circle = struct {
filled bool;
center CirclePoint;
radius float32;
color box<Color>;
dashed bool;
};
`,
expected: `struct/member l/Circle.center l/CirclePoint
struct/member l/Circle.color box<l/Color>
struct/member l/Circle.dashed bool
struct/member l/Circle.filled bool
struct/member l/Circle.radius float32
struct l/Circle
struct/member l/CirclePoint.x float32
struct/member l/CirclePoint.y float32
struct l/CirclePoint
struct/member l/Color.b float32
struct/member l/Color.g float32
struct/member l/Color.r float32
struct l/Color
library l
`,
},
{
name: "tables",
fidl: `
library l;
type Profile = table {
1: locales vector<string>;
2: calendars vector<string>;
3: time_zones vector<string>;
};
`,
expected: `table/member l/Profile.calendars vector<string>
table/member l/Profile.locales vector<string>
table/member l/Profile.time_zones vector<string>
table l/Profile
library l
`,
},
{
name: "unions",
fidl: `
library l;
type Left = struct {};
type Right = struct {};
type Either = strict union {
1: left Left;
2: right Right;
};
`,
expected: `union/member l/Either.left l/Left
union/member l/Either.right l/Right
strict union l/Either
struct l/Left
struct l/Right
library l
`,
},
{
name: "protocols 1",
fidl: `
library l;
protocol Calculator {
Add(struct { a int32; b int32; }) -> (struct { sum int32; });
};
`,
expected: `protocol/member l/Calculator.Add(int32 a,int32 b) -> (int32 sum)
protocol l/Calculator
library l
`,
},
{
name: "protocols 2",
fidl: `
library l;
type Foo = struct {};
type Bar = struct {};
protocol P {
M(struct { b box<Bar>; }) -> (struct { c Foo; });
};
`,
expected: `struct l/Bar
struct l/Foo
protocol/member l/P.M(box<l/Bar> b) -> (l/Foo c)
protocol l/P
library l
`,
},
{
name: "protocols 3",
fidl: `
library l;
type Bar = struct {};
protocol P {};
protocol P2 {
M1(resource struct { a client_end:P; });
M2(resource struct { a client_end:<P, optional>; });
M3(resource struct { a server_end:<P>; });
M4(resource struct { a server_end:<P, optional>; });
};
`,
expected: `struct l/Bar
protocol l/P
protocol/member l/P2.M1(client_end:l/P a)
protocol/member l/P2.M2(client_end:<l/P,optional> a)
protocol/member l/P2.M3(server_end:l/P a)
protocol/member l/P2.M4(server_end:<l/P,optional> a)
protocol l/P2
library l
`,
},
{
name: "protocols 4",
fidl: `
library l;
protocol P {
-> F1(struct { a int32; });
F2() -> (struct { a int32; });
F3() -> (struct {}) error int32;
F4();
};
`,
expected: `protocol/member l/P.F1 -> (int32 a)
protocol/member l/P.F2() -> (int32 a)
protocol/member l/P.F3() -> (l/P_F3_Result result)
protocol/member l/P.F4()
protocol l/P
struct l/P_F3_Response
union/member l/P_F3_Result.err int32
union/member l/P_F3_Result.response l/P_F3_Response
strict union l/P_F3_Result
library l
`,
},
{
name: "check types",
fidl: `
library l;
type S = struct {
f1 string;
f2 string:4;
f3 string:<4, optional>;
};
`,
expected: `struct/member l/S.f1 string
struct/member l/S.f2 string:4
struct/member l/S.f3 string:<4,optional>
struct l/S
library l
`,
},
{
name: "with foreign library",
dep: l2Library,
fidl: `
library l;
using l2;
type A = struct {
a l2.T;
};
`,
expected: `struct/member l/A.a l2/T
struct l/A
library l
`,
},
{
name: "protocol with foreign library",
dep: l2Library,
fidl: `
library l;
using l2;
type Foo = struct {};
type Bar = struct {};
protocol Calculator {
Add(struct { a l2.T; b Bar; }) -> (struct { c Foo; });
};
`,
expected: `struct l/Bar
protocol/member l/Calculator.Add(l2/T a,l/Bar b) -> (l/Foo c)
protocol l/Calculator
struct l/Foo
library l
`,
},
{
name: "reserved keyword",
fidl: `
library l;
type E = strict union {
1: reserved;
2: e int32;
};
type T = table {
1: reserved;
2: e int32;
};
`,
expected: `union/member l/E.e int32
strict union l/E
table/member l/T.e int32
table l/T
library l
`,
},
}
runWriteTests(t, tests, Write)
}
func TestWriteJSON(t *testing.T) {
tests := []summaryTestCase{
{
name: "library only",
fidl: `library l;`,
expected: `[
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "primitives 1",
fidl: `
library l;
const OFFSET int8 = -33;
const ENABLED_FLAG bool = true;
`,
expected: `[
{
"declaration": "bool",
"kind": "const",
"name": "l/ENABLED_FLAG",
"value": "true"
},
{
"declaration": "int8",
"kind": "const",
"name": "l/OFFSET",
"value": "-33"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "bits",
fidl: `
library l;
type Bits1 = strict bits {
BIT1 = 0x01;
BIT2 = 0x02;
};
`,
expected: `[
{
"kind": "bits/member",
"name": "l/Bits1.BIT1",
"value": "1"
},
{
"kind": "bits/member",
"name": "l/Bits1.BIT2",
"value": "2"
},
{
"declaration": "uint32",
"kind": "bits",
"name": "l/Bits1",
"strictness": "strict"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "bits 2",
fidl: `
library l;
type Bits1 = strict bits {
BIT1 = 0x01;
BIT2 = 0x02;
};
type Bits2 = strict bits {
BIT1 = 0x01;
BIT2 = 0x02;
};
`,
expected: `[
{
"kind": "bits/member",
"name": "l/Bits1.BIT1",
"value": "1"
},
{
"kind": "bits/member",
"name": "l/Bits1.BIT2",
"value": "2"
},
{
"declaration": "uint32",
"kind": "bits",
"name": "l/Bits1",
"strictness": "strict"
},
{
"kind": "bits/member",
"name": "l/Bits2.BIT1",
"value": "1"
},
{
"kind": "bits/member",
"name": "l/Bits2.BIT2",
"value": "2"
},
{
"declaration": "uint32",
"kind": "bits",
"name": "l/Bits2",
"strictness": "strict"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "bits 3",
fidl: `
library l;
type Bits = flexible bits : uint8 {
BIT1 = 0x01;
BIT2 = 0x02;
};
`,
expected: `[
{
"kind": "bits/member",
"name": "l/Bits.BIT1",
"value": "1"
},
{
"kind": "bits/member",
"name": "l/Bits.BIT2",
"value": "2"
},
{
"declaration": "uint8",
"kind": "bits",
"name": "l/Bits",
"strictness": "flexible"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "enums",
fidl: `
library l;
type Beverage = flexible enum : uint8 {
WATER = 0;
COFFEE = 1;
TEA = 2;
WHISKEY = 3;
};
// Underlying type is assumed to be uint32.
type Vessel = strict enum {
CUP = 0;
BOWL = 1;
TUREEN = 2;
JUG = 3;
};
`,
expected: `[
{
"kind": "enum/member",
"name": "l/Beverage.COFFEE",
"value": "1"
},
{
"kind": "enum/member",
"name": "l/Beverage.TEA",
"value": "2"
},
{
"kind": "enum/member",
"name": "l/Beverage.WATER",
"value": "0"
},
{
"kind": "enum/member",
"name": "l/Beverage.WHISKEY",
"value": "3"
},
{
"declaration": "uint8",
"kind": "enum",
"name": "l/Beverage",
"strictness": "flexible"
},
{
"kind": "enum/member",
"name": "l/Vessel.BOWL",
"value": "1"
},
{
"kind": "enum/member",
"name": "l/Vessel.CUP",
"value": "0"
},
{
"kind": "enum/member",
"name": "l/Vessel.JUG",
"value": "3"
},
{
"kind": "enum/member",
"name": "l/Vessel.TUREEN",
"value": "2"
},
{
"declaration": "uint32",
"kind": "enum",
"name": "l/Vessel",
"strictness": "strict"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "struct as precondition for arrays",
fidl: `
library l;
type S = struct {
x float32;
};
`,
expected: `[
{
"declaration": "float32",
"kind": "struct/member",
"name": "l/S.x"
},
{
"kind": "struct",
"name": "l/S"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "struct with an element with default value",
fidl: `
library l;
const VALUE string = "booyah!";
type S = struct {
x float32 = 0.314159;
foo string = "huzzah";
bar bool = true;
baz string = VALUE;
};
`,
expected: `[
{
"declaration": "bool",
"kind": "struct/member",
"name": "l/S.bar",
"value": "true"
},
{
"declaration": "string",
"kind": "struct/member",
"name": "l/S.baz",
"value": "booyah!"
},
{
"declaration": "string",
"kind": "struct/member",
"name": "l/S.foo",
"value": "huzzah"
},
{
"declaration": "float32",
"kind": "struct/member",
"name": "l/S.x",
"value": "0.314159"
},
{
"kind": "struct",
"name": "l/S"
},
{
"declaration": "string",
"kind": "const",
"name": "l/VALUE",
"value": "booyah!"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "arrays",
fidl: `
library l;
type Arrays = struct {
form array<float32, 16>;
matrix array<array<string, 4>, 10>;
};
`,
expected: `[
{
"declaration": "array<float32,16>",
"kind": "struct/member",
"name": "l/Arrays.form"
},
{
"declaration": "array<array<string,4>,10>",
"kind": "struct/member",
"name": "l/Arrays.matrix"
},
{
"kind": "struct",
"name": "l/Arrays"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "strings",
fidl: `
library l;
type Document = struct {
title string:40;
description string:optional;
};
`,
expected: `[
{
"declaration": "string:optional",
"kind": "struct/member",
"name": "l/Document.description"
},
{
"declaration": "string:40",
"kind": "struct/member",
"name": "l/Document.title"
},
{
"kind": "struct",
"name": "l/Document"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "vectors",
fidl: `
library l;
type Vectors = struct {
params vector<int32>:10;
blob bytes;
nullable_vector_of_strings vector<string>:<24, optional>;
vector_of_nullable_strings vector<string:optional>;
complex vector<vector<array<float32, 16>>>;
};
`,
expected: `[
{
"declaration": "vector<uint8>",
"kind": "struct/member",
"name": "l/Vectors.blob"
},
{
"declaration": "vector<vector<array<float32,16>>>",
"kind": "struct/member",
"name": "l/Vectors.complex"
},
{
"declaration": "vector<string>:<24,optional>",
"kind": "struct/member",
"name": "l/Vectors.nullable_vector_of_strings"
},
{
"declaration": "vector<int32>:10",
"kind": "struct/member",
"name": "l/Vectors.params"
},
{
"declaration": "vector<string:optional>",
"kind": "struct/member",
"name": "l/Vectors.vector_of_nullable_strings"
},
{
"kind": "struct",
"name": "l/Vectors"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "handles",
dep: zxLibrary,
fidl: `
library l;
using zx;
type Handles = resource struct {
h zx.handle;
c zx.handle:<CHANNEL, optional>;
};
`,
expected: `[
{
"declaration": "zx/handle:<CHANNEL,optional>",
"kind": "struct/member",
"name": "l/Handles.c"
},
{
"declaration": "zx/handle",
"kind": "struct/member",
"name": "l/Handles.h"
},
{
"kind": "struct",
"name": "l/Handles",
"resourceness": "resource"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "struct local type reference",
fidl: `
library l;
type A = struct {};
type B = struct {
a A;
};
`,
expected: `[
{
"kind": "struct",
"name": "l/A"
},
{
"declaration": "l/A",
"kind": "struct/member",
"name": "l/B.a"
},
{
"kind": "struct",
"name": "l/B"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "structs 2",
fidl: `
library l;
type CirclePoint = struct {
x float32;
y float32;
};
type Color = struct {
r float32;
g float32;
b float32;
};
type Circle = struct {
filled bool;
center CirclePoint;
radius float32;
color box<Color>;
dashed bool;
};
`,
expected: `[
{
"declaration": "l/CirclePoint",
"kind": "struct/member",
"name": "l/Circle.center"
},
{
"declaration": "box<l/Color>",
"kind": "struct/member",
"name": "l/Circle.color"
},
{
"declaration": "bool",
"kind": "struct/member",
"name": "l/Circle.dashed"
},
{
"declaration": "bool",
"kind": "struct/member",
"name": "l/Circle.filled"
},
{
"declaration": "float32",
"kind": "struct/member",
"name": "l/Circle.radius"
},
{
"kind": "struct",
"name": "l/Circle"
},
{
"declaration": "float32",
"kind": "struct/member",
"name": "l/CirclePoint.x"
},
{
"declaration": "float32",
"kind": "struct/member",
"name": "l/CirclePoint.y"
},
{
"kind": "struct",
"name": "l/CirclePoint"
},
{
"declaration": "float32",
"kind": "struct/member",
"name": "l/Color.b"
},
{
"declaration": "float32",
"kind": "struct/member",
"name": "l/Color.g"
},
{
"declaration": "float32",
"kind": "struct/member",
"name": "l/Color.r"
},
{
"kind": "struct",
"name": "l/Color"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "tables",
fidl: `
library l;
type Profile = table {
1: locales vector<string>;
2: calendars vector<string>;
3: time_zones vector<string>;
};
`,
expected: `[
{
"declaration": "vector<string>",
"kind": "table/member",
"name": "l/Profile.calendars"
},
{
"declaration": "vector<string>",
"kind": "table/member",
"name": "l/Profile.locales"
},
{
"declaration": "vector<string>",
"kind": "table/member",
"name": "l/Profile.time_zones"
},
{
"kind": "table",
"name": "l/Profile"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "unions",
fidl: `
library l;
type Left = struct {};
type Right = struct {};
type Either = strict union {
1: left Left;
2: right Right;
};
`,
expected: `[
{
"declaration": "l/Left",
"kind": "union/member",
"name": "l/Either.left"
},
{
"declaration": "l/Right",
"kind": "union/member",
"name": "l/Either.right"
},
{
"kind": "union",
"name": "l/Either",
"strictness": "strict"
},
{
"kind": "struct",
"name": "l/Left"
},
{
"kind": "struct",
"name": "l/Right"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "protocols 1",
fidl: `
library l;
protocol Calculator {
Add(struct { a int32; b int32; }) -> (struct { sum int32; });
};
`,
expected: `[
{
"declaration": "(int32 a,int32 b) -> (int32 sum)",
"kind": "protocol/member",
"name": "l/Calculator.Add"
},
{
"kind": "protocol",
"name": "l/Calculator"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "protocols 2",
fidl: `
library l;
type Foo = struct {};
type Bar = struct {};
protocol P {
M(struct { b box<Bar>; }) -> (struct { c Foo; });
};
`,
expected: `[
{
"kind": "struct",
"name": "l/Bar"
},
{
"kind": "struct",
"name": "l/Foo"
},
{
"declaration": "(box<l/Bar> b) -> (l/Foo c)",
"kind": "protocol/member",
"name": "l/P.M"
},
{
"kind": "protocol",
"name": "l/P"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "protocols 3",
fidl: `
library l;
type Bar = struct {};
protocol P {};
protocol P2 {
M1(resource struct { a client_end:P; });
M2(resource struct { a client_end:<P, optional>; });
M3(resource struct { a server_end:<P>; });
M4(resource struct { a server_end:<P, optional>; });
};
`,
expected: `[
{
"kind": "struct",
"name": "l/Bar"
},
{
"kind": "protocol",
"name": "l/P"
},
{
"declaration": "(client_end:l/P a)",
"kind": "protocol/member",
"name": "l/P2.M1"
},
{
"declaration": "(client_end:<l/P,optional> a)",
"kind": "protocol/member",
"name": "l/P2.M2"
},
{
"declaration": "(server_end:l/P a)",
"kind": "protocol/member",
"name": "l/P2.M3"
},
{
"declaration": "(server_end:<l/P,optional> a)",
"kind": "protocol/member",
"name": "l/P2.M4"
},
{
"kind": "protocol",
"name": "l/P2"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "protocols 4",
fidl: `
library l;
protocol P {
-> F1(struct { a int32; });
F2() -> (struct { a int32; });
F3() -> (struct {}) error int32;
F4();
};
`,
expected: `[
{
"declaration": " -> (int32 a)",
"kind": "protocol/member",
"name": "l/P.F1"
},
{
"declaration": "() -> (int32 a)",
"kind": "protocol/member",
"name": "l/P.F2"
},
{
"declaration": "() -> (l/P_F3_Result result)",
"kind": "protocol/member",
"name": "l/P.F3"
},
{
"declaration": "()",
"kind": "protocol/member",
"name": "l/P.F4"
},
{
"kind": "protocol",
"name": "l/P"
},
{
"kind": "struct",
"name": "l/P_F3_Response"
},
{
"declaration": "int32",
"kind": "union/member",
"name": "l/P_F3_Result.err"
},
{
"declaration": "l/P_F3_Response",
"kind": "union/member",
"name": "l/P_F3_Result.response"
},
{
"kind": "union",
"name": "l/P_F3_Result",
"strictness": "strict"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "check types",
fidl: `
library l;
type S = struct {
f1 string;
f2 string:4;
f3 string:<4, optional>;
};
`,
expected: `[
{
"declaration": "string",
"kind": "struct/member",
"name": "l/S.f1"
},
{
"declaration": "string:4",
"kind": "struct/member",
"name": "l/S.f2"
},
{
"declaration": "string:<4,optional>",
"kind": "struct/member",
"name": "l/S.f3"
},
{
"kind": "struct",
"name": "l/S"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "with foreign library",
dep: l2Library,
fidl: `
library l;
using l2;
type A = struct {
a l2.T;
};
`,
expected: `[
{
"declaration": "l2/T",
"kind": "struct/member",
"name": "l/A.a"
},
{
"kind": "struct",
"name": "l/A"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "protocol with foreign library",
dep: l2Library,
fidl: `
library l;
using l2;
type Foo = struct {};
type Bar = struct {};
protocol Calculator {
Add(struct { a l2.T; b Bar; }) -> (struct { c Foo; });
};
`,
expected: `[
{
"kind": "struct",
"name": "l/Bar"
},
{
"declaration": "(l2/T a,l/Bar b) -> (l/Foo c)",
"kind": "protocol/member",
"name": "l/Calculator.Add"
},
{
"kind": "protocol",
"name": "l/Calculator"
},
{
"kind": "struct",
"name": "l/Foo"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
{
name: "reserved keyword",
fidl: `
library l;
type E = strict union {
1: reserved;
2: e int32;
};
type T = table {
1: reserved;
2: e int32;
};
`,
expected: `[
{
"declaration": "int32",
"kind": "union/member",
"name": "l/E.e"
},
{
"kind": "union",
"name": "l/E",
"strictness": "strict"
},
{
"declaration": "int32",
"kind": "table/member",
"name": "l/T.e"
},
{
"kind": "table",
"name": "l/T"
},
{
"kind": "library",
"name": "l"
}
]
`,
},
}
runWriteTests(t, tests, WriteJSON)
}
func runWriteTests(t *testing.T, tests []summaryTestCase, writeFn func(fidlgen.Root, io.Writer) error) {
t.Helper()
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
c := fidlgentest.EndToEndTest{T: t}
if test.dep != "" {
c = c.WithDependency(test.dep)
}
r := c.Single(test.fidl)
var sb strings.Builder
if err := writeFn(r, &sb); err != nil {
t.Fatalf("while summarizing file: %v", err)
}
actual := strings.Split(sb.String(), "\n")
expected := strings.Split(test.expected, "\n")
if !cmp.Equal(expected, actual) {
t.Errorf("expected:\n---BEGIN---\n%+v\n---END---\n\n"+
"actual:\n---BEGIN---\n%+v\n---END---\n\ndiff:\n%v\n\nroot: %+v",
test.expected, sb.String(),
cmp.Diff(expected, actual), r)
}
})
}
}