func TestgetRandomDevAddr(t *testing.T) { conf := getConfig() Convey("Given a Redis database and NetID 010203", t, func() { p := NewRedisPool(conf.RedisURL) netID := lorawan.NetID{1, 2, 3} Convey("When calling getRandomDevAddr many times, it should always return an unique DevAddr", func() { log := make(map[lorawan.DevAddr]struct{}) for i := 0; i < 1000; i++ { devAddr, err := getRandomDevAddr(p, netID) if err != nil { t.Fatal(err) } if devAddr.NwkID() != netID.NwkID() { t.Fatalf("%b must equal %b", devAddr.NwkID(), netID.NwkID()) } if len(log) != i { t.Fatalf("%d must equal %d", len(log), i) } log[devAddr] = struct{}{} } }) }) }
// getRandomDevAddr returns a random free DevAddr. Note that the 7 MSB will be // set to the NwkID (based on the configured NetID). // TODO: handle collission with retry? func getRandomDevAddr(p *redis.Pool, netID lorawan.NetID) (lorawan.DevAddr, error) { var d lorawan.DevAddr b := make([]byte, len(d)) if _, err := rand.Read(b); err != nil { return d, fmt.Errorf("could not read from random reader: %s", err) } copy(d[:], b) d[0] = d[0] & 1 // zero out 7 msb d[0] = d[0] ^ (netID.NwkID() << 1) // set 7 msb to NwkID c := p.Get() defer c.Close() key := "node_session_" + d.String() val, err := redis.Int(c.Do("EXISTS", key)) if err != nil { return lorawan.DevAddr{}, fmt.Errorf("test DevAddr %s exist error: %s", d, err) } if val == 1 { return lorawan.DevAddr{}, fmt.Errorf("DevAddr %s already exists", d) } return d, nil }