func TestApplicationMethods(t *testing.T) { conf := common.GetTestConfig() Convey("Given a clean database", t, func() { db, err := OpenDatabase(conf.PostgresDSN) So(err, ShouldBeNil) common.MustResetDB(db) Convey("When creating an application", func() { app := models.Application{ AppEUI: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}, Name: "test app", } So(CreateApplication(db, app), ShouldBeNil) Convey("Then we can get it", func() { app2, err := GetApplication(db, app.AppEUI) So(err, ShouldBeNil) So(app2, ShouldResemble, app) }) Convey("Then get applications returns a single item", func() { apps, err := GetApplications(db, 10, 0) So(err, ShouldBeNil) So(apps, ShouldHaveLength, 1) So(apps[0], ShouldResemble, app) }) Convey("Then applications count returns 1", func() { count, err := GetApplicationsCount(db) So(err, ShouldBeNil) So(count, ShouldEqual, 1) }) Convey("When updating the application", func() { app.Name = "new name" So(UpdateApplication(db, app), ShouldBeNil) Convey("The application has been updated", func() { app2, err := GetApplication(db, app.AppEUI) So(err, ShouldBeNil) So(app2, ShouldResemble, app) }) }) Convey("After deleting the application", func() { So(DeleteApplication(db, app.AppEUI), ShouldBeNil) Convey("The application has gone", func() { count, err := GetApplicationsCount(db) So(err, ShouldBeNil) So(count, ShouldEqual, 0) }) }) }) }) }
func TestApplicationAPI(t *testing.T) { conf := common.GetTestConfig() Convey("Given a clean database and api instance", t, func() { db, err := storage.OpenDatabase(conf.PostgresDSN) So(err, ShouldBeNil) common.MustResetDB(db) ctx := context.Background() lsCtx := loraserver.Context{DB: db} api := NewApplicationAPI(lsCtx) Convey("When creating an application", func() { _, err := api.Create(ctx, &pb.CreateApplicationRequest{AppEUI: "0102030405060708", Name: "test app"}) So(err, ShouldBeNil) Convey("Then we can get it", func() { resp, err := api.Get(ctx, &pb.GetApplicationRequest{AppEUI: "0102030405060708"}) So(err, ShouldBeNil) So(resp, ShouldResemble, &pb.GetApplicationResponse{AppEUI: "0102030405060708", Name: "test app"}) }) Convey("Then listing the applications returns a single item", func() { resp, err := api.List(ctx, &pb.ListApplicationRequest{Limit: 10}) So(err, ShouldBeNil) So(resp.Result, ShouldHaveLength, 1) So(resp.TotalCount, ShouldEqual, 1) So(resp.Result[0], ShouldResemble, &pb.GetApplicationResponse{AppEUI: "0102030405060708", Name: "test app"}) }) Convey("When updating the application", func() { _, err := api.Update(ctx, &pb.UpdateApplicationRequest{AppEUI: "0102030405060708", Name: "test app 2"}) So(err, ShouldBeNil) Convey("Then the application has been updated", func() { resp, err := api.Get(ctx, &pb.GetApplicationRequest{AppEUI: "0102030405060708"}) So(err, ShouldBeNil) So(resp.Name, ShouldEqual, "test app 2") }) }) Convey("After deleting the application", func() { _, err := api.Delete(ctx, &pb.DeleteApplicationRequest{AppEUI: "0102030405060708"}) So(err, ShouldBeNil) Convey("Then listing the applications resturns zero items", func() { resp, err := api.List(ctx, &pb.ListApplicationRequest{Limit: 10}) So(err, ShouldBeNil) So(resp.Result, ShouldHaveLength, 0) }) }) }) }) }
func TestNodeMethods(t *testing.T) { conf := common.GetTestConfig() Convey("Given a clean database with application", t, func() { db, err := OpenDatabase(conf.PostgresDSN) So(err, ShouldBeNil) common.MustResetDB(db) app := models.Application{ AppEUI: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}, Name: "test app", } So(CreateApplication(db, app), ShouldBeNil) Convey("When creating a node", func() { node := models.Node{ DevEUI: [8]byte{8, 7, 6, 5, 4, 3, 2, 1}, AppEUI: app.AppEUI, AppKey: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}, RXDelay: 2, RX1DROffset: 3, } So(CreateNode(db, node), ShouldBeNil) Convey("Whe can get it", func() { node2, err := GetNode(db, node.DevEUI) node2.UsedDevNonces = nil So(err, ShouldBeNil) So(node2, ShouldResemble, node) }) Convey("Then get nodes returns a single item", func() { nodes, err := GetNodes(db, 10, 0) So(err, ShouldBeNil) So(nodes, ShouldHaveLength, 1) nodes[0].UsedDevNonces = nil So(nodes[0], ShouldResemble, node) }) Convey("Then get nodes for AppEUI returns a single item", func() { nodes, err := GetNodesForAppEUI(db, app.AppEUI, 10, 0) So(err, ShouldBeNil) So(nodes, ShouldHaveLength, 1) nodes[0].UsedDevNonces = nil So(nodes[0], ShouldResemble, node) }) Convey("Then get nodes count returns 1", func() { count, err := GetNodesCount(db) So(err, ShouldBeNil) So(count, ShouldEqual, 1) }) Convey("Then get nodes count for AppEUI returns 1", func() { count, err := GetNodesForAppEUICount(db, app.AppEUI) So(err, ShouldBeNil) So(count, ShouldEqual, 1) }) Convey("When updating the node", func() { node.AppKey = [16]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} So(UpdateNode(db, node), ShouldBeNil) Convey("Then the nodes has been updated", func() { node2, err := GetNode(db, node.DevEUI) So(err, ShouldBeNil) node2.UsedDevNonces = nil So(node2, ShouldResemble, node) }) }) Convey("When deleting the node", func() { So(DeleteNode(db, node.DevEUI), ShouldBeNil) Convey("Then get nodes count returns 0", func() { count, err := GetNodesCount(db) So(err, ShouldBeNil) So(count, ShouldEqual, 0) }) }) }) }) }
func TestNodeSessionAPI(t *testing.T) { conf := common.GetTestConfig() Convey("Given a clean database and api instance", t, func() { db, err := storage.OpenDatabase(conf.PostgresDSN) So(err, ShouldBeNil) common.MustResetDB(db) p := storage.NewRedisPool(conf.RedisURL) common.MustFlushRedis(p) lsCtx := loraserver.Context{DB: db, RedisPool: p, NetID: [3]byte{1, 2, 3}} ctx := context.Background() api := NewNodeSessionAPI(lsCtx) Convey("Given an application and node are created (fk constraints)", func() { app := models.Application{ AppEUI: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}, Name: "test app", } So(storage.CreateApplication(db, app), ShouldBeNil) node := models.Node{ DevEUI: [8]byte{8, 7, 6, 5, 4, 3, 2, 1}, AppEUI: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}, AppKey: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, UsedDevNonces: [][2]byte{}, } So(storage.CreateNode(db, node), ShouldBeNil) Convey("When creating a node-session", func() { _, err := api.Create(ctx, &pb.CreateNodeSessionRequest{ DevAddr: "06020304", DevEUI: node.DevEUI.String(), AppEUI: node.AppEUI.String(), AppSKey: node.AppKey.String(), NwkSKey: node.AppKey.String(), FCntUp: 10, FCntDown: 11, RxDelay: 1, Rx1DROffset: 2, CFList: []uint32{ 868700000, }, }) So(err, ShouldBeNil) Convey("Then it can be retrieved by DevAddr", func() { resp, err := api.Get(ctx, &pb.GetNodeSessionRequest{DevAddr: "06020304"}) So(err, ShouldBeNil) So(resp, ShouldResemble, &pb.GetNodeSessionResponse{ DevAddr: "06020304", DevEUI: node.DevEUI.String(), AppEUI: node.AppEUI.String(), AppSKey: node.AppKey.String(), NwkSKey: node.AppKey.String(), FCntUp: 10, FCntDown: 11, RxDelay: 1, Rx1DROffset: 2, CFList: []uint32{ 868700000, 0, 0, 0, 0, }, }) }) Convey("Then it can be retrieved by DevEUI", func() { resp, err := api.GetByDevEUI(ctx, &pb.GetNodeSessionByDevEUIRequest{DevEUI: node.DevEUI.String()}) So(err, ShouldBeNil) So(resp, ShouldResemble, &pb.GetNodeSessionResponse{ DevAddr: "06020304", DevEUI: node.DevEUI.String(), AppEUI: node.AppEUI.String(), AppSKey: node.AppKey.String(), NwkSKey: node.AppKey.String(), FCntUp: 10, FCntDown: 11, RxDelay: 1, Rx1DROffset: 2, CFList: []uint32{ 868700000, 0, 0, 0, 0, }, }) }) Convey("When updating the node-session", func() { _, err := api.Update(ctx, &pb.UpdateNodeSessionRequest{ DevAddr: "06020304", DevEUI: node.DevEUI.String(), AppEUI: node.AppEUI.String(), AppSKey: node.AppKey.String(), NwkSKey: node.AppKey.String(), FCntUp: 20, FCntDown: 22, RxDelay: 10, Rx1DROffset: 20, CFList: []uint32{ 868700000, 868800000, }, }) So(err, ShouldBeNil) Convey("Then the node-session has been updated", func() { resp, err := api.Get(ctx, &pb.GetNodeSessionRequest{DevAddr: "06020304"}) So(err, ShouldBeNil) So(resp, ShouldResemble, &pb.GetNodeSessionResponse{ DevAddr: "06020304", DevEUI: node.DevEUI.String(), AppEUI: node.AppEUI.String(), AppSKey: node.AppKey.String(), NwkSKey: node.AppKey.String(), FCntUp: 20, FCntDown: 22, RxDelay: 10, Rx1DROffset: 20, CFList: []uint32{ 868700000, 868800000, 0, 0, 0, }, }) }) }) Convey("When deleting the node-session", func() { _, err := api.Delete(ctx, &pb.DeleteNodeSessionRequest{DevAddr: "06020304"}) So(err, ShouldBeNil) Convey("Then the node-session has been deleted", func() { _, err := api.Get(ctx, &pb.GetNodeSessionRequest{DevAddr: "06020304"}) So(err, ShouldNotBeNil) }) }) }) }) }) }
func TestHandleJoinRequestPackets(t *testing.T) { conf := common.GetTestConfig() Convey("Given a dummy gateway and application backend and a clean Postgres and Redis database", t, func() { a := &testApplicationBackend{ rxPayloadChan: make(chan models.RXPayload, 1), notificationPayloadChan: make(chan interface{}, 10), } g := &testGatewayBackend{ rxPacketChan: make(chan models.RXPacket, 1), txPacketChan: make(chan models.TXPacket, 1), } p := storage.NewRedisPool(conf.RedisURL) common.MustFlushRedis(p) db, err := storage.OpenDatabase(conf.PostgresDSN) So(err, ShouldBeNil) common.MustResetDB(db) ctx := Context{ RedisPool: p, Gateway: g, Application: a, DB: db, } Convey("Given a node and application in the database", func() { app := models.Application{ AppEUI: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}, Name: "test app", } So(storage.CreateApplication(ctx.DB, app), ShouldBeNil) node := models.Node{ DevEUI: [8]byte{8, 7, 6, 5, 4, 3, 2, 1}, AppEUI: app.AppEUI, AppKey: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, RXDelay: 3, RX1DROffset: 2, } So(storage.CreateNode(ctx.DB, node), ShouldBeNil) Convey("Given a JoinRequest with correct DevEUI but incorrect AppEUI", func() { phy := lorawan.PHYPayload{ MHDR: lorawan.MHDR{ MType: lorawan.JoinRequest, Major: lorawan.LoRaWANR1, }, MACPayload: &lorawan.JoinRequestPayload{ AppEUI: [8]byte{1, 2, 3, 4, 5, 6, 7, 9}, DevEUI: node.DevEUI, DevNonce: [2]byte{1, 2}, }, } So(phy.SetMIC(node.AppKey), ShouldBeNil) rxPacket := models.RXPacket{ PHYPayload: phy, RXInfo: models.RXInfo{ Frequency: common.Band.UplinkChannels[0].Frequency, DataRate: common.Band.DataRates[common.Band.UplinkChannels[0].DataRates[0]], }, } Convey("then handleRXPacket returns an error", func() { So(handleRXPacket(ctx, rxPacket), ShouldResemble, errors.New("node 0807060504030201 belongs to application 0102030405060708, 0102030405060709 was given")) }) }) Convey("Given a JoinRequest packet", func() { phy := lorawan.PHYPayload{ MHDR: lorawan.MHDR{ MType: lorawan.JoinRequest, Major: lorawan.LoRaWANR1, }, MACPayload: &lorawan.JoinRequestPayload{ AppEUI: app.AppEUI, DevEUI: node.DevEUI, DevNonce: [2]byte{1, 2}, }, } So(phy.SetMIC(node.AppKey), ShouldBeNil) rxPacket := models.RXPacket{ PHYPayload: phy, RXInfo: models.RXInfo{ Frequency: common.Band.UplinkChannels[0].Frequency, DataRate: common.Band.DataRates[common.Band.UplinkChannels[0].DataRates[0]], }, } Convey("When calling handleRXPacket", func() { So(handleRXPacket(ctx, rxPacket), ShouldBeNil) Convey("Then a JoinAccept was sent to the node", func() { txPacket := <-g.txPacketChan phy := txPacket.PHYPayload So(phy.DecryptJoinAcceptPayload(node.AppKey), ShouldBeNil) So(phy.MHDR.MType, ShouldEqual, lorawan.JoinAccept) Convey("Then it was sent after 5s", func() { So(txPacket.TXInfo.Timestamp, ShouldEqual, rxPacket.RXInfo.Timestamp+uint32(5*time.Second/time.Microsecond)) }) Convey("Then the RXDelay is set to 3s", func() { jaPL := phy.MACPayload.(*lorawan.JoinAcceptPayload) So(jaPL.RXDelay, ShouldEqual, 3) }) Convey("Then the DLSettings are set correctly", func() { jaPL := phy.MACPayload.(*lorawan.JoinAcceptPayload) So(jaPL.DLSettings.RX2DataRate, ShouldEqual, uint8(common.Band.RX2DataRate)) So(jaPL.DLSettings.RX1DROffset, ShouldEqual, node.RX1DROffset) }) Convey("Then a node-session was created", func() { jaPL := phy.MACPayload.(*lorawan.JoinAcceptPayload) _, err := storage.GetNodeSession(ctx.RedisPool, jaPL.DevAddr) So(err, ShouldBeNil) }) Convey("Then the dev-nonce was added to the used dev-nonces", func() { node, err := storage.GetNode(ctx.DB, node.DevEUI) So(err, ShouldBeNil) So([2]byte{1, 2}, ShouldBeIn, node.UsedDevNonces) }) Convey("Then a join notification was sent to the application", func() { notification := <-a.notificationPayloadChan join, ok := notification.(models.JoinNotification) So(ok, ShouldBeTrue) So(join.DevEUI, ShouldResemble, node.DevEUI) }) }) }) }) }) }) }
func TestNodeAPI(t *testing.T) { conf := common.GetTestConfig() Convey("Given a clean database with an application and api instance", t, func() { db, err := storage.OpenDatabase(conf.PostgresDSN) So(err, ShouldBeNil) common.MustResetDB(db) p := storage.NewRedisPool(conf.RedisURL) common.MustFlushRedis(p) ctx := context.Background() lsCtx := loraserver.Context{DB: db, RedisPool: p} api := NewNodeAPI(lsCtx) app := models.Application{ AppEUI: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}, Name: "test app", } So(storage.CreateApplication(db, app), ShouldBeNil) Convey("When creating a node", func() { _, err := api.Create(ctx, &pb.CreateNodeRequest{ DevEUI: "0807060504030201", AppEUI: "0102030405060708", AppKey: "01020304050607080102030405060708", RxDelay: 1, Rx1DROffset: 3, }) So(err, ShouldBeNil) Convey("The node has been created", func() { node, err := api.Get(ctx, &pb.GetNodeRequest{DevEUI: "0807060504030201"}) So(err, ShouldBeNil) So(node, ShouldResemble, &pb.GetNodeResponse{ DevEUI: "0807060504030201", AppEUI: "0102030405060708", AppKey: "01020304050607080102030405060708", RxDelay: 1, Rx1DROffset: 3, }) }) Convey("Then listing the nodes returns a single items", func() { nodes, err := api.List(ctx, &pb.ListNodeRequest{ Limit: 10, }) So(err, ShouldBeNil) So(nodes.Result, ShouldHaveLength, 1) So(nodes.TotalCount, ShouldEqual, 1) So(nodes.Result[0], ShouldResemble, &pb.GetNodeResponse{ DevEUI: "0807060504030201", AppEUI: "0102030405060708", AppKey: "01020304050607080102030405060708", RxDelay: 1, Rx1DROffset: 3, }) }) Convey("Then listing the nodes for a given AppEUI returns a single item", func() { nodes, err := api.ListByAppEUI(ctx, &pb.ListNodeByAppEUIRequest{ Limit: 10, AppEUI: "0102030405060708", }) So(err, ShouldBeNil) So(nodes.Result, ShouldHaveLength, 1) So(nodes.TotalCount, ShouldEqual, 1) So(nodes.Result[0], ShouldResemble, &pb.GetNodeResponse{ DevEUI: "0807060504030201", AppEUI: "0102030405060708", AppKey: "01020304050607080102030405060708", RxDelay: 1, Rx1DROffset: 3, }) }) Convey("When updating the node", func() { _, err := api.Update(ctx, &pb.UpdateNodeRequest{ DevEUI: "0807060504030201", AppEUI: "0102030405060708", AppKey: "08070605040302010807060504030201", RxDelay: 3, Rx1DROffset: 1, }) So(err, ShouldBeNil) Convey("Then the node has been updated", func() { node, err := api.Get(ctx, &pb.GetNodeRequest{DevEUI: "0807060504030201"}) So(err, ShouldBeNil) So(node, ShouldResemble, &pb.GetNodeResponse{ DevEUI: "0807060504030201", AppEUI: "0102030405060708", AppKey: "08070605040302010807060504030201", RxDelay: 3, Rx1DROffset: 1, }) }) }) Convey("After deleting the node", func() { _, err := api.Delete(ctx, &pb.DeleteNodeRequest{DevEUI: "0807060504030201"}) So(err, ShouldBeNil) Convey("Then listing the nodes returns zero nodes", func() { nodes, err := api.List(ctx, &pb.ListNodeRequest{Limit: 10}) So(err, ShouldBeNil) So(nodes.TotalCount, ShouldEqual, 0) So(nodes.Result, ShouldHaveLength, 0) }) }) Convey("Given a tx payload in the the queue", func() { So(storage.AddTXPayloadToQueue(p, models.TXPayload{ DevEUI: [8]byte{8, 7, 6, 5, 4, 3, 2, 1}, Data: []byte("hello!"), }), ShouldBeNil) count, err := storage.GetTXPayloadQueueSize(p, [8]byte{8, 7, 6, 5, 4, 3, 2, 1}) So(err, ShouldBeNil) So(count, ShouldEqual, 1) Convey("When flushing the tx-payload queue", func() { _, err := api.FlushTXPayloadQueue(ctx, &pb.FlushTXPayloadQueueRequest{DevEUI: "0807060504030201"}) So(err, ShouldBeNil) Convey("Then the queue is empty", func() { count, err := storage.GetTXPayloadQueueSize(p, [8]byte{8, 7, 6, 5, 4, 3, 2, 1}) So(err, ShouldBeNil) So(count, ShouldEqual, 0) }) }) }) }) }) }
func TestChannelFunctions(t *testing.T) { conf := common.GetTestConfig() Convey("Given a clean database", t, func() { db, err := OpenDatabase(conf.PostgresDSN) So(err, ShouldBeNil) common.MustResetDB(db) Convey("When creating a channel-list", func() { cl := models.ChannelList{ Name: "test channel-list", } So(CreateChannelList(db, &cl), ShouldBeNil) Convey("Then the channel-list exists", func() { cl2, err := GetChannelList(db, cl.ID) So(err, ShouldBeNil) So(cl2, ShouldResemble, cl) }) Convey("When updating the channel-list", func() { cl.Name = "test channel-list changed" So(UpdateChannelList(db, cl), ShouldBeNil) Convey("Then the channel-list has been updated", func() { cl2, err := GetChannelList(db, cl.ID) So(err, ShouldBeNil) So(cl2, ShouldResemble, cl) }) }) Convey("Then listing the channel-lists returns 1 result", func() { lists, err := GetChannelLists(db, 10, 0) So(err, ShouldBeNil) So(lists, ShouldHaveLength, 1) So(lists[0], ShouldResemble, cl) }) Convey("Then the channel-list count returns 1", func() { count, err := GetChannelListsCount(db) So(err, ShouldBeNil) So(count, ShouldEqual, 1) }) Convey("When deleting the channel-list", func() { So(DeleteChannelList(db, cl.ID), ShouldBeNil) Convey("Then the channel-list has been removed", func() { count, err := GetChannelListsCount(db) So(err, ShouldBeNil) So(count, ShouldEqual, 0) }) }) Convey("When creating a channel", func() { c := models.Channel{ ChannelListID: cl.ID, Channel: 4, Frequency: 868700000, } So(CreateChannel(db, &c), ShouldBeNil) Convey("Then the channel has been created", func() { c2, err := GetChannel(db, c.ID) So(err, ShouldBeNil) So(c2, ShouldResemble, c) }) Convey("When updating the channel", func() { c.Channel = 5 So(UpdateChannel(db, c), ShouldBeNil) Convey("Then the channel has been updated", func() { c2, err := GetChannel(db, c.ID) So(err, ShouldBeNil) So(c2, ShouldResemble, c) }) }) Convey("When deleting the channel", func() { So(DeleteChannel(db, c.ID), ShouldBeNil) Convey("Then the channel has been deleted", func() { _, err := GetChannel(db, c.ID) So(err, ShouldNotBeNil) }) }) Convey("When getting all channels for the channel-list", func() { channels, err := GetChannelsForChannelList(db, cl.ID) So(err, ShouldBeNil) Convey("Then it contains the channel", func() { So(channels, ShouldHaveLength, 1) So(channels[0], ShouldResemble, c) }) }) }) }) }) }
func TestChannelListAndChannelAPI(t *testing.T) { conf := common.GetTestConfig() Convey("Given a clean database and api instances", t, func() { db, err := storage.OpenDatabase(conf.PostgresDSN) So(err, ShouldBeNil) common.MustResetDB(db) ctx := context.Background() lsCtx := loraserver.Context{DB: db} cAPI := NewChannelAPI(lsCtx) clAPI := NewChannelListAPI(lsCtx) Convey("When creating a channel-list", func() { resp, err := clAPI.Create(ctx, &pb.CreateChannelListRequest{Name: "test channel-list"}) So(err, ShouldBeNil) clID := resp.Id Convey("Then the channel-list has been created", func() { cl, err := clAPI.Get(ctx, &pb.GetChannelListRequest{Id: clID}) So(err, ShouldBeNil) So(cl, ShouldResemble, &pb.GetChannelListResponse{Id: clID, Name: "test channel-list"}) }) Convey("When updating the channel-list", func() { _, err := clAPI.Update(ctx, &pb.UpdateChannelListRequest{Id: clID, Name: "test channel-list changed"}) So(err, ShouldBeNil) Convey("Then the channel-list has been updated", func() { cl, err := clAPI.Get(ctx, &pb.GetChannelListRequest{Id: clID}) So(err, ShouldBeNil) So(cl, ShouldResemble, &pb.GetChannelListResponse{Id: clID, Name: "test channel-list changed"}) }) }) Convey("Then listing the channel-lists returns 1 result", func() { resp, err := clAPI.List(ctx, &pb.ListChannelListRequest{Limit: 10, Offset: 0}) So(err, ShouldBeNil) So(resp.TotalCount, ShouldEqual, 1) So(resp.Result, ShouldHaveLength, 1) So(resp.Result[0], ShouldResemble, &pb.GetChannelListResponse{Id: clID, Name: "test channel-list"}) }) Convey("When deleting the channel-list", func() { _, err := clAPI.Delete(ctx, &pb.DeleteChannelListRequest{Id: clID}) So(err, ShouldBeNil) Convey("Then the channel-list has been deleted", func() { resp, err := clAPI.List(ctx, &pb.ListChannelListRequest{Limit: 10, Offset: 0}) So(err, ShouldBeNil) So(resp.TotalCount, ShouldEqual, 0) }) }) Convey("When creating a channel", func() { resp, err := cAPI.Create(ctx, &pb.CreateChannelRequest{ ChannelListID: clID, Channel: 4, Frequency: 868700000, }) So(err, ShouldBeNil) cID := resp.Id Convey("Then the channel has been created", func() { resp, err := cAPI.Get(ctx, &pb.GetChannelRequest{Id: cID}) So(err, ShouldBeNil) So(resp, ShouldResemble, &pb.GetChannelResponse{ Id: cID, ChannelListID: clID, Channel: 4, Frequency: 868700000, }) Convey("When updating the channel", func() { _, err := cAPI.Update(ctx, &pb.UpdateChannelRequest{ Id: cID, ChannelListID: clID, Channel: 5, Frequency: 868700000, }) So(err, ShouldBeNil) Convey("Then the channel has been updated", func() { resp, err := cAPI.Get(ctx, &pb.GetChannelRequest{Id: cID}) So(err, ShouldBeNil) So(resp, ShouldResemble, &pb.GetChannelResponse{ Id: cID, ChannelListID: clID, Channel: 5, Frequency: 868700000, }) }) }) Convey("When deleting the channel", func() { _, err := cAPI.Delete(ctx, &pb.DeleteChannelRequest{Id: cID}) So(err, ShouldBeNil) Convey("Then the channel has been deleted", func() { _, err := cAPI.Get(ctx, &pb.GetChannelRequest{Id: cID}) So(err, ShouldNotBeNil) }) }) Convey("When getting all channels for the channel-list", func() { resp, err := cAPI.ListByChannelList(ctx, &pb.ListChannelsByChannelListRequest{Id: clID}) So(err, ShouldBeNil) Convey("Then it contains the channel", func() { So(resp.Result, ShouldHaveLength, 1) So(resp.Result[0], ShouldResemble, &pb.GetChannelResponse{ Id: cID, ChannelListID: clID, Channel: 4, Frequency: 868700000, }) }) }) }) }) }) }) }