@@ -268,6 +268,113 @@ func TestEndDevicesPagination(t *testing.T) {
268268 }, withPrivateTestDatabase (p ))
269269}
270270
271+ func TestEndDevicesCount (t * testing.T ) {
272+ p := & storetest.Population {}
273+
274+ usr1 := p .NewUser ()
275+ app1 := p .NewApplication (usr1 .GetOrganizationOrUserIdentifiers ())
276+ for range 5 {
277+ p .NewEndDevice (app1 .GetIds ())
278+ }
279+
280+ key , _ := p .NewAPIKey (usr1 .GetEntityIdentifiers (), ttnpb .Right_RIGHT_ALL )
281+ creds := rpcCreds (key )
282+
283+ readKey , _ := p .NewAPIKey (usr1 .GetEntityIdentifiers (), ttnpb .Right_RIGHT_APPLICATION_DEVICES_READ )
284+ readCreds := rpcCreds (readKey )
285+
286+ t .Parallel ()
287+ a , ctx := test .New (t )
288+
289+ testWithIdentityServer (t , func (_ * IdentityServer , cc * grpc.ClientConn ) {
290+ reg := ttnpb .NewEndDeviceRegistryClient (cc )
291+
292+ t .Run ("Permission denied without credentials" , func (t * testing.T ) { // nolint:paralleltest
293+ _ , err := reg .Count (ctx , & ttnpb.CountEndDevicesRequest {
294+ ApplicationIds : app1 .GetIds (),
295+ })
296+ if a .So (err , should .NotBeNil ) {
297+ a .So (errors .IsPermissionDenied (err ), should .BeTrue )
298+ }
299+ })
300+
301+ t .Run ("Count with read credentials" , func (t * testing.T ) { // nolint:paralleltest
302+ resp , err := reg .Count (ctx , & ttnpb.CountEndDevicesRequest {
303+ ApplicationIds : app1 .GetIds (),
304+ }, readCreds )
305+ if a .So (err , should .BeNil ) && a .So (resp , should .NotBeNil ) {
306+ a .So (resp .Count , should .Equal , uint64 (5 ))
307+ }
308+ })
309+
310+ t .Run ("Count after adding a device" , func (t * testing.T ) { // nolint:paralleltest
311+ _ , err := reg .Create (ctx , & ttnpb.CreateEndDeviceRequest {
312+ EndDevice : & ttnpb.EndDevice {
313+ Ids : & ttnpb.EndDeviceIdentifiers {
314+ ApplicationIds : app1 .GetIds (),
315+ DeviceId : "count-test-dev" ,
316+ },
317+ },
318+ }, creds )
319+ a .So (err , should .BeNil )
320+
321+ resp , err := reg .Count (ctx , & ttnpb.CountEndDevicesRequest {
322+ ApplicationIds : app1 .GetIds (),
323+ }, readCreds )
324+ if a .So (err , should .BeNil ) && a .So (resp , should .NotBeNil ) {
325+ a .So (resp .Count , should .Equal , uint64 (6 ))
326+ }
327+ })
328+
329+ t .Run ("Count after deleting a device" , func (t * testing.T ) { // nolint:paralleltest
330+ _ , err := reg .Delete (ctx , & ttnpb.EndDeviceIdentifiers {
331+ ApplicationIds : app1 .GetIds (),
332+ DeviceId : "count-test-dev" ,
333+ }, creds )
334+ a .So (err , should .BeNil )
335+
336+ resp , err := reg .Count (ctx , & ttnpb.CountEndDevicesRequest {
337+ ApplicationIds : app1 .GetIds (),
338+ }, readCreds )
339+ if a .So (err , should .BeNil ) && a .So (resp , should .NotBeNil ) {
340+ a .So (resp .Count , should .Equal , uint64 (5 ))
341+ }
342+ })
343+
344+ t .Run ("Count with updated_since filter" , func (t * testing.T ) { // nolint:paralleltest
345+ // Filter by 1 hour ago - all devices should match.
346+ resp , err := reg .Count (ctx , & ttnpb.CountEndDevicesRequest {
347+ ApplicationIds : app1 .GetIds (),
348+ Filters : []* ttnpb.ListEndDevicesRequest_Filter {
349+ {
350+ Field : & ttnpb.ListEndDevicesRequest_Filter_UpdatedSince {
351+ UpdatedSince : timestamppb .New (time .Now ().Add (- time .Hour )),
352+ },
353+ },
354+ },
355+ }, readCreds )
356+ if a .So (err , should .BeNil ) && a .So (resp , should .NotBeNil ) {
357+ a .So (resp .Count , should .Equal , uint64 (5 ))
358+ }
359+
360+ // Filter by now - no devices should match.
361+ resp , err = reg .Count (ctx , & ttnpb.CountEndDevicesRequest {
362+ ApplicationIds : app1 .GetIds (),
363+ Filters : []* ttnpb.ListEndDevicesRequest_Filter {
364+ {
365+ Field : & ttnpb.ListEndDevicesRequest_Filter_UpdatedSince {
366+ UpdatedSince : timestamppb .New (time .Now ()),
367+ },
368+ },
369+ },
370+ }, readCreds )
371+ if a .So (err , should .BeNil ) && a .So (resp , should .NotBeNil ) {
372+ a .So (resp .Count , should .Equal , uint64 (0 ))
373+ }
374+ })
375+ }, withPrivateTestDatabase (p ))
376+ }
377+
271378func TestEndDevicesBatchOperationsPermissions (t * testing.T ) {
272379 t .Parallel ()
273380 a , ctx := test .New (t )
0 commit comments