Skip to content

Commit

Permalink
Merge pull request #277 from okp4/feat/did-components-predicate
Browse files Browse the repository at this point in the history
Feat/did components predicate
  • Loading branch information
ccamel authored Feb 3, 2023
2 parents e12df90 + 42ef3dd commit 7f1d60f
Show file tree
Hide file tree
Showing 7 changed files with 330 additions and 0 deletions.
11 changes: 11 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ require (
github.com/creachadair/taskgroup v0.3.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
github.com/dgraph-io/ristretto v0.1.0 // indirect
Expand All @@ -94,6 +95,7 @@ require (
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/goccy/go-json v0.9.7 // indirect
github.com/goccy/go-yaml v1.9.4 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gogo/gateway v1.1.0 // indirect
Expand Down Expand Up @@ -139,6 +141,12 @@ require (
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.15.11 // indirect
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
github.com/lestrrat-go/blackmagic v1.0.0 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/iter v1.0.1 // indirect
github.com/lestrrat-go/jwx v1.2.25 // indirect
github.com/lestrrat-go/option v1.0.0 // indirect
github.com/lib/pq v1.10.6 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/magiconair/properties v1.8.6 // indirect
Expand All @@ -155,6 +163,8 @@ require (
github.com/moby/sys/mount v0.3.1 // indirect
github.com/moby/sys/mountinfo v0.6.0 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/nuts-foundation/go-did v0.4.0 // indirect
github.com/ockam-network/did v0.1.4-0.20210103172416-02ae01ce06d8 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
github.com/opencontainers/runc v1.1.3 // indirect
Expand All @@ -176,6 +186,7 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/shengdoushi/base58 v1.0.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/spf13/afero v1.9.2 // indirect
Expand Down
22 changes: 22 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
Expand Down Expand Up @@ -634,6 +635,8 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-yaml v1.9.4 h1:S0GCYjwHKVI6IHqio7QWNKNThUl6NLzFd/g8Z65Axw8=
github.com/goccy/go-yaml v1.9.4/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
Expand Down Expand Up @@ -976,6 +979,18 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A=
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
github.com/lestrrat-go/jwx v1.2.25 h1:tAx93jN2SdPvFn08fHNAhqFJazn5mBBOB8Zli0g0otA=
github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY=
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
Expand Down Expand Up @@ -1097,8 +1112,12 @@ github.com/neilotoole/errgroup v0.1.6/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/notional-labs/wasmd v0.25.1-0.20220918064224-459cefae5a9a h1:VGHDEuEPdh9jtGMvwZ8RNAYxpCgicMXlu+l19BJtv1k=
github.com/notional-labs/wasmd v0.25.1-0.20220918064224-459cefae5a9a/go.mod h1:jS7RT9qst8yfUwROBEh6DiteG3gNWYNIltbGd2hvjS4=
github.com/nuts-foundation/go-did v0.4.0 h1:HyzyDOup3Mwt8t8PESQeipW3y8KHDf/XNlBb7XMe79c=
github.com/nuts-foundation/go-did v0.4.0/go.mod h1:FfY394+fFTGXQeYTzIFAHlzGZfPYpL0XygmtHb5Xjdg=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/ockam-network/did v0.1.4-0.20210103172416-02ae01ce06d8 h1:s5GFggECXv/KwF37ax4B7ACMOKoUnKvmur4i+7I07UE=
github.com/ockam-network/did v0.1.4-0.20210103172416-02ae01ce06d8/go.mod h1:ZsbTIuVGt8OrQEbqWrSztUISN4joeMabdsinbLubbzw=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
Expand Down Expand Up @@ -1304,6 +1323,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shengdoushi/base58 v1.0.0 h1:tGe4o6TmdXFJWoI31VoSWvuaKxf0Px3gqa3sUWhAxBs=
github.com/shengdoushi/base58 v1.0.0/go.mod h1:m5uIILfzcKMw6238iWAhP4l3s5+uXyF3+bJKUNhAL9I=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
Expand Down Expand Up @@ -1524,6 +1545,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE=
golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
Expand Down
1 change: 1 addition & 0 deletions x/logic/interpreter/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ var Registry = map[string]RegistryEntry{
"bank_balances/2": {predicate.BankBalances, 1},
"bank_spendable_balances/2": {predicate.BankSpendableBalances, 1},
"bank_locked_balances/2": {predicate.BankLockedBalances, 1},
"did_components/2": {predicate.DIDComponents, 1},
}

// RegistryNames is the list of the predicate names in the Registry.
Expand Down
112 changes: 112 additions & 0 deletions x/logic/predicate/did.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package predicate

import (
"fmt"
"net/url"
"strings"

"github.com/ichiban/prolog/engine"
godid "github.com/nuts-foundation/go-did/did"
"github.com/okp4/okp4d/x/logic/util"
)

// AtomDID is a term which represents a DID as a compound term `did(Method, ID, Path, Query, Fragment)`.
var AtomDID = engine.NewAtom("did")

// DIDComponents is a predicate which breaks down a DID into its components according to the [W3C DID] specification.
//
// did_components(+DID, -Components) is det
// did_components(-DID, +Components) is det
//
// where:
// - `DID` represents the DID URI as a `text`, compliant with the [W3C DID] specification.
// - `Components` is a term `did(Method, ID, Path, Query, Fragment)` following the [DID syntax] which represents
// respectively the method name, the method-specific ID, the path, the query, and the fragment of the DID, in decoded
// form. Components that are not found (i.e. `null`) are left uninstantiated (variable).
//
// Example:
//
// # Decompose a DID into its components.
// - did_components('did:example:123456?versionId=1', did(Method, ID, Path, Query, Fragment)).
//
// # Reconstruct a DID from its components.
// - did_components(DID, did('example', '123456', null, 'versionId=1', _42)).
//
// [W3C DID]: https://w3c.github.io/did-core
// [DID syntax]: https://w3c.github.io/did-core/#did-syntax
func DIDComponents(vm *engine.VM, did, components engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
switch t1 := env.Resolve(did).(type) {
case engine.Variable:
case engine.Atom:
parsedDid, err := godid.ParseDIDURL(t1.String())
if err != nil {
return engine.Error(fmt.Errorf("did_components/2: %w", err))
}

terms, err := didToTerms(parsedDid)
if err != nil {
return engine.Error(fmt.Errorf("did_components/2: %w", err))
}

return engine.Unify(vm, components, AtomDID.Apply(terms...), cont, env)
default:
return engine.Error(fmt.Errorf("did_components/2: cannot unify did with %T", t1))
}

switch t2 := env.Resolve(components).(type) {
case engine.Variable:
return engine.Error(fmt.Errorf("did_components/2: at least one argument must be instantiated"))
case engine.Compound:
if t2.Functor() != AtomDID {
return engine.Error(fmt.Errorf("did_components/2: invalid functor %s. Expected %s", t2.Functor().String(), AtomDID.String()))
}
if t2.Arity() != 5 {
return engine.Error(fmt.Errorf("did_components/2: invalid arity %d. Expected 5", t2.Arity()))
}

buf := strings.Builder{}
buf.WriteString("did:")
if segment, ok := util.Resolve(env, t2.Arg(0)); ok {
buf.WriteString(url.PathEscape(segment.String()))
}
if segment, ok := util.Resolve(env, t2.Arg(1)); ok {
buf.WriteString(":")
buf.WriteString(url.PathEscape(segment.String()))
}
if segment, ok := util.Resolve(env, t2.Arg(2)); ok {
for _, s := range strings.FieldsFunc(segment.String(), func(c rune) bool { return c == '/' }) {
buf.WriteString("/")
buf.WriteString(url.PathEscape(s))
}
}
if segment, ok := util.Resolve(env, t2.Arg(3)); ok {
buf.WriteString("?")
buf.WriteString(url.PathEscape(segment.String()))
}
if segment, ok := util.Resolve(env, t2.Arg(4)); ok {
buf.WriteString("#")
buf.WriteString(url.PathEscape(segment.String()))
}
return engine.Unify(vm, did, engine.NewAtom(buf.String()), cont, env)
default:
return engine.Error(fmt.Errorf("did_components/2: cannot unify did with %T", t2))
}
}

// didToTerms converts a DID to a "tuple" of terms (either an Atom or a Variable),
// or returns an error if the conversion fails.
// The returned atoms are url decoded.
func didToTerms(did *godid.DID) ([]engine.Term, error) {
components := []string{did.Method, did.ID, did.Path, did.Query, did.Fragment}
terms := make([]engine.Term, 0, len(components))

for _, component := range components {
r, err := url.PathUnescape(component)
if err != nil {
return nil, err
}
terms = append(terms, util.StringToTerm(r))
}

return terms, nil
}
140 changes: 140 additions & 0 deletions x/logic/predicate/did_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//nolint:gocognit
package predicate

import (
"fmt"
"testing"

"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ichiban/prolog/engine"
"github.com/okp4/okp4d/x/logic/testutil"
"github.com/okp4/okp4d/x/logic/types"
. "github.com/smartystreets/goconvey/convey"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmdb "github.com/tendermint/tm-db"
)

func TestDID(t *testing.T) {
Convey("Given a test cases", t, func() {
cases := []struct {
program string
query string
wantResult []types.TermResults
wantError error
}{
{
query: `did_components('did:example:123456',did(X,Y,_,_,_)).`,
wantResult: []types.TermResults{{"X": "example", "Y": "'123456'"}},
},
{
query: `did_components('did:example:123456/path', X).`,
wantResult: []types.TermResults{{"X": "did(example,'123456',path,_1,_2)"}},
},
{
query: `did_components('did:example:123456?versionId=1', X).`,
wantResult: []types.TermResults{{"X": "did(example,'123456',_1,'versionId=1',_2)"}},
},
{
query: `did_components('did:example:123456/path%20with/space', X).`,
wantResult: []types.TermResults{{"X": "did(example,'123456','path with/space',_1,_2)"}},
},
{
query: `did_components(X,did(example,'123456',_,'versionId=1',_)).`,
wantResult: []types.TermResults{{"X": "'did:example:123456?versionId=1'"}},
},
{
query: `did_components(X,did(example,'123456','/foo/bar','versionId=1','test')).`,
wantResult: []types.TermResults{{"X": "'did:example:123456/foo/bar?versionId=1#test'"}},
},
{
query: `did_components(X,did(example,'123456','path with/space',_,test)).`,
wantResult: []types.TermResults{{"X": "'did:example:123456/path%20with/space#test'"}},
},
{
query: `did_components(X,Y).`,
wantResult: []types.TermResults{},
wantError: fmt.Errorf("did_components/2: at least one argument must be instantiated"),
},
{
query: `did_components('foo',X).`,
wantResult: []types.TermResults{},
wantError: fmt.Errorf("did_components/2: invalid DID: input length is less than 7"),
},
{
query: `did_components(123,X).`,
wantResult: []types.TermResults{},
wantError: fmt.Errorf("did_components/2: cannot unify did with engine.Integer"),
},
{
query: `did_components(X, 123).`,
wantResult: []types.TermResults{},
wantError: fmt.Errorf("did_components/2: cannot unify did with engine.Integer"),
},
{
query: `did_components(X,foo('bar')).`,
wantResult: []types.TermResults{},
wantError: fmt.Errorf("did_components/2: invalid functor foo. Expected did"),
},
{
query: `did_components(X,did('bar')).`,
wantResult: []types.TermResults{},
wantError: fmt.Errorf("did_components/2: invalid arity 1. Expected 5"),
},
{
query: `did_components('did:example:123456',foo(X)).`,
wantResult: []types.TermResults{},
},
}
for nc, tc := range cases {
Convey(fmt.Sprintf("Given the query #%d: %s", nc, tc.query), func() {
Convey("and a context", func() {
db := tmdb.NewMemDB()
stateStore := store.NewCommitMultiStore(db)
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())

Convey("and a vm", func() {
interpreter := testutil.NewInterpreterMust(ctx)
interpreter.Register2(engine.NewAtom("did_components"), DIDComponents)

err := interpreter.Compile(ctx, tc.program)
So(err, ShouldBeNil)

Convey("When the predicate is called", func() {
sols, err := interpreter.QueryContext(ctx, tc.query)

Convey("Then the error should be nil", func() {
So(err, ShouldBeNil)
So(sols, ShouldNotBeNil)

Convey("and the bindings should be as expected", func() {
var got []types.TermResults
for sols.Next() {
m := types.TermResults{}
err := sols.Scan(m)
So(err, ShouldBeNil)

got = append(got, m)
}
if tc.wantError != nil {
So(sols.Err(), ShouldNotBeNil)
So(sols.Err().Error(), ShouldEqual, tc.wantError.Error())
} else {
So(sols.Err(), ShouldBeNil)
So(len(got), ShouldEqual, len(tc.wantResult))
for iGot, resultGot := range got {
for varGot, termGot := range resultGot {
So(testutil.ReindexUnknownVariables(termGot), ShouldEqual, tc.wantResult[iGot][varGot])
}
}
}
})
})
})
})
})
})
}
})
}
Loading

0 comments on commit 7f1d60f

Please sign in to comment.