Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Network Server GetDevAddrAssignment RPC #758

Merged
merged 1 commit into from
May 29, 2019
Merged

Network Server GetDevAddrAssignment RPC #758

merged 1 commit into from
May 29, 2019

Conversation

furtiman
Copy link
Contributor

@furtiman furtiman commented May 26, 2019

Summary

Closes #294

Changes

  • Added NS service and API definitions for it
  • Added grpc_ns.go and grpc_ns_test.go files
  • Added GenerateDevAddrAssignment rpc in grpc_ns.go
  • Added TestGenerateDevAddrAssignment test in grpc_ns_test.go.

Notes for Reviewers

Props @htdvisser for helping out

@furtiman furtiman added the c/network server This is related to the Network Server label May 26, 2019
@furtiman furtiman added this to the May 2019 milestone May 26, 2019
@furtiman furtiman requested a review from htdvisser as a code owner May 26, 2019 17:09
@furtiman furtiman self-assigned this May 26, 2019
@furtiman furtiman changed the title ns: Add GetDevAddrAssignment rpc and test Network Server GetDevAddrAssignment RPC May 26, 2019
@furtiman furtiman added the compat/api This could affect API compatibility label May 26, 2019
@coveralls
Copy link

coveralls commented May 26, 2019

Coverage Status

Coverage decreased (-0.03%) to 73.095% when pulling c634ffa on furtiman:feature/294-devAddr-generating-ns-rpc into 9bfc00b on TheThingsNetwork:master.


service Ns {
// GetDevAddrAssignment requests a device address assignment from the Network Server.
rpc GetDevAddrAssignment(GetDevAddrAssignmentRequest) returns (GetDevAddrAssignmentResponse) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Why not just use google.protobuf.Empty as the request here?
  • IMO Get here implies that you're getting something that already exists, however that's not the case - DevAddr is generated when this RPC is called. How about AssignDevAddr, CreateDevAddr, GenerateDevAddr?

// See the License for the specific language governing permissions and
// limitations under the License.

package networkserver
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be networkserver_test

},
})).(*NetworkServer)

if !a.So(ns.devAddrPrefixes, should.HaveLength, 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not belong here

if !a.So(ns.devAddrPrefixes, should.HaveLength, 1) {
t.FailNow()
}
a.So(ns.devAddrPrefixes[0], should.Resemble, types.DevAddrPrefix{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDEM

})

devAddr, _ := ns.GetDevAddrAssignment(test.Context(), nil)
a.So(devAddr.DevAddr.HasPrefix(ns.devAddrPrefixes[0]), should.BeTrue)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specify the prefix explicitly

}
}
}
a.So(seen[ns.devAddrPrefixes[0]], should.BeGreaterThan, 0)
Copy link
Contributor

@rvolosatovs rvolosatovs May 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is non-deterministic, right? Eventually this test will start consistently failing in CI, since the RNG will omit one of the prefixes.
Check each devAddr returned explicitly - i.e. in the loop assert that it has one of the prefixes configured above in the config.
Also, do not use internal NS fields(ns.devAddrPrefixes)

@furtiman furtiman requested a review from rvolosatovs May 27, 2019 13:52
seen[testPrefix3]++
}
}
a.So(seen[testPrefix1], should.BeGreaterThan, 0)
Copy link
Contributor

@rvolosatovs rvolosatovs May 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still non-deterministic, drop the seen and assert the prefix in the loop per each generated DevAddr.(i.e. assert that each generated DevAddr has one of the 3 prefixes specified)

Copy link
Member

@johanstokking johanstokking May 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comes from my suggested code where we test the generation itself. I agree that we should assert that, but also that all prefixes are present. With N of 100 that, statistically, must be the case if the RNG isn’t broken. I’d like to test that. We can increase N though, but all prefixes must be there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what would be the best way to resolve that, if we talk about assertion AND check if all of the prefixes present? add assertion without dropping the seen?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, or sum the seen and check if that number matches the number of generated, or fatal the test if the prefix doesn't match in the loop

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we don't need to test the RNG here, right?
Why not just do this on L84:

hasOneOfPrefixes := func(devAddr types.DevAddr, prefixes ...string) bool {
	for _, p := range prefixes {
		if devAddr.HasPrefix(p) {
			return true
		}
	}
	return false
}
a.So(hasOneOfPrefixes(devAddr.DevAddr, testPrefix1, testPrefix2, testPrefix3), should.BeTrue)

It's obvious what happens here and it's easy to debug.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we don't need to test the RNG here, right?

We need to test if all the configured prefixes are considered. That is complementary to testing whether all DevAddrs fit in one of the configured prefixes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to test that NS actually uses the RNG, then you can leave the seen assertions as is, but you do need to assert that devAddr generated is actually valid

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is the long version of "complementary" 😉

},
})).(*NetworkServer)

devAddr, _ := ns.GenerateDevAddrAssignment(test.Context(), nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call this via the gRPC client(https://github.com/TheThingsNetwork/lorawan-stack/pull/758/files#diff-e699b03edbcaf36d0a1bd906c75d1d22R584)
Look at the registry tests for an example on how to do that.

}

service Ns {
// GetDevAddrAssignment requests a device address assignment from the Network Server.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong comment

@@ -69,3 +69,16 @@ service NsEndDeviceRegistry {
};
}

message GetDevAddrAssignmentResponse {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong name(does not reflect the rename)


service Ns {
// GetDevAddrAssignment requests a device address assignment from the Network Server.
rpc GenerateDevAddrAssignment(google.protobuf.Empty) returns (GetDevAddrAssignmentResponse) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just GenerateDevAddr?

@furtiman
Copy link
Contributor Author

furtiman commented May 28, 2019

1 - In the networkserver.proto:
@rvolosatovs:

  • Why not just use google.protobuf.Empty as the request here?
  • For some reason I get
WARN Task failed                             panic: runtime error: invalid memory address or nil pointer dereference [recovered]
    panic: runtime error: invalid memory address or nil pointer dereference

when I try to use the google.protobuf.Empty and an according type for the function parameter. Also, the API with an empty request was initially suggested by @htdvisser , and now it works, so yeah

2 - I have rewritten the tests and now they indeed include both of the discussed complementary properties ;)

@furtiman furtiman requested a review from rvolosatovs May 28, 2019 18:16
@@ -69,3 +69,20 @@ service NsEndDeviceRegistry {
};
}

message GenerateDevAddrRequest {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should either use google.protobuf.Empty in the RPC or this message should contain a TODO with references to issues, which describe what fields are missing here

DevAddrPrefix types.DevAddrPrefix
}{
{
Name: "Prefix from NS NedID 1",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetID?
Also other occurences

"go.thethings.network/lorawan-stack/pkg/util/test/assertions/should"
)

func pureNewDevAddr(netID types.NetID) types.DevAddr {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant, just use test.Must(types.NewDevAddr).(types.DevAddr)
Also, the naming is mustX or MustX, e.g. mustNewDevAddr

test.Must(nil, ns.Start())
defer ns.Close()

devAddr, _ := ttnpb.NewNsClient(ns.LoopbackConn()).GenerateDevAddr(test.Context(), nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert that error is nil


seen := map[types.DevAddrPrefix]int{}
for i := 0; i < 100; i++ {
devAddr, _ := ttnpb.NewNsClient(ns.LoopbackConn()).GenerateDevAddr(test.Context(), nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDEM

},
})).(*NetworkServer)

ns.AddContextFiller(func(ctx context.Context) context.Context {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant

_ = cancel
return ctx
})
ns.AddContextFiller(func(ctx context.Context) context.Context {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant

},
})).(*NetworkServer)

ns.AddContextFiller(func(ctx context.Context) context.Context {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDEM

_ = cancel
return ctx
})
ns.AddContextFiller(func(ctx context.Context) context.Context {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDEM

pkg/networkserver/grpc_ns_test.go Outdated Show resolved Hide resolved
@rvolosatovs
Copy link
Contributor

You probably returned nil instead of ttnpb.Empty, which caused the panic when using google.protobuf.Empty

@furtiman furtiman requested a review from rvolosatovs May 29, 2019 09:18
Copy link
Contributor

@rvolosatovs rvolosatovs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

"go.thethings.network/lorawan-stack/pkg/util/test/assertions/should"
)

func TestGenerateDevAddrAssignment(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestGenerateDevAddr


"github.com/smartystreets/assertions"
"go.thethings.network/lorawan-stack/pkg/component"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be no empty line here

@furtiman furtiman merged commit 07355e1 into TheThingsNetwork:master May 29, 2019
@furtiman furtiman deleted the feature/294-devAddr-generating-ns-rpc branch May 29, 2019 11:54
rvolosatovs pushed a commit to rvolosatovs/lorawan-stack-fork that referenced this pull request May 29, 2019
rvolosatovs added a commit that referenced this pull request May 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c/network server This is related to the Network Server compat/api This could affect API compatibility
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add RPC to NS for generating ABP DevAddr
4 participants