From 9cd33e210555f613dfffc05779dec4205554713c Mon Sep 17 00:00:00 2001 From: wenovus Date: Fri, 1 Dec 2023 17:14:09 -0800 Subject: [PATCH 1/3] ygnmi.MustPath --- ygnmi/path_types.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ygnmi/path_types.go b/ygnmi/path_types.go index 1401e27..8aad026 100644 --- a/ygnmi/path_types.go +++ b/ygnmi/path_types.go @@ -115,6 +115,19 @@ func ResolvePath(n PathStruct) (*gpb.Path, map[string]interface{}, error) { return &gpb.Path{Elem: p}, root.CustomData(), nil } +// MustPath calls ResolvePath and panics on error. +// It is intended for use in tests with generated PathStructs. +// +// ygnmi.MustResolvePath(ocpath.Interface("port0").Name().Config().PathStruct()) +// returns "/interfaces/interface[name=port0]/config/name +func MustPath(q UntypedQuery) *gpb.Path { + p, _, err := ResolvePath(q.PathStruct()) + if err != nil { + panic(err) + } + return p +} + // ResolveRelPath returns the partial []*gpb.PathElem representing the // PathStruct's relative path. func ResolveRelPath(n PathStruct) ([]*gpb.PathElem, []error) { From 34f8a6cce0390d74f5cf0f2b4867520298cc79a9 Mon Sep 17 00:00:00 2001 From: wenovus Date: Fri, 1 Dec 2023 17:38:47 -0800 Subject: [PATCH 2/3] Context RequestValues for ygnmi queries * Values are added at Subscribe/Get calls. * Tests added for both compress/uncompressed queries. NewContext/FromContext are the calls that add/extract context values. --- exampleoc/a/a-0.go | 2 +- exampleoc/enum.go | 2 +- exampleoc/enum_map.go | 2 +- exampleoc/exampleocpath/exampleocpath.go | 2 +- exampleoc/modelb/modelb-0.go | 2 +- exampleoc/schema.go | 2 +- exampleoc/structs-0.go | 2 +- exampleoc/union.go | 2 +- internal/exampleocconfig/a/a-0.go | 2 +- internal/exampleocconfig/enum.go | 2 +- internal/exampleocconfig/enum_map.go | 2 +- .../exampleocconfigpath.go | 2 +- internal/exampleocconfig/modelb/modelb-0.go | 2 +- internal/exampleocconfig/schema.go | 2 +- internal/exampleocconfig/structs-0.go | 2 +- internal/exampleocconfig/union.go | 2 +- internal/exampleocunordered/enum.go | 2 +- internal/exampleocunordered/enum_map.go | 2 +- .../exampleocunorderedpath.go | 2 +- .../exampleocunordered/nested/nested-0.go | 2 +- internal/exampleocunordered/schema.go | 2 +- .../exampleocunordered/simple/simple-0.go | 2 +- internal/exampleocunordered/structs-0.go | 2 +- internal/exampleocunordered/union.go | 2 +- .../withlistval/withlistval-0.go | 2 +- internal/gnmitestutil/gnmi.go | 29 +++- internal/uexampleoc/a/a-0.go | 2 +- internal/uexampleoc/enum.go | 2 +- internal/uexampleoc/enum_map.go | 2 +- internal/uexampleoc/modelb/modelb-0.go | 2 +- internal/uexampleoc/nested/nested-0.go | 2 +- internal/uexampleoc/schema.go | 2 +- internal/uexampleoc/simple/simple-0.go | 2 +- internal/uexampleoc/structs-0.go | 2 +- .../uexampleocpath/uexampleocpath.go | 4 +- internal/uexampleoc/union.go | 2 +- .../uexampleoc/withlistval/withlistval-0.go | 2 +- pathgen/gnmigen.go | 3 +- ygnmi/context.go | 54 +++++++ ygnmi/context_test.go | 91 ++++++++++++ ygnmi/gnmi.go | 2 + ygnmi/ygnmi_preferconfig_test.go | 134 +++++++++++++++--- ygnmi/ygnmi_test.go | 132 ++++++++++++++--- ygnmi/ygnmi_testhelpers_test.go | 51 ++++++- ygnmi/ygnmi_uncompressed_test.go | 15 ++ ygnmi/ygnmi_unordered_test.go | 1 + 46 files changed, 494 insertions(+), 92 deletions(-) create mode 100644 ygnmi/context.go create mode 100644 ygnmi/context_test.go diff --git a/exampleoc/a/a-0.go b/exampleoc/a/a-0.go index e1173b8..cb9baf4 100644 --- a/exampleoc/a/a-0.go +++ b/exampleoc/a/a-0.go @@ -16,7 +16,7 @@ Package a is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../pathgen/testdata/yang/openconfig-simple.yang - ../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/exampleoc/enum.go b/exampleoc/enum.go index 2e810f0..d1ef213 100644 --- a/exampleoc/enum.go +++ b/exampleoc/enum.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../pathgen/testdata/yang/openconfig-simple.yang - ../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/exampleoc/enum_map.go b/exampleoc/enum_map.go index 0494802..63e224f 100644 --- a/exampleoc/enum_map.go +++ b/exampleoc/enum_map.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../pathgen/testdata/yang/openconfig-simple.yang - ../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/exampleoc/exampleocpath/exampleocpath.go b/exampleoc/exampleocpath/exampleocpath.go index 29a6e05..bc02e3d 100644 --- a/exampleoc/exampleocpath/exampleocpath.go +++ b/exampleoc/exampleocpath/exampleocpath.go @@ -16,7 +16,7 @@ Package exampleocpath is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../pathgen/testdata/yang/openconfig-simple.yang - ../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/exampleoc/modelb/modelb-0.go b/exampleoc/modelb/modelb-0.go index 6c62dad..7127f9c 100644 --- a/exampleoc/modelb/modelb-0.go +++ b/exampleoc/modelb/modelb-0.go @@ -16,7 +16,7 @@ Package modelb is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../pathgen/testdata/yang/openconfig-simple.yang - ../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/exampleoc/schema.go b/exampleoc/schema.go index 6cb6da6..d892c59 100644 --- a/exampleoc/schema.go +++ b/exampleoc/schema.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../pathgen/testdata/yang/openconfig-simple.yang - ../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/exampleoc/structs-0.go b/exampleoc/structs-0.go index 3ad69b7..aa5b463 100644 --- a/exampleoc/structs-0.go +++ b/exampleoc/structs-0.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../pathgen/testdata/yang/openconfig-simple.yang - ../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/exampleoc/union.go b/exampleoc/union.go index 4e2d029..a480d05 100644 --- a/exampleoc/union.go +++ b/exampleoc/union.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../pathgen/testdata/yang/openconfig-simple.yang - ../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocconfig/a/a-0.go b/internal/exampleocconfig/a/a-0.go index 63b9768..96a13ba 100644 --- a/internal/exampleocconfig/a/a-0.go +++ b/internal/exampleocconfig/a/a-0.go @@ -16,7 +16,7 @@ Package a is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocconfig/enum.go b/internal/exampleocconfig/enum.go index 007ec24..c8009b8 100644 --- a/internal/exampleocconfig/enum.go +++ b/internal/exampleocconfig/enum.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocconfig/enum_map.go b/internal/exampleocconfig/enum_map.go index 74b214f..8a916eb 100644 --- a/internal/exampleocconfig/enum_map.go +++ b/internal/exampleocconfig/enum_map.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocconfig/exampleocconfigpath/exampleocconfigpath.go b/internal/exampleocconfig/exampleocconfigpath/exampleocconfigpath.go index 781c946..a49574e 100644 --- a/internal/exampleocconfig/exampleocconfigpath/exampleocconfigpath.go +++ b/internal/exampleocconfig/exampleocconfigpath/exampleocconfigpath.go @@ -16,7 +16,7 @@ Package exampleocconfigpath is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocconfig/modelb/modelb-0.go b/internal/exampleocconfig/modelb/modelb-0.go index e554dc9..cc6185e 100644 --- a/internal/exampleocconfig/modelb/modelb-0.go +++ b/internal/exampleocconfig/modelb/modelb-0.go @@ -16,7 +16,7 @@ Package modelb is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocconfig/schema.go b/internal/exampleocconfig/schema.go index e89547b..7fa45f7 100644 --- a/internal/exampleocconfig/schema.go +++ b/internal/exampleocconfig/schema.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocconfig/structs-0.go b/internal/exampleocconfig/structs-0.go index e958717..fea51ab 100644 --- a/internal/exampleocconfig/structs-0.go +++ b/internal/exampleocconfig/structs-0.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocconfig/union.go b/internal/exampleocconfig/union.go index 39f06c0..4e1ce42 100644 --- a/internal/exampleocconfig/union.go +++ b/internal/exampleocconfig/union.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocunordered/enum.go b/internal/exampleocunordered/enum.go index e379a4b..61e8ebd 100644 --- a/internal/exampleocunordered/enum.go +++ b/internal/exampleocunordered/enum.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocunordered/enum_map.go b/internal/exampleocunordered/enum_map.go index af8eb19..3567eec 100644 --- a/internal/exampleocunordered/enum_map.go +++ b/internal/exampleocunordered/enum_map.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocunordered/exampleocunorderedpath/exampleocunorderedpath.go b/internal/exampleocunordered/exampleocunorderedpath/exampleocunorderedpath.go index 4dffacf..9277f90 100644 --- a/internal/exampleocunordered/exampleocunorderedpath/exampleocunorderedpath.go +++ b/internal/exampleocunordered/exampleocunorderedpath/exampleocunorderedpath.go @@ -16,7 +16,7 @@ Package exampleocunorderedpath is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocunordered/nested/nested-0.go b/internal/exampleocunordered/nested/nested-0.go index c8d637a..676fe2e 100644 --- a/internal/exampleocunordered/nested/nested-0.go +++ b/internal/exampleocunordered/nested/nested-0.go @@ -16,7 +16,7 @@ Package nested is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocunordered/schema.go b/internal/exampleocunordered/schema.go index 0ebc75e..20748b5 100644 --- a/internal/exampleocunordered/schema.go +++ b/internal/exampleocunordered/schema.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocunordered/simple/simple-0.go b/internal/exampleocunordered/simple/simple-0.go index 89311ad..9c304ad 100644 --- a/internal/exampleocunordered/simple/simple-0.go +++ b/internal/exampleocunordered/simple/simple-0.go @@ -16,7 +16,7 @@ Package simple is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocunordered/structs-0.go b/internal/exampleocunordered/structs-0.go index 1908f70..4b2bd44 100644 --- a/internal/exampleocunordered/structs-0.go +++ b/internal/exampleocunordered/structs-0.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocunordered/union.go b/internal/exampleocunordered/union.go index 99ec565..f38fbd3 100644 --- a/internal/exampleocunordered/union.go +++ b/internal/exampleocunordered/union.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was true in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/exampleocunordered/withlistval/withlistval-0.go b/internal/exampleocunordered/withlistval/withlistval-0.go index 4666413..86d90ae 100644 --- a/internal/exampleocunordered/withlistval/withlistval-0.go +++ b/internal/exampleocunordered/withlistval/withlistval-0.go @@ -16,7 +16,7 @@ Package withlistval is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/gnmitestutil/gnmi.go b/internal/gnmitestutil/gnmi.go index fa76922..e30024e 100644 --- a/internal/gnmitestutil/gnmi.go +++ b/internal/gnmitestutil/gnmi.go @@ -20,6 +20,7 @@ import ( "io" "github.com/openconfig/gnmi/testing/fake/gnmi" + "github.com/openconfig/ygnmi/ygnmi" "github.com/pkg/errors" "google.golang.org/grpc" "google.golang.org/grpc/credentials/local" @@ -32,7 +33,7 @@ import ( type FakeGNMI struct { agent *gnmi.Agent stub *Stubber - clientWrapper *clientWithGetter + clientWrapper *clientWrap } // StartGNMI launches a new fake GNMI server on the given port @@ -53,7 +54,7 @@ func StartGNMI(port int) (*FakeGNMI, error) { return &FakeGNMI{ agent: agent, stub: stub, - clientWrapper: &clientWithGetter{stub: stub}, + clientWrapper: &clientWrap{stub: stub}, }, nil } @@ -79,6 +80,12 @@ func (g *FakeGNMI) Requests() []*gpb.SubscribeRequest { return g.agent.Requests() } +// Requests returns the request-scoped values from the last ygnmi request sent +// to the gNMI server. +func (g *FakeGNMI) LastRequestContextValues() *ygnmi.RequestValues { + return g.clientWrapper.requestValues +} + // GetRequests returns the set of GetRequests sent to the gNMI server. // // They're ordered in reverse time of request. @@ -86,15 +93,17 @@ func (g *FakeGNMI) GetRequests() []*gpb.GetRequest { return g.clientWrapper.getRequests } -// clientWithGetter adds gNMI Get functionality to a GNMI client. -type clientWithGetter struct { +// clientWrap adds gNMI Get functionality to a GNMI client. +type clientWrap struct { gpb.GNMIClient - stub *Stubber - getRequests []*gpb.GetRequest + stub *Stubber + getRequests []*gpb.GetRequest + requestValues *ygnmi.RequestValues } // Get is a fake implementation of gnmi.Get, it returns the GetResponse contained in the stub. -func (g *clientWithGetter) Get(ctx context.Context, req *gpb.GetRequest, _ ...grpc.CallOption) (*gpb.GetResponse, error) { +func (g *clientWrap) Get(ctx context.Context, req *gpb.GetRequest, _ ...grpc.CallOption) (*gpb.GetResponse, error) { + g.requestValues = ygnmi.FromContext(ctx) g.getRequests = append([]*gpb.GetRequest{req}, g.getRequests...) if len(g.stub.getResponses) == 0 { return nil, io.EOF @@ -106,6 +115,12 @@ func (g *clientWithGetter) Get(ctx context.Context, req *gpb.GetRequest, _ ...gr return resp, err } +// Subscribe is a wrapper of the fake implementation of gnmi.Subscribe. +func (g *clientWrap) Subscribe(ctx context.Context, opts ...grpc.CallOption) (gpb.GNMI_SubscribeClient, error) { + g.requestValues = ygnmi.FromContext(ctx) + return g.GNMIClient.Subscribe(ctx, opts...) +} + // Stubber is a handle to add stubbed responses. type Stubber struct { gen *fpb.FixedGenerator diff --git a/internal/uexampleoc/a/a-0.go b/internal/uexampleoc/a/a-0.go index 52be2d2..25123e9 100644 --- a/internal/uexampleoc/a/a-0.go +++ b/internal/uexampleoc/a/a-0.go @@ -16,7 +16,7 @@ Package a is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/uexampleoc/enum.go b/internal/uexampleoc/enum.go index 2f475c7..7106267 100644 --- a/internal/uexampleoc/enum.go +++ b/internal/uexampleoc/enum.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was false in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/uexampleoc/enum_map.go b/internal/uexampleoc/enum_map.go index a221626..135b0b3 100644 --- a/internal/uexampleoc/enum_map.go +++ b/internal/uexampleoc/enum_map.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was false in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/uexampleoc/modelb/modelb-0.go b/internal/uexampleoc/modelb/modelb-0.go index 7eeb52e..9fd1db5 100644 --- a/internal/uexampleoc/modelb/modelb-0.go +++ b/internal/uexampleoc/modelb/modelb-0.go @@ -16,7 +16,7 @@ Package modelb is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/uexampleoc/nested/nested-0.go b/internal/uexampleoc/nested/nested-0.go index 2c41dd6..95e960b 100644 --- a/internal/uexampleoc/nested/nested-0.go +++ b/internal/uexampleoc/nested/nested-0.go @@ -16,7 +16,7 @@ Package nested is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/uexampleoc/schema.go b/internal/uexampleoc/schema.go index 1a1c870..2222362 100644 --- a/internal/uexampleoc/schema.go +++ b/internal/uexampleoc/schema.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was false in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/uexampleoc/simple/simple-0.go b/internal/uexampleoc/simple/simple-0.go index 9bcc2d0..eee912e 100644 --- a/internal/uexampleoc/simple/simple-0.go +++ b/internal/uexampleoc/simple/simple-0.go @@ -16,7 +16,7 @@ Package simple is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/uexampleoc/structs-0.go b/internal/uexampleoc/structs-0.go index 102007d..684c71e 100644 --- a/internal/uexampleoc/structs-0.go +++ b/internal/uexampleoc/structs-0.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was false in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/uexampleoc/uexampleocpath/uexampleocpath.go b/internal/uexampleoc/uexampleocpath/uexampleocpath.go index 406e027..199bb35 100644 --- a/internal/uexampleoc/uexampleocpath/uexampleocpath.go +++ b/internal/uexampleoc/uexampleocpath/uexampleocpath.go @@ -16,7 +16,7 @@ Package uexampleocpath is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang @@ -265,7 +265,7 @@ func (b *Batch) Query() ygnmi.SingletonQuery[*oc.Device] { false, false, false, - true, + false, false, ygnmi.NewDeviceRootBase(), nil, diff --git a/internal/uexampleoc/union.go b/internal/uexampleoc/union.go index 866f399..2864c12 100644 --- a/internal/uexampleoc/union.go +++ b/internal/uexampleoc/union.go @@ -18,7 +18,7 @@ of structs which represent a YANG schema. The generated schema can be compressed by a series of transformations (compression was false in this case). -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/internal/uexampleoc/withlistval/withlistval-0.go b/internal/uexampleoc/withlistval/withlistval-0.go index 4ad2fb8..e4247e9 100644 --- a/internal/uexampleoc/withlistval/withlistval-0.go +++ b/internal/uexampleoc/withlistval/withlistval-0.go @@ -16,7 +16,7 @@ Package withlistval is a generated package which contains definitions of structs which generate gNMI paths for a YANG schema. -This package was generated by ygnmi version: (devel): (ygot: v0.29.12) +This package was generated by ygnmi version: (devel): (ygot: v0.29.16) using the following YANG input files: - ../../pathgen/testdata/yang/openconfig-simple.yang - ../../pathgen/testdata/yang/openconfig-withlistval.yang diff --git a/pathgen/gnmigen.go b/pathgen/gnmigen.go index 3c8c104..a19339b 100644 --- a/pathgen/gnmigen.go +++ b/pathgen/gnmigen.go @@ -132,7 +132,7 @@ func defaultStateTmplStruct(pathStructName, fakeRootName string, compressBehavio SchemaStructPkgAccessor: "oc.", IsState: true, IsShadowPath: compressBehaviour == genutil.PreferIntendedConfig, - IsCompressedSchema: true, + IsCompressedSchema: compressBehaviour.CompressEnabled(), MethodName: "State", SingletonTypeName: singletonQueryTypeName, WildcardTypeName: wildcardQueryTypeName, @@ -230,7 +230,6 @@ func GNMIFieldGenerator(pathStructName, _ string, compressBehaviour genutil.Comp // to distinguish between config and state queries. func GNMIInitGenerator(pathStructName, fakeRootName string, compressBehaviour genutil.CompressBehaviour, _ *ygen.ParsedDirectory, node *NodeData, wildcard bool) (string, error) { tmplStruct := defaultStateTmplStruct(pathStructName, fakeRootName, compressBehaviour, node) - tmplStruct.IsCompressedSchema = false if err := modifyQueryType(node, &tmplStruct); err != nil { return "", err } diff --git a/ygnmi/context.go b/ygnmi/context.go new file mode 100644 index 0000000..6650736 --- /dev/null +++ b/ygnmi/context.go @@ -0,0 +1,54 @@ +// Copyright 2023 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ygnmi + +import ( + "context" +) + +// RequestValues contains request-scoped values for ygnmi queries. +type RequestValues struct { + // CompressedConfigQuery is a key type that means that the query is + // uninterested in /state paths. + CompressedConfigQuery bool + // CompressedStateQuery is a key type that means that the query is + // uninterested in /config paths. + CompressedStateQuery bool +} + +// FromContext extracts certain ygnmi request-scoped values, if present. +func FromContext(ctx context.Context) *RequestValues { + compConfig, _ := ctx.Value(compressedConfigQuery{}).(bool) + compState, _ := ctx.Value(compressedStateQuery{}).(bool) + return &RequestValues{ + CompressedConfigQuery: compConfig, + CompressedStateQuery: compState, + } +} + +// NewContext returns a new Context carrying ygnmi request-scoped values. +func NewContext(ctx context.Context, q UntypedQuery) context.Context { + if q.isCompressedSchema() { + if q.IsState() { + return context.WithValue(ctx, compressedStateQuery{}, true) + } else { + return context.WithValue(ctx, compressedConfigQuery{}, true) + } + } + return ctx +} + +type compressedConfigQuery struct{} +type compressedStateQuery struct{} diff --git a/ygnmi/context_test.go b/ygnmi/context_test.go new file mode 100644 index 0000000..d237789 --- /dev/null +++ b/ygnmi/context_test.go @@ -0,0 +1,91 @@ +// Copyright 2023 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ygnmi_test + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/openconfig/ygnmi/exampleoc/exampleocpath" + "github.com/openconfig/ygnmi/internal/uexampleoc/uexampleocpath" + "github.com/openconfig/ygnmi/ygnmi" +) + +func TestFromContext(t *testing.T) { + tests := []struct { + desc string + inContext context.Context + wantRequestValues *ygnmi.RequestValues + }{{ + desc: "compress-config", + inContext: ygnmi.NewContext(context.Background(), exampleocpath.Root().Parent().Config()), + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: true, + CompressedStateQuery: false, + }, + }, { + desc: "compress-config-leaf", + inContext: ygnmi.NewContext(context.Background(), exampleocpath.Root().Parent().Child().Five().Config()), + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: true, + CompressedStateQuery: false, + }, + }, { + desc: "compress-state", + inContext: ygnmi.NewContext(context.Background(), exampleocpath.Root().Parent().State()), + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + }, { + desc: "compress-state-leaf", + inContext: ygnmi.NewContext(context.Background(), exampleocpath.Root().Parent().Child().Five().State()), + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + }, { + desc: "uncompressed-container", + inContext: ygnmi.NewContext(context.Background(), uexampleocpath.Root().Parent()), + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: false, + }, + }, { + desc: "uncompressed-config-container", + inContext: ygnmi.NewContext(context.Background(), uexampleocpath.Root().Parent().Child().Config()), + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: false, + }, + }, { + desc: "uncompressed-leaf", + inContext: ygnmi.NewContext(context.Background(), uexampleocpath.Root().Parent().Child().Config().Five()), + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: false, + }, + }} + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + got := ygnmi.FromContext(tt.inContext) + if diff := cmp.Diff(tt.wantRequestValues, got); diff != "" { + t.Errorf("(-want, +got):\n%s", diff) + } + }) + } +} diff --git a/ygnmi/gnmi.go b/ygnmi/gnmi.go index f91f997..690e1eb 100644 --- a/ygnmi/gnmi.go +++ b/ygnmi/gnmi.go @@ -71,6 +71,8 @@ func subscribe[T any](ctx context.Context, c *Client, q AnyQuery[T], mode gpb.Su return nil, fmt.Errorf("using gnmi.Get is only valid for ONCE subscriptions") } + ctx = NewContext(ctx, q) + var sub gpb.GNMI_SubscribeClient var err error if o.useGet { diff --git a/ygnmi/ygnmi_preferconfig_test.go b/ygnmi/ygnmi_preferconfig_test.go index 28a4390..1008eca 100644 --- a/ygnmi/ygnmi_preferconfig_test.go +++ b/ygnmi/ygnmi_preferconfig_test.go @@ -28,8 +28,8 @@ import ( "github.com/openconfig/gnmi/errdiff" "github.com/openconfig/ygnmi/internal/exampleocconfig" "github.com/openconfig/ygnmi/internal/exampleocconfig/exampleocconfigpath" - "github.com/openconfig/ygnmi/internal/testutil" "github.com/openconfig/ygnmi/internal/gnmitestutil" + "github.com/openconfig/ygnmi/internal/testutil" "github.com/openconfig/ygnmi/schemaless" "github.com/openconfig/ygnmi/ygnmi" "github.com/openconfig/ygot/ygot" @@ -117,6 +117,7 @@ func TestPreferConfigLookup(t *testing.T) { desc string stub func(s *gnmitestutil.Stubber) inQuery ygnmi.SingletonQuery[string] + wantRequestValues *ygnmi.RequestValues wantSubscriptionPath *gpb.Path wantVal *ygnmi.Value[string] wantErr string @@ -132,6 +133,10 @@ func TestPreferConfigLookup(t *testing.T) { }}, }).Sync() }, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, wantSubscriptionPath: leafPath, wantVal: (&ygnmi.Value[string]{ Path: leafPath, @@ -291,7 +296,7 @@ func TestPreferConfigLookup(t *testing.T) { for _, tt := range leafTests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - lookupCheckFn(t, fakeGNMI, c, tt.inQuery, tt.wantErr, tt.wantSubscriptionPath, tt.wantVal) + lookupCheckFn(t, fakeGNMI, c, tt.inQuery, tt.wantErr, tt.wantRequestValues, tt.wantSubscriptionPath, tt.wantVal) }) } @@ -307,6 +312,7 @@ func TestPreferConfigLookup(t *testing.T) { desc string stub func(s *gnmitestutil.Stubber) inQuery ygnmi.SingletonQuery[*exampleocconfig.Parent_Child] + wantRequestValues *ygnmi.RequestValues wantSubscriptionPath *gpb.Path wantVal *ygnmi.Value[*exampleocconfig.Parent_Child] wantErr string @@ -321,7 +327,11 @@ func TestPreferConfigLookup(t *testing.T) { }}, }).Sync() }, - inQuery: configQuery, + inQuery: configQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: true, + CompressedStateQuery: false, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleocconfig.Parent_Child]{ Path: rootPath, @@ -340,7 +350,11 @@ func TestPreferConfigLookup(t *testing.T) { }}, }).Sync() }, - inQuery: stateQuery, + inQuery: stateQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleocconfig.Parent_Child]{ Path: rootPath, @@ -360,7 +374,11 @@ func TestPreferConfigLookup(t *testing.T) { }}, }).Sync() }, - inQuery: stateQuery, + inQuery: stateQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleocconfig.Parent_Child]{ Path: rootPath, @@ -379,7 +397,11 @@ func TestPreferConfigLookup(t *testing.T) { }}, }).Sync() }, - inQuery: configQuery, + inQuery: configQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: true, + CompressedStateQuery: false, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleocconfig.Parent_Child]{ Path: rootPath, @@ -456,7 +478,11 @@ func TestPreferConfigLookup(t *testing.T) { stub: func(s *gnmitestutil.Stubber) { s.Sync() }, - inQuery: stateQuery, + inQuery: stateQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleocconfig.Parent_Child]{ Path: rootPath, @@ -466,7 +492,7 @@ func TestPreferConfigLookup(t *testing.T) { for _, tt := range nonLeafTests { t.Run("nonleaf "+tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - lookupCheckFn(t, fakeGNMI, c, tt.inQuery, tt.wantErr, tt.wantSubscriptionPath, tt.wantVal) + lookupCheckFn(t, fakeGNMI, c, tt.inQuery, tt.wantErr, tt.wantRequestValues, tt.wantSubscriptionPath, tt.wantVal) }) } @@ -483,6 +509,7 @@ func TestPreferConfigLookup(t *testing.T) { t, fakeGNMI, c, exampleocconfigpath.Root().Model().SingleKey("foo").Counter().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counter"), (&ygnmi.Value[float32]{ Path: testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counter"), @@ -504,6 +531,7 @@ func TestPreferConfigLookup(t *testing.T) { t, fakeGNMI, c, exampleocconfigpath.Root().Model().SingleKey("foo").Counters().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counters"), (&ygnmi.Value[[]float32]{ Path: testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counters"), @@ -551,6 +579,7 @@ func TestPreferConfigLookup(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[*exampleocconfig.Model_SingleKey_OrderedList_OrderedMap](exampleocconfigpath.Root().Model().SingleKey("foo").OrderedListMap().Config()), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists"), (&ygnmi.Value[*exampleocconfig.Model_SingleKey_OrderedList_OrderedMap]{ Path: testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists"), @@ -597,6 +626,7 @@ func TestPreferConfigLookup(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[map[string]*exampleocconfig.Model_SingleKey](exampleocconfigpath.Root().Model().SingleKeyMap().Config()), "", + nil, testutil.GNMIPath(t, "/model/a"), (&ygnmi.Value[map[string]*exampleocconfig.Model_SingleKey]{ Path: testutil.GNMIPath(t, "/model/a"), @@ -661,6 +691,10 @@ func TestPreferConfigLookupWithGet(t *testing.T) { t, fakeGNMI, c, exampleocconfigpath.Root().RemoteContainer().ALeaf().State(), "", + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, tt.wantRequest, tt.wantVal, ) @@ -733,13 +767,24 @@ func TestPreferConfigLookupWithGet(t *testing.T) { for _, tt := range nonLeafTests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - got, err := ygnmi.Lookup[*exampleocconfig.Parent_Child](context.Background(), c, exampleocconfigpath.Root().Parent().Child().Config(), ygnmi.WithUseGet()) - if err != nil { - t.Fatalf("Lookup() returned unexpected error: %v", err) - } - if diff := cmp.Diff(tt.wantVal, got, cmp.AllowUnexported(ygnmi.Value[*exampleocconfig.Parent_Child]{}), cmpopts.IgnoreFields(ygnmi.TelemetryError{}, "Err"), cmpopts.IgnoreFields(ygnmi.Value[*exampleocconfig.Parent_Child]{}, "RecvTimestamp"), protocmp.Transform()); diff != "" { - t.Errorf("Lookup() returned unexpected diff: %s", diff) - } + path := exampleocconfigpath.Root().Parent().Child().Config() + lookupWithGetCheckFn( + t, fakeGNMI, c, + ygnmi.SingletonQuery[*exampleocconfig.Parent_Child](path), + "", + &ygnmi.RequestValues{ + CompressedConfigQuery: true, + CompressedStateQuery: false, + }, + &gpb.GetRequest{ + Encoding: gpb.Encoding_JSON_IETF, + Type: gpb.GetRequest_CONFIG, + Prefix: &gpb.Path{}, + Path: []*gpb.Path{nonLeafPath}, + }, + tt.wantVal, + cmpopts.IgnoreFields(ygnmi.TelemetryError{}, "Err"), + ) }) } @@ -784,6 +829,7 @@ func TestPreferConfigLookupWithGet(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[*exampleocconfig.Model_SingleKey_OrderedList_OrderedMap](exampleocconfigpath.Root().Model().SingleKey("foo").OrderedListMap().Config()), "", + nil, &gpb.GetRequest{ Encoding: gpb.Encoding_JSON_IETF, Type: gpb.GetRequest_CONFIG, @@ -837,6 +883,7 @@ func TestPreferConfigLookupWithGet(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[map[string]*exampleocconfig.Model_SingleKey](exampleocconfigpath.Root().Model().SingleKeyMap().Config()), "", + nil, &gpb.GetRequest{ Encoding: gpb.Encoding_JSON_IETF, Type: gpb.GetRequest_CONFIG, @@ -900,7 +947,13 @@ func TestPreferConfigGet(t *testing.T) { for _, tt := range tests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - getCheckFn(t, fakeGNMI, c, lq, tt.wantErr, tt.wantSubscriptionPath, tt.wantVal) + getCheckFn( + t, fakeGNMI, c, lq, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVal) }) } @@ -972,6 +1025,7 @@ func TestPreferConfigGet(t *testing.T) { getCheckFn(t, fakeGNMI, c, exampleocconfigpath.Root().Model().SingleKey("foo").OrderedListMap().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists"), getSamplePreferConfigOrderedMap(t), ) @@ -1169,6 +1223,10 @@ func TestPreferConfigWatch(t *testing.T) { tt.opts, func(val string) bool { return val == "foo" }, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, []*gpb.Path{tt.wantSubscriptionPath}, []gpb.SubscriptionMode{tt.wantMode}, []uint64{tt.wantInterval}, @@ -1401,6 +1459,10 @@ func TestPreferConfigWatch(t *testing.T) { return val.One != nil && *val.One == "foo" && val.Three == exampleocconfig.Child_Three_ONE }, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, []*gpb.Path{tt.wantSubscriptionPath}, []gpb.SubscriptionMode{gpb.SubscriptionMode_TARGET_DEFINED}, []uint64{0}, @@ -1476,6 +1538,7 @@ func TestPreferConfigWatch(t *testing.T) { return cmp.Equal(val, want, cmp.AllowUnexported(exampleocconfig.Model_SingleKey_OrderedList_OrderedMap{})) }, "", + nil, []*gpb.Path{testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists")}, []gpb.SubscriptionMode{gpb.SubscriptionMode_TARGET_DEFINED}, []uint64{0}, @@ -1560,6 +1623,7 @@ func TestPreferConfigWatch(t *testing.T) { return cmp.Equal(val, want) }, "", + nil, []*gpb.Path{testutil.GNMIPath(t, "/model/a")}, []gpb.SubscriptionMode{gpb.SubscriptionMode_TARGET_DEFINED}, []uint64{0}, @@ -1760,6 +1824,7 @@ func TestPreferConfigCollect(t *testing.T) { desc string stub func(s *gnmitestutil.Stubber) dur time.Duration + wantRequestValues *ygnmi.RequestValues wantSubscriptionPath *gpb.Path wantVals []*ygnmi.Value[string] wantErr string @@ -1844,7 +1909,14 @@ func TestPreferConfigCollect(t *testing.T) { for _, tt := range tests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - collectCheckFn(t, fakeGNMI, client, lq, tt.wantErr, tt.wantSubscriptionPath, tt.wantVals) + collectCheckFn( + t, fakeGNMI, client, lq, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVals, + ) }) } @@ -1920,7 +1992,13 @@ func TestPreferConfigCollect(t *testing.T) { for _, tt := range nonLeafTests { t.Run("nonleaf "+tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - collectCheckFn(t, fakeGNMI, client, nonLeafQuery, tt.wantErr, tt.wantSubscriptionPath, tt.wantVals) + collectCheckFn( + t, fakeGNMI, client, nonLeafQuery, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVals) }) } } @@ -2077,7 +2155,13 @@ func TestPreferConfigLookupAll(t *testing.T) { for _, tt := range leafTests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - lookupAllCheckFn(t, fakeGNMI, c, lq, tt.wantErr, tt.wantSubscriptionPath, tt.wantVals, false) + lookupAllCheckFn(t, fakeGNMI, c, lq, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVals, false, + ) }) } @@ -2190,7 +2274,14 @@ func TestPreferConfigLookupAll(t *testing.T) { for _, tt := range nonLeafTests { t.Run("nonLeaf "+tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - lookupAllCheckFn(t, fakeGNMI, c, nonLeafQ, tt.wantErr, tt.wantSubscriptionPath, tt.wantVals, true) + lookupAllCheckFn( + t, fakeGNMI, c, nonLeafQ, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVals, true, + ) }) } @@ -2259,6 +2350,7 @@ func TestPreferConfigLookupAll(t *testing.T) { t, fakeGNMI, c, exampleocconfigpath.Root().Model().SingleKeyAny().OrderedListMap().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=*]/ordered-lists"), []*ygnmi.Value[*exampleocconfig.Model_SingleKey_OrderedList_OrderedMap]{ // In alphabetical order. @@ -2346,6 +2438,7 @@ func TestPreferConfigLookupAll(t *testing.T) { t, fakeGNMI, c, exampleocconfigpath.Root().Model().SingleKeyAny().SingleKeyMap().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=*]/inner-a"), []*ygnmi.Value[map[string]*exampleocconfig.Model_SingleKey_SingleKey]{ // In alphabetical order. @@ -4138,6 +4231,7 @@ func TestPreferConfigCustomRootBatch(t *testing.T) { return cmp.Equal(val, want) }, "", + nil, []*gpb.Path{ testutil.GNMIPath(t, "/model/a/single-key[key=*]/state/key"), testutil.GNMIPath(t, "/model/a/single-key[key=*]/state/value"), diff --git a/ygnmi/ygnmi_test.go b/ygnmi/ygnmi_test.go index c057f3c..7ffb716 100644 --- a/ygnmi/ygnmi_test.go +++ b/ygnmi/ygnmi_test.go @@ -115,6 +115,7 @@ func TestLookup(t *testing.T) { desc string stub func(s *gnmitestutil.Stubber) inQuery ygnmi.SingletonQuery[string] + wantRequestValues *ygnmi.RequestValues wantSubscriptionPath *gpb.Path wantVal *ygnmi.Value[string] wantErr string @@ -130,6 +131,10 @@ func TestLookup(t *testing.T) { }}, }).Sync() }, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, wantSubscriptionPath: leafPath, wantVal: (&ygnmi.Value[string]{ Path: leafPath, @@ -289,7 +294,7 @@ func TestLookup(t *testing.T) { for _, tt := range leafTests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - lookupCheckFn(t, fakeGNMI, c, tt.inQuery, tt.wantErr, tt.wantSubscriptionPath, tt.wantVal) + lookupCheckFn(t, fakeGNMI, c, tt.inQuery, tt.wantErr, tt.wantRequestValues, tt.wantSubscriptionPath, tt.wantVal) }) } @@ -305,6 +310,7 @@ func TestLookup(t *testing.T) { desc string stub func(s *gnmitestutil.Stubber) inQuery ygnmi.SingletonQuery[*exampleoc.Parent_Child] + wantRequestValues *ygnmi.RequestValues wantSubscriptionPath *gpb.Path wantVal *ygnmi.Value[*exampleoc.Parent_Child] wantErr string @@ -319,7 +325,11 @@ func TestLookup(t *testing.T) { }}, }).Sync() }, - inQuery: configQuery, + inQuery: configQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: true, + CompressedStateQuery: false, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleoc.Parent_Child]{ Path: rootPath, @@ -338,7 +348,11 @@ func TestLookup(t *testing.T) { }}, }).Sync() }, - inQuery: stateQuery, + inQuery: stateQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleoc.Parent_Child]{ Path: rootPath, @@ -358,7 +372,11 @@ func TestLookup(t *testing.T) { }}, }).Sync() }, - inQuery: stateQuery, + inQuery: stateQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleoc.Parent_Child]{ Path: rootPath, @@ -377,7 +395,11 @@ func TestLookup(t *testing.T) { }}, }).Sync() }, - inQuery: configQuery, + inQuery: configQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: true, + CompressedStateQuery: false, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleoc.Parent_Child]{ Path: rootPath, @@ -454,7 +476,11 @@ func TestLookup(t *testing.T) { stub: func(s *gnmitestutil.Stubber) { s.Sync() }, - inQuery: stateQuery, + inQuery: stateQuery, + wantRequestValues: &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, wantSubscriptionPath: rootPath, wantVal: (&ygnmi.Value[*exampleoc.Parent_Child]{ Path: rootPath, @@ -464,7 +490,7 @@ func TestLookup(t *testing.T) { for _, tt := range nonLeafTests { t.Run("nonleaf "+tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - lookupCheckFn(t, fakeGNMI, c, tt.inQuery, tt.wantErr, tt.wantSubscriptionPath, tt.wantVal) + lookupCheckFn(t, fakeGNMI, c, tt.inQuery, tt.wantErr, tt.wantRequestValues, tt.wantSubscriptionPath, tt.wantVal) }) } @@ -481,6 +507,7 @@ func TestLookup(t *testing.T) { t, fakeGNMI, c, exampleocpath.Root().Model().SingleKey("foo").Counter().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counter"), (&ygnmi.Value[float32]{ Path: testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counter"), @@ -502,6 +529,7 @@ func TestLookup(t *testing.T) { t, fakeGNMI, c, exampleocpath.Root().Model().SingleKey("foo").Counters().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counters"), (&ygnmi.Value[[]float32]{ Path: testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counters"), @@ -549,6 +577,7 @@ func TestLookup(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[*exampleoc.Model_SingleKey_OrderedList_OrderedMap](exampleocpath.Root().Model().SingleKey("foo").OrderedListMap().Config()), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists"), (&ygnmi.Value[*exampleoc.Model_SingleKey_OrderedList_OrderedMap]{ Path: testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists"), @@ -595,6 +624,7 @@ func TestLookup(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[map[string]*exampleoc.Model_SingleKey](exampleocpath.Root().Model().SingleKeyMap().Config()), "", + nil, testutil.GNMIPath(t, "/model/a"), (&ygnmi.Value[map[string]*exampleoc.Model_SingleKey]{ Path: testutil.GNMIPath(t, "/model/a"), @@ -659,6 +689,10 @@ func TestLookupWithGet(t *testing.T) { t, fakeGNMI, c, exampleocpath.Root().RemoteContainer().ALeaf().State(), "", + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, tt.wantRequest, tt.wantVal, ) @@ -731,13 +765,24 @@ func TestLookupWithGet(t *testing.T) { for _, tt := range nonLeafTests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - got, err := ygnmi.Lookup[*exampleoc.Parent_Child](context.Background(), c, exampleocpath.Root().Parent().Child().Config(), ygnmi.WithUseGet()) - if err != nil { - t.Fatalf("Lookup() returned unexpected error: %v", err) - } - if diff := cmp.Diff(tt.wantVal, got, cmp.AllowUnexported(ygnmi.Value[*exampleoc.Parent_Child]{}), cmpopts.IgnoreFields(ygnmi.TelemetryError{}, "Err"), cmpopts.IgnoreFields(ygnmi.Value[*exampleoc.Parent_Child]{}, "RecvTimestamp"), protocmp.Transform()); diff != "" { - t.Errorf("Lookup() returned unexpected diff: %s", diff) - } + path := exampleocpath.Root().Parent().Child().Config() + lookupWithGetCheckFn( + t, fakeGNMI, c, + ygnmi.SingletonQuery[*exampleoc.Parent_Child](path), + "", + &ygnmi.RequestValues{ + CompressedConfigQuery: true, + CompressedStateQuery: false, + }, + &gpb.GetRequest{ + Encoding: gpb.Encoding_JSON_IETF, + Type: gpb.GetRequest_CONFIG, + Prefix: &gpb.Path{}, + Path: []*gpb.Path{nonLeafPath}, + }, + tt.wantVal, + cmpopts.IgnoreFields(ygnmi.TelemetryError{}, "Err"), + ) }) } @@ -782,6 +827,7 @@ func TestLookupWithGet(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[*exampleoc.Model_SingleKey_OrderedList_OrderedMap](exampleocpath.Root().Model().SingleKey("foo").OrderedListMap().Config()), "", + nil, &gpb.GetRequest{ Encoding: gpb.Encoding_JSON_IETF, Type: gpb.GetRequest_CONFIG, @@ -835,6 +881,7 @@ func TestLookupWithGet(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[map[string]*exampleoc.Model_SingleKey](exampleocpath.Root().Model().SingleKeyMap().Config()), "", + nil, &gpb.GetRequest{ Encoding: gpb.Encoding_JSON_IETF, Type: gpb.GetRequest_CONFIG, @@ -898,7 +945,13 @@ func TestGet(t *testing.T) { for _, tt := range tests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - getCheckFn(t, fakeGNMI, c, lq, tt.wantErr, tt.wantSubscriptionPath, tt.wantVal) + getCheckFn( + t, fakeGNMI, c, lq, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVal) }) } @@ -970,6 +1023,7 @@ func TestGet(t *testing.T) { getCheckFn(t, fakeGNMI, c, exampleocpath.Root().Model().SingleKey("foo").OrderedListMap().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists"), getSampleOrderedMap(t), ) @@ -1167,6 +1221,10 @@ func TestWatch(t *testing.T) { tt.opts, func(val string) bool { return val == "foo" }, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, []*gpb.Path{tt.wantSubscriptionPath}, []gpb.SubscriptionMode{tt.wantMode}, []uint64{tt.wantInterval}, @@ -1399,6 +1457,10 @@ func TestWatch(t *testing.T) { return val.One != nil && *val.One == "foo" && val.Three == exampleoc.Child_Three_ONE }, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, []*gpb.Path{tt.wantSubscriptionPath}, []gpb.SubscriptionMode{gpb.SubscriptionMode_TARGET_DEFINED}, []uint64{0}, @@ -1474,6 +1536,7 @@ func TestWatch(t *testing.T) { return cmp.Equal(val, want, cmp.AllowUnexported(exampleoc.Model_SingleKey_OrderedList_OrderedMap{})) }, "", + nil, []*gpb.Path{testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists")}, []gpb.SubscriptionMode{gpb.SubscriptionMode_TARGET_DEFINED}, []uint64{0}, @@ -1558,6 +1621,7 @@ func TestWatch(t *testing.T) { return cmp.Equal(val, want) }, "", + nil, []*gpb.Path{testutil.GNMIPath(t, "/model/a")}, []gpb.SubscriptionMode{gpb.SubscriptionMode_TARGET_DEFINED}, []uint64{0}, @@ -1758,6 +1822,7 @@ func TestCollect(t *testing.T) { desc string stub func(s *gnmitestutil.Stubber) dur time.Duration + wantRequestValues *ygnmi.RequestValues wantSubscriptionPath *gpb.Path wantVals []*ygnmi.Value[string] wantErr string @@ -1842,7 +1907,14 @@ func TestCollect(t *testing.T) { for _, tt := range tests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - collectCheckFn(t, fakeGNMI, client, lq, tt.wantErr, tt.wantSubscriptionPath, tt.wantVals) + collectCheckFn( + t, fakeGNMI, client, lq, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVals, + ) }) } @@ -1918,7 +1990,13 @@ func TestCollect(t *testing.T) { for _, tt := range nonLeafTests { t.Run("nonleaf "+tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - collectCheckFn(t, fakeGNMI, client, nonLeafQuery, tt.wantErr, tt.wantSubscriptionPath, tt.wantVals) + collectCheckFn( + t, fakeGNMI, client, nonLeafQuery, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVals) }) } } @@ -2075,7 +2153,13 @@ func TestLookupAll(t *testing.T) { for _, tt := range leafTests { t.Run(tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - lookupAllCheckFn(t, fakeGNMI, c, lq, tt.wantErr, tt.wantSubscriptionPath, tt.wantVals, false) + lookupAllCheckFn(t, fakeGNMI, c, lq, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVals, false, + ) }) } @@ -2188,7 +2272,14 @@ func TestLookupAll(t *testing.T) { for _, tt := range nonLeafTests { t.Run("nonLeaf "+tt.desc, func(t *testing.T) { tt.stub(fakeGNMI.Stub()) - lookupAllCheckFn(t, fakeGNMI, c, nonLeafQ, tt.wantErr, tt.wantSubscriptionPath, tt.wantVals, true) + lookupAllCheckFn( + t, fakeGNMI, c, nonLeafQ, tt.wantErr, + &ygnmi.RequestValues{ + CompressedConfigQuery: false, + CompressedStateQuery: true, + }, + tt.wantSubscriptionPath, tt.wantVals, true, + ) }) } @@ -2257,6 +2348,7 @@ func TestLookupAll(t *testing.T) { t, fakeGNMI, c, exampleocpath.Root().Model().SingleKeyAny().OrderedListMap().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=*]/ordered-lists"), []*ygnmi.Value[*exampleoc.Model_SingleKey_OrderedList_OrderedMap]{ // In alphabetical order. @@ -2344,6 +2436,7 @@ func TestLookupAll(t *testing.T) { t, fakeGNMI, c, exampleocpath.Root().Model().SingleKeyAny().SingleKeyMap().State(), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=*]/inner-a"), []*ygnmi.Value[map[string]*exampleoc.Model_SingleKey_SingleKey]{ // In alphabetical order. @@ -4136,6 +4229,7 @@ func TestCustomRootBatch(t *testing.T) { return cmp.Equal(val, want) }, "", + nil, []*gpb.Path{ testutil.GNMIPath(t, "/model/a/single-key[key=*]/state/key"), testutil.GNMIPath(t, "/model/a/single-key[key=*]/state/value"), diff --git a/ygnmi/ygnmi_testhelpers_test.go b/ygnmi/ygnmi_testhelpers_test.go index 7520619..4806a3e 100644 --- a/ygnmi/ygnmi_testhelpers_test.go +++ b/ygnmi/ygnmi_testhelpers_test.go @@ -37,7 +37,7 @@ import ( ygottestutil "github.com/openconfig/ygot/testutil" ) -func lookupCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.SingletonQuery[T], wantErrSubstring string, wantSubscriptionPath *gpb.Path, wantVal *ygnmi.Value[T]) { +func lookupCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.SingletonQuery[T], wantErrSubstring string, wantRequestValues *ygnmi.RequestValues, wantSubscriptionPath *gpb.Path, wantVal *ygnmi.Value[T]) { t.Helper() got, err := ygnmi.Lookup(context.Background(), c, inQuery) if diff := errdiff.Substring(err, wantErrSubstring); diff != "" { @@ -53,9 +53,15 @@ func lookupCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnm if diff := cmp.Diff(wantVal, got, cmp.AllowUnexported(ygnmi.Value[T]{}, exampleoc.Model_SingleKey_OrderedList_OrderedMap{}, exampleocconfig.Model_SingleKey_OrderedList_OrderedMap{}), protocmp.Transform()); diff != "" { t.Errorf("Lookup(ctx, c, %v) returned unexpected diff (-want,+got):\n %s\nComplianceErrors:\n%v", inQuery, diff, got.ComplianceErrors) } + + if wantRequestValues != nil { + if diff := cmp.Diff(wantRequestValues, fakeGNMI.LastRequestContextValues()); diff != "" { + t.Errorf("RequestValues (-want, +got):\n%s", diff) + } + } } -func lookupWithGetCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.SingletonQuery[T], wantErrSubstring string, wantRequest *gpb.GetRequest, wantVal *ygnmi.Value[T]) { +func lookupWithGetCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.SingletonQuery[T], wantErrSubstring string, wantRequestValues *ygnmi.RequestValues, wantRequest *gpb.GetRequest, wantVal *ygnmi.Value[T], copts ...cmp.Option) { t.Helper() got, err := ygnmi.Lookup(context.Background(), c, inQuery, ygnmi.WithUseGet()) if diff := errdiff.Substring(err, wantErrSubstring); diff != "" { @@ -64,15 +70,22 @@ func lookupWithGetCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, if err != nil { return } - if diff := cmp.Diff(wantVal, got, cmp.AllowUnexported(ygnmi.Value[T]{}, exampleoc.Model_SingleKey_OrderedList_OrderedMap{}, exampleocconfig.Model_SingleKey_OrderedList_OrderedMap{}), cmpopts.IgnoreFields(ygnmi.Value[T]{}, "RecvTimestamp"), protocmp.Transform()); diff != "" { + copts = append(copts, cmp.AllowUnexported(ygnmi.Value[T]{}, exampleoc.Model_SingleKey_OrderedList_OrderedMap{}, exampleocconfig.Model_SingleKey_OrderedList_OrderedMap{}), cmpopts.IgnoreFields(ygnmi.Value[T]{}, "RecvTimestamp"), protocmp.Transform()) + if diff := cmp.Diff(wantVal, got, copts...); diff != "" { t.Errorf("Lookup() returned unexpected diff (-want, +got):\n%s", diff) } if diff := cmp.Diff(wantRequest, fakeGNMI.GetRequests()[0], protocmp.Transform()); diff != "" { t.Errorf("Lookup() GetRequest different from expected (-want, +got):\n%s", diff) } + + if wantRequestValues != nil { + if diff := cmp.Diff(wantRequestValues, fakeGNMI.LastRequestContextValues()); diff != "" { + t.Errorf("RequestValues (-want, +got):\n%s", diff) + } + } } -func getCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.SingletonQuery[T], wantErrSubstring string, wantSubscriptionPath *gpb.Path, wantVal T) { +func getCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.SingletonQuery[T], wantErrSubstring string, wantRequestValues *ygnmi.RequestValues, wantSubscriptionPath *gpb.Path, wantVal T) { t.Helper() got, err := ygnmi.Get(context.Background(), c, inQuery) if diff := errdiff.Substring(err, wantErrSubstring); diff != "" { @@ -86,10 +99,16 @@ func getCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.C if diff := cmp.Diff(wantVal, got, cmp.AllowUnexported(exampleoc.Model_SingleKey_OrderedList_OrderedMap{}, exampleocconfig.Model_SingleKey_OrderedList_OrderedMap{})); diff != "" { t.Errorf("Get(ctx, c, %v) returned unexpected diff (-want,+got):\n %s", inQuery, diff) } + + if wantRequestValues != nil { + if diff := cmp.Diff(wantRequestValues, fakeGNMI.LastRequestContextValues()); diff != "" { + t.Errorf("RequestValues (-want, +got):\n%s", diff) + } + } } func watchCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, duration time.Duration, c *ygnmi.Client, inQuery ygnmi.SingletonQuery[T], - inOpts []ygnmi.Option, valPred func(T) bool, wantErrSubstring string, wantSubscriptionPaths []*gpb.Path, wantModes []gpb.SubscriptionMode, wantIntervals []uint64, wantVals []*ygnmi.Value[T], wantLastVal *ygnmi.Value[T]) { + inOpts []ygnmi.Option, valPred func(T) bool, wantErrSubstring string, wantRequestValues *ygnmi.RequestValues, wantSubscriptionPaths []*gpb.Path, wantModes []gpb.SubscriptionMode, wantIntervals []uint64, wantVals []*ygnmi.Value[T], wantLastVal *ygnmi.Value[T]) { t.Helper() i := 0 ctx, cancel := context.WithTimeout(context.Background(), duration) @@ -128,9 +147,15 @@ func watchCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, duration if diff := cmp.Diff(wantLastVal, val, cmp.AllowUnexported(ygnmi.Value[T]{}, exampleoc.Model_SingleKey_OrderedList_OrderedMap{}, exampleocconfig.Model_SingleKey_OrderedList_OrderedMap{}), protocmp.Transform()); diff != "" { t.Errorf("Await() returned unexpected value (-want,+got):\n%s", diff) } + + if wantRequestValues != nil { + if diff := cmp.Diff(wantRequestValues, fakeGNMI.LastRequestContextValues()); diff != "" { + t.Errorf("RequestValues (-want, +got):\n%s", diff) + } + } } -func collectCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.SingletonQuery[T], wantErrSubstring string, wantSubscriptionPath *gpb.Path, wantVals []*ygnmi.Value[T]) { +func collectCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.SingletonQuery[T], wantErrSubstring string, wantRequestValues *ygnmi.RequestValues, wantSubscriptionPath *gpb.Path, wantVals []*ygnmi.Value[T]) { t.Helper() vals, err := ygnmi.Collect(context.Background(), c, inQuery).Await() if diff := errdiff.Substring(err, wantErrSubstring); diff != "" { @@ -143,9 +168,15 @@ func collectCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygn if diff := cmp.Diff(wantVals, vals, cmpopts.IgnoreFields(ygnmi.Value[T]{}, "RecvTimestamp"), cmp.AllowUnexported(ygnmi.Value[T]{}), protocmp.Transform()); diff != "" { t.Errorf("Await() returned unexpected value (-want,+got):\n%s", diff) } + + if wantRequestValues != nil { + if diff := cmp.Diff(wantRequestValues, fakeGNMI.LastRequestContextValues()); diff != "" { + t.Errorf("RequestValues (-want, +got):\n%s", diff) + } + } } -func lookupAllCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.WildcardQuery[T], wantErrSubstring string, wantSubscriptionPath *gpb.Path, wantVals []*ygnmi.Value[T], nonLeaf bool) { +func lookupAllCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *ygnmi.Client, inQuery ygnmi.WildcardQuery[T], wantErrSubstring string, wantRequestValues *ygnmi.RequestValues, wantSubscriptionPath *gpb.Path, wantVals []*ygnmi.Value[T], nonLeaf bool) { t.Helper() got, err := ygnmi.LookupAll(context.Background(), c, inQuery) if diff := errdiff.Substring(err, wantErrSubstring); diff != "" { @@ -169,6 +200,12 @@ func lookupAllCheckFn[T any](t *testing.T, fakeGNMI *gnmitestutil.FakeGNMI, c *y if diff := cmp.Diff(wantVals, got, copts...); diff != "" { t.Errorf("LookupAll() returned unexpected diff (-want,+got):\n%s", diff) } + + if wantRequestValues != nil { + if diff := cmp.Diff(wantRequestValues, fakeGNMI.LastRequestContextValues()); diff != "" { + t.Errorf("RequestValues (-want, +got):\n%s", diff) + } + } } func configCheckFn(t *testing.T, setClient *gnmitestutil.SetClient, c *ygnmi.Client, op func(*ygnmi.Client) (*ygnmi.Result, error), wantRequest *gpb.SetRequest, stubResponse *gpb.SetResponse, wantErrSubstring string, stubErr error) { diff --git a/ygnmi/ygnmi_uncompressed_test.go b/ygnmi/ygnmi_uncompressed_test.go index f0011d4..587a066 100644 --- a/ygnmi/ygnmi_uncompressed_test.go +++ b/ygnmi/ygnmi_uncompressed_test.go @@ -61,6 +61,7 @@ func TestUncompressedTelemetry(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[string](uexampleocpath.Root().Model().A().SingleKey("foo").Config().Key()), "", + &ygnmi.RequestValues{}, testutil.GNMIPath(t, `/model/a/single-key[key=foo]/config/key`), (&ygnmi.Value[string]{ Path: testutil.GNMIPath(t, `/model/a/single-key[key=foo]/config/key`), @@ -82,6 +83,7 @@ func TestUncompressedTelemetry(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[string](uexampleocpath.Root().Model().A().SingleKey("foo").State().Key()), "", + &ygnmi.RequestValues{}, testutil.GNMIPath(t, `/model/a/single-key[key=foo]/state/key`), (&ygnmi.Value[string]{ Path: testutil.GNMIPath(t, `/model/a/single-key[key=foo]/state/key`), @@ -131,6 +133,7 @@ func TestUncompressedTelemetry(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[*uexampleoc.OpenconfigWithlistval_Model_A](uexampleocpath.Root().Model().A()), "", + &ygnmi.RequestValues{}, testutil.GNMIPath(t, "/model/a"), (&ygnmi.Value[*uexampleoc.OpenconfigWithlistval_Model_A]{ Path: testutil.GNMIPath(t, "/model/a"), @@ -180,6 +183,7 @@ func TestUncompressedTelemetry(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[map[string]*uexampleoc.OpenconfigWithlistval_Model_A_SingleKey](uexampleocpath.Root().Model().A().SingleKeyMap()), "", + &ygnmi.RequestValues{}, testutil.GNMIPath(t, "/model/a/single-key"), (&ygnmi.Value[map[string]*uexampleoc.OpenconfigWithlistval_Model_A_SingleKey]{ Path: testutil.GNMIPath(t, "/model/a/single-key"), @@ -208,6 +212,7 @@ func TestUncompressedTelemetry(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[string](uexampleocpath.Root().Model().A().SingleKey("foo").Config().Key()), "EOF", + &ygnmi.RequestValues{}, testutil.GNMIPath(t, `/model/a/single-key[key=foo]/config/key`), []*ygnmi.Value[string]{ (&ygnmi.Value[string]{ @@ -235,6 +240,7 @@ func TestUncompressedTelemetry(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[float32](uexampleocpath.Root().Model().A().SingleKey("foo").State().Counter()), "", + &ygnmi.RequestValues{}, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counter"), (&ygnmi.Value[float32]{ Path: testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counter"), @@ -256,6 +262,7 @@ func TestUncompressedTelemetry(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[[]float32](uexampleocpath.Root().Model().A().SingleKey("foo").State().Counters()), "", + &ygnmi.RequestValues{}, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counters"), (&ygnmi.Value[[]float32]{ Path: testutil.GNMIPath(t, "/model/a/single-key[key=foo]/state/counters"), @@ -435,6 +442,10 @@ func TestUncompressedBatchGet(t *testing.T) { if diff := cmp.Diff(tt.wantVal, got, cmp.AllowUnexported(ygnmi.Value[*uexampleoc.Device]{}), protocmp.Transform()); diff != "" { t.Errorf("Lookup() returned unexpected diff (-want,+got):\n %s\nComplianceErrors:\n%v", diff, got.ComplianceErrors) } + + if diff := cmp.Diff(&ygnmi.RequestValues{}, fakeGNMI.LastRequestContextValues()); diff != "" { + t.Errorf("RequestValues (-want, +got):\n%s", diff) + } }) } t.Run("immutable query", func(t *testing.T) { @@ -526,6 +537,10 @@ func TestUncompressedCustomRootBatch(t *testing.T) { if diff := cmp.Diff(tt.wantVal, got, cmp.AllowUnexported(ygnmi.Value[*uexampleoc.OpenconfigSimple_Parent]{}), protocmp.Transform()); diff != "" { t.Errorf("Watch() returned unexpected diff (-want,+got):\n %s\nComplianceErrors:\n%v", diff, got.ComplianceErrors) } + + if diff := cmp.Diff(&ygnmi.RequestValues{}, fakeGNMI.LastRequestContextValues()); diff != "" { + t.Errorf("RequestValues (-want, +got):\n%s", diff) + } }) } } diff --git a/ygnmi/ygnmi_unordered_test.go b/ygnmi/ygnmi_unordered_test.go index 8654e7c..b365039 100644 --- a/ygnmi/ygnmi_unordered_test.go +++ b/ygnmi/ygnmi_unordered_test.go @@ -41,6 +41,7 @@ func TestUnorderedOrderedMap(t *testing.T) { t, fakeGNMI, c, ygnmi.SingletonQuery[string](exampleocunorderedpath.Root().Model().SingleKey("foo").OrderedList("foo").Key().Config()), "", + nil, testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists/ordered-list[key=foo]/config/key"), (&ygnmi.Value[string]{ Path: testutil.GNMIPath(t, "/model/a/single-key[key=foo]/ordered-lists/ordered-list[key=foo]/config/key"), From c4c3264648156d813e85d96125804e6185ceb30a Mon Sep 17 00:00:00 2001 From: wenovus Date: Sat, 2 Dec 2023 17:35:00 -0800 Subject: [PATCH 3/3] Fix lint --- internal/gnmitestutil/gnmi.go | 4 ++-- ygnmi/path_types.go | 13 ------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/internal/gnmitestutil/gnmi.go b/internal/gnmitestutil/gnmi.go index e30024e..fb458ee 100644 --- a/internal/gnmitestutil/gnmi.go +++ b/internal/gnmitestutil/gnmi.go @@ -80,8 +80,8 @@ func (g *FakeGNMI) Requests() []*gpb.SubscribeRequest { return g.agent.Requests() } -// Requests returns the request-scoped values from the last ygnmi request sent -// to the gNMI server. +// LastRequestContextValues returns the request-scoped values from the last +// ygnmi request sent to the gNMI server. func (g *FakeGNMI) LastRequestContextValues() *ygnmi.RequestValues { return g.clientWrapper.requestValues } diff --git a/ygnmi/path_types.go b/ygnmi/path_types.go index 8aad026..1401e27 100644 --- a/ygnmi/path_types.go +++ b/ygnmi/path_types.go @@ -115,19 +115,6 @@ func ResolvePath(n PathStruct) (*gpb.Path, map[string]interface{}, error) { return &gpb.Path{Elem: p}, root.CustomData(), nil } -// MustPath calls ResolvePath and panics on error. -// It is intended for use in tests with generated PathStructs. -// -// ygnmi.MustResolvePath(ocpath.Interface("port0").Name().Config().PathStruct()) -// returns "/interfaces/interface[name=port0]/config/name -func MustPath(q UntypedQuery) *gpb.Path { - p, _, err := ResolvePath(q.PathStruct()) - if err != nil { - panic(err) - } - return p -} - // ResolveRelPath returns the partial []*gpb.PathElem representing the // PathStruct's relative path. func ResolveRelPath(n PathStruct) ([]*gpb.PathElem, []error) {