Пример #1
0
func handleTXPayloads(ctx Context) {
	var wg sync.WaitGroup
	for txPayload := range ctx.Application.TXPayloadChan() {
		go func(txPayload models.TXPayload) {
			wg.Add(1)
			defer wg.Done()
			if err := storage.AddTXPayloadToQueue(ctx.RedisPool, txPayload); err != nil {
				log.WithFields(log.Fields{
					"dev_eui":     txPayload.DevEUI,
					"reference":   txPayload.Reference,
					"data_base64": base64.StdEncoding.EncodeToString(txPayload.Data),
				}).Errorf("add tx-payload to queue error: %s", err)
			}
		}(txPayload)
	}
	wg.Wait()
}
Пример #2
0
func runDataUpTests(ctx Context, devEUI lorawan.EUI64, devAddr lorawan.DevAddr, tests []dataUpTestCase) {
	for i, test := range tests {
		Convey(fmt.Sprintf("When testing: %s [%d]", test.Name, i), func() {
			ctx.Application.(*testApplicationBackend).err = test.ApplicationBackendError

			for _, pl := range test.TXPayloadQueue {
				So(storage.AddTXPayloadToQueue(ctx.RedisPool, pl), ShouldBeNil)
			}

			for _, mac := range test.TXMACPayloadQueue {
				So(storage.AddMACPayloadToTXQueue(ctx.RedisPool, mac), ShouldBeNil)
			}

			if test.TXMACPayloadInProcess != nil {
				So(storage.AddTXPayloadToQueue(ctx.RedisPool, *test.TXMACPayloadInProcess), ShouldBeNil)
				_, err := storage.GetTXPayloadFromQueue(ctx.RedisPool, devEUI) // getting an item from the queue will put it into in-process
				So(err, ShouldBeNil)
			}

			So(test.PHYPayload.EncryptFRMPayload(test.EncryptFRMPayloadKey), ShouldBeNil)
			So(test.PHYPayload.SetMIC(test.SetMICKey), ShouldBeNil)

			rxPacket := models.RXPacket{
				PHYPayload: test.PHYPayload,
				RXInfo:     test.RXInfo,
			}

			So(handleRXPacket(ctx, rxPacket), ShouldResemble, test.ExpectedHandleRXPacketError)

			Convey("Then the expected rx-info payloads are sent to the network-controller", func() {
				So(ctx.Controller.(*testControllerBackend).rxInfoPayloadChan, ShouldHaveLength, len(test.ExpectedControllerRXInfoPayloads))
				for _, expPL := range test.ExpectedControllerRXInfoPayloads {
					pl := <-ctx.Controller.(*testControllerBackend).rxInfoPayloadChan
					So(pl, ShouldResemble, expPL)
				}
			})

			Convey("Then the expected error payloads are sent to the network-controller", func() {
				So(ctx.Controller.(*testControllerBackend).errorPayloadChan, ShouldHaveLength, len(test.ExpectedControllerErrorPayloads))
				for _, expPL := range test.ExpectedControllerErrorPayloads {
					pl := <-ctx.Controller.(*testControllerBackend).errorPayloadChan
					So(pl, ShouldResemble, expPL)
				}
			})

			Convey("Then the expected mac-commands are received by the network-controller", func() {
				So(ctx.Controller.(*testControllerBackend).rxMACPayloadChan, ShouldHaveLength, len(test.ExpectedControllerRXMACPayloads))
				for _, expPl := range test.ExpectedControllerRXMACPayloads {
					pl := <-ctx.Controller.(*testControllerBackend).rxMACPayloadChan
					So(pl, ShouldResemble, expPl)
				}
			})

			Convey("Then the expected rx-payloads are received by the application-backend", func() {
				So(ctx.Application.(*testApplicationBackend).rxPayloadChan, ShouldHaveLength, len(test.ExpectedApplicationRXPayloads))
				for _, expPL := range test.ExpectedApplicationRXPayloads {
					pl := <-ctx.Application.(*testApplicationBackend).rxPayloadChan
					So(pl, ShouldResemble, expPL)
				}
			})

			Convey("Then the expected notifications are received by the application-backend", func() {
				So(ctx.Application.(*testApplicationBackend).notificationPayloadChan, ShouldHaveLength, len(test.ExpectedApplicationNotifications))
				for _, expPL := range test.ExpectedApplicationNotifications {
					pl := <-ctx.Application.(*testApplicationBackend).notificationPayloadChan
					So(pl, ShouldResemble, expPL)
				}
			})

			Convey("Then the expected tx-packets are received by the gateway (FRMPayload decrypted and MIC ignored)", func() {
				So(ctx.Gateway.(*testGatewayBackend).txPacketChan, ShouldHaveLength, len(test.ExpectedGatewayTXPackets))
				for _, expPL := range test.ExpectedGatewayTXPackets {
					pl := <-ctx.Gateway.(*testGatewayBackend).txPacketChan
					So(pl.PHYPayload.DecryptFRMPayload(test.DecryptExpectedFRMPayloadKey), ShouldBeNil)
					expPL.PHYPayload.MIC = pl.PHYPayload.MIC
					So(pl, ShouldResemble, expPL)
				}
			})

			Convey("Then the frame-counters are as expected", func() {
				ns, err := storage.GetNodeSessionByDevEUI(ctx.RedisPool, devEUI)
				So(err, ShouldBeNil)
				So(ns.FCntDown, ShouldEqual, test.ExpectedFCntDown)
				So(ns.FCntUp, ShouldEqual, test.ExpectedFCntUp)
			})

			Convey("Then the MACPayload tx-queue is as expected", func() {
				macQueue, err := storage.ReadMACPayloadTXQueue(ctx.RedisPool, devAddr)
				So(err, ShouldBeNil)
				So(macQueue, ShouldResemble, test.ExpectedTXMACPayloadQueue)
			})

			Convey("Then the next TXPayload is as expected", func() {
				txPL, err := storage.GetTXPayloadFromQueue(ctx.RedisPool, devEUI)
				if test.ExpectedGetTXPayloadFromQueue == nil {
					So(err, ShouldResemble, common.ErrEmptyQueue)
				} else {
					So(err, ShouldBeNil)
					So(txPL, ShouldResemble, *test.ExpectedGetTXPayloadFromQueue)
				}
			})
		})
	}
}
Пример #3
0
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)
					})
				})
			})
		})
	})
}