diff --git a/pkg/packetbrokeragent/agent_test.go b/pkg/packetbrokeragent/agent_test.go index c7d8209003..864e149bae 100644 --- a/pkg/packetbrokeragent/agent_test.go +++ b/pkg/packetbrokeragent/agent_test.go @@ -30,6 +30,7 @@ import ( "go.thethings.network/lorawan-stack/v3/pkg/component" componenttest "go.thethings.network/lorawan-stack/v3/pkg/component/test" "go.thethings.network/lorawan-stack/v3/pkg/config" + mockis "go.thethings.network/lorawan-stack/v3/pkg/identityserver/mock" "go.thethings.network/lorawan-stack/v3/pkg/log" . "go.thethings.network/lorawan-stack/v3/pkg/packetbrokeragent" "go.thethings.network/lorawan-stack/v3/pkg/packetbrokeragent/mock" @@ -75,12 +76,37 @@ func TestForwarder(t *testing.T) { ctx, cancel := context.WithCancel(ctx) defer cancel() + is, isAddr, closeIS := mockis.New(ctx) + defer closeIS() + + // IS Related test cases setup. + userFoo := &ttnpb.UserIdentifiers{UserId: "foo", Email: "usr-foo@example.com"} + userBar := &ttnpb.UserIdentifiers{UserId: "bar", Email: "usr-bar@example.com"} + orgID := &ttnpb.OrganizationIdentifiers{OrganizationId: "foo-org"} + + is.UserRegistry().Create(ctx, &ttnpb.CreateUserRequest{ + User: &ttnpb.User{Ids: userFoo, PrimaryEmailAddress: userFoo.Email}, + }) + is.UserRegistry().Create(ctx, &ttnpb.CreateUserRequest{ + User: &ttnpb.User{Ids: userBar, PrimaryEmailAddress: userBar.Email}, + }) + is.OrganizationRegistry().Create(ctx, &ttnpb.CreateOrganizationRequest{ + Organization: &ttnpb.Organization{ + Ids: orgID, + AdministrativeContact: userFoo.GetOrganizationOrUserIdentifiers(), + TechnicalContact: userBar.GetOrganizationOrUserIdentifiers(), + }, + }) + c := componenttest.NewComponent(t, &component.Config{ ServiceBase: config.ServiceBase{ FrequencyPlans: config.FrequencyPlansConfig{ ConfigSource: "static", Static: test.StaticFrequencyPlans, }, + Cluster: cluster.Config{ + IdentityServer: isAddr, + }, }, }) @@ -120,6 +146,7 @@ func TestForwarder(t *testing.T) { defer c.Close() mustHavePeer(ctx, c, ttnpb.ClusterRole_GATEWAY_SERVER) mustHavePeer(ctx, c, ttnpb.ClusterRole_PACKET_BROKER_AGENT) + mustHavePeer(ctx, c, ttnpb.ClusterRole_ENTITY_REGISTRY) receivedAt := time.Date(2020, time.March, 24, 12, 0, 0, 0, time.UTC) @@ -461,63 +488,129 @@ func TestForwarder(t *testing.T) { return ttnpb.Empty, nil } - res, err := gs.UpdateGateway(ctx, &ttnpb.UpdatePacketBrokerGatewayRequest{ - Gateway: &ttnpb.PacketBrokerGateway{ - Ids: &ttnpb.PacketBrokerGateway_GatewayIdentifiers{ - GatewayId: "foo-gateway", - Eui: types.EUI64{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}.Bytes(), - }, - ContactInfo: []*ttnpb.ContactInfo{ - { - ContactType: ttnpb.ContactType_CONTACT_TYPE_OTHER, - ContactMethod: ttnpb.ContactMethod_CONTACT_METHOD_EMAIL, - Value: "admin@example.com", + t.Run("Only contactInfo present", func(t *testing.T) { // nolint:paralleltest + res, err := gs.UpdateGateway(ctx, &ttnpb.UpdatePacketBrokerGatewayRequest{ + Gateway: &ttnpb.PacketBrokerGateway{ + Ids: &ttnpb.PacketBrokerGateway_GatewayIdentifiers{ + GatewayId: "foo-gateway", + Eui: types.EUI64{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}.Bytes(), }, - { - ContactType: ttnpb.ContactType_CONTACT_TYPE_TECHNICAL, - ContactMethod: ttnpb.ContactMethod_CONTACT_METHOD_EMAIL, - Value: "tech@example.com", + ContactInfo: []*ttnpb.ContactInfo{ + { + ContactType: ttnpb.ContactType_CONTACT_TYPE_OTHER, + ContactMethod: ttnpb.ContactMethod_CONTACT_METHOD_EMAIL, + Value: "admin@example.com", + }, + { + ContactType: ttnpb.ContactType_CONTACT_TYPE_TECHNICAL, + ContactMethod: ttnpb.ContactMethod_CONTACT_METHOD_EMAIL, + Value: "tech@example.com", + }, }, - }, - FrequencyPlanIds: []string{"EU_863_870"}, - Antennas: []*ttnpb.GatewayAntenna{ - { - Location: &ttnpb.Location{ - Latitude: 4.85464, - Longitude: 52.34562, - Altitude: 16, - Accuracy: 10, - Source: ttnpb.LocationSource_SOURCE_REGISTRY, + FrequencyPlanIds: []string{"EU_863_870"}, + Antennas: []*ttnpb.GatewayAntenna{ + { + Location: &ttnpb.Location{ + Latitude: 4.85464, + Longitude: 52.34562, + Altitude: 16, + Accuracy: 10, + Source: ttnpb.LocationSource_SOURCE_REGISTRY, + }, }, }, + StatusPublic: true, + LocationPublic: true, + Online: true, }, - StatusPublic: true, - LocationPublic: true, - Online: true, - }, - FieldMask: ttnpb.FieldMask( - "antennas", - "contact_info", - "frequency_plan_ids", - "ids", - "location_public", - "online", - "status_public", - ), + FieldMask: ttnpb.FieldMask( + "antennas", + "contact_info", + "frequency_plan_ids", + "ids", + "location_public", + "online", + "status_public", + ), + }) + a.So(err, should.BeNil) + a.So(res.OnlineTtl.AsDuration(), should.NotBeZeroValue) + + select { + case update := <-updateCh: + a.So(update.AdministrativeContact.GetValue().GetEmail(), should.Equal, "admin@example.com") + a.So(update.TechnicalContact.GetValue().GetEmail(), should.Equal, "tech@example.com") + a.So(update.FrequencyPlan.GetLoraMultiSfChannels(), should.HaveLength, 8) + a.So(update.Online.GetValue(), should.BeTrue) + a.So(update.GatewayLocation.GetLocation().GetTerrestrial().GetAntennaCount().GetValue(), should.Equal, 1) + case <-time.After(timeout): + t.Fatal("Expected gateway update timeout") + } }) - a.So(err, should.BeNil) - a.So(res.OnlineTtl.AsDuration(), should.NotBeZeroValue) - select { - case update := <-updateCh: - a.So(update.AdministrativeContact.GetValue().GetEmail(), should.Equal, "admin@example.com") - a.So(update.TechnicalContact.GetValue().GetEmail(), should.Equal, "tech@example.com") - a.So(update.FrequencyPlan.GetLoraMultiSfChannels(), should.HaveLength, 8) - a.So(update.Online.GetValue(), should.BeTrue) - a.So(update.GatewayLocation.GetLocation().GetTerrestrial().GetAntennaCount().GetValue(), should.Equal, 1) - case <-time.After(timeout): - t.Fatal("Expected gateway update timeout") - } + t.Run("admin-tech contacts present", func(t *testing.T) { // nolint:paralleltest + res, err := gs.UpdateGateway(ctx, &ttnpb.UpdatePacketBrokerGatewayRequest{ + Gateway: &ttnpb.PacketBrokerGateway{ + Ids: &ttnpb.PacketBrokerGateway_GatewayIdentifiers{ + GatewayId: "foo-gateway", + Eui: types.EUI64{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}.Bytes(), + }, + ContactInfo: []*ttnpb.ContactInfo{ + { + ContactType: ttnpb.ContactType_CONTACT_TYPE_OTHER, + ContactMethod: ttnpb.ContactMethod_CONTACT_METHOD_EMAIL, + Value: "admin@example.com", + }, + { + ContactType: ttnpb.ContactType_CONTACT_TYPE_TECHNICAL, + ContactMethod: ttnpb.ContactMethod_CONTACT_METHOD_EMAIL, + Value: "tech@example.com", + }, + }, + AdministrativeContact: userFoo.GetOrganizationOrUserIdentifiers(), + TechnicalContact: orgID.GetOrganizationOrUserIdentifiers(), + FrequencyPlanIds: []string{"EU_863_870"}, + Antennas: []*ttnpb.GatewayAntenna{ + { + Location: &ttnpb.Location{ + Latitude: 4.85464, + Longitude: 52.34562, + Altitude: 16, + Accuracy: 10, + Source: ttnpb.LocationSource_SOURCE_REGISTRY, + }, + }, + }, + StatusPublic: true, + LocationPublic: true, + Online: true, + }, + FieldMask: ttnpb.FieldMask( + "antennas", + "contact_info", + "frequency_plan_ids", + "ids", + "location_public", + "online", + "status_public", + ), + }) + a.So(err, should.BeNil) + a.So(res.OnlineTtl.AsDuration(), should.NotBeZeroValue) + + select { + case update := <-updateCh: + a.So(update.AdministrativeContact.GetValue().GetName(), should.Equal, "foo") + a.So(update.AdministrativeContact.GetValue().GetEmail(), should.Equal, "usr-foo@example.com") + a.So(update.TechnicalContact.GetValue().GetName(), should.Equal, "bar") + a.So(update.TechnicalContact.GetValue().GetEmail(), should.Equal, "usr-bar@example.com") + a.So(update.FrequencyPlan.GetLoraMultiSfChannels(), should.HaveLength, 8) + a.So(update.Online.GetValue(), should.BeTrue) + a.So(update.GatewayLocation.GetLocation().GetTerrestrial().GetAntennaCount().GetValue(), should.Equal, 1) + case <-time.After(timeout): + t.Fatal("Expected gateway update timeout") + } + }) }) }