1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.healthconnect.cts; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.content.Context; 22 import android.health.connect.DeleteUsingFiltersRequest; 23 import android.health.connect.HealthConnectException; 24 import android.health.connect.ReadRecordsRequestUsingFilters; 25 import android.health.connect.ReadRecordsRequestUsingIds; 26 import android.health.connect.RecordIdFilter; 27 import android.health.connect.TimeInstantRangeFilter; 28 import android.health.connect.changelog.ChangeLogTokenRequest; 29 import android.health.connect.changelog.ChangeLogTokenResponse; 30 import android.health.connect.changelog.ChangeLogsRequest; 31 import android.health.connect.changelog.ChangeLogsResponse; 32 import android.health.connect.datatypes.DataOrigin; 33 import android.health.connect.datatypes.Device; 34 import android.health.connect.datatypes.Metadata; 35 import android.health.connect.datatypes.Record; 36 import android.health.connect.datatypes.StepsCadenceRecord; 37 import android.platform.test.annotations.AppModeFull; 38 39 import androidx.test.core.app.ApplicationProvider; 40 import androidx.test.runner.AndroidJUnit4; 41 42 import org.junit.After; 43 import org.junit.Assert; 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 48 import java.time.Instant; 49 import java.time.ZoneOffset; 50 import java.util.ArrayList; 51 import java.util.Arrays; 52 import java.util.Collections; 53 import java.util.List; 54 import java.util.UUID; 55 56 @AppModeFull(reason = "HealthConnectManager is not accessible to instant apps") 57 @RunWith(AndroidJUnit4.class) 58 public class StepsCadenceRecordTest { 59 60 private static final String TAG = "StepsCadenceRecordTest"; 61 62 @Before setUp()63 public void setUp() { 64 // TODO(b/283737434): Update the HC code to use user aware context on permission change. 65 // Temporary fix to set firstGrantTime for the correct user in HSUM. 66 TestUtils.deleteAllStagedRemoteData(); 67 } 68 69 @After tearDown()70 public void tearDown() throws InterruptedException { 71 TestUtils.verifyDeleteRecords( 72 StepsCadenceRecord.class, 73 new TimeInstantRangeFilter.Builder() 74 .setStartTime(Instant.EPOCH) 75 .setEndTime(Instant.now()) 76 .build()); 77 TestUtils.deleteAllStagedRemoteData(); 78 } 79 80 @Test testInsertStepsCadenceRecord()81 public void testInsertStepsCadenceRecord() throws InterruptedException { 82 TestUtils.insertRecords( 83 Arrays.asList(getBaseStepsCadenceRecord(), getCompleteStepsCadenceRecord())); 84 } 85 86 @Test testReadStepsCadenceRecord_usingIds()87 public void testReadStepsCadenceRecord_usingIds() throws InterruptedException { 88 testReadStepsCadenceRecordIds(); 89 } 90 91 @Test testReadStepsCadenceRecord_invalidIds()92 public void testReadStepsCadenceRecord_invalidIds() throws InterruptedException { 93 ReadRecordsRequestUsingIds<StepsCadenceRecord> request = 94 new ReadRecordsRequestUsingIds.Builder<>(StepsCadenceRecord.class) 95 .addId(UUID.randomUUID().toString()) 96 .build(); 97 List<StepsCadenceRecord> result = TestUtils.readRecords(request); 98 assertThat(result.size()).isEqualTo(0); 99 } 100 101 @Test testReadStepsCadenceRecord_usingClientRecordIds()102 public void testReadStepsCadenceRecord_usingClientRecordIds() throws InterruptedException { 103 List<Record> recordList = 104 Arrays.asList(getCompleteStepsCadenceRecord(), getCompleteStepsCadenceRecord()); 105 List<Record> insertedRecords = TestUtils.insertRecords(recordList); 106 readStepsCadenceRecordUsingClientId(insertedRecords); 107 } 108 109 @Test testReadStepsCadenceRecord_invalidClientRecordIds()110 public void testReadStepsCadenceRecord_invalidClientRecordIds() throws InterruptedException { 111 ReadRecordsRequestUsingIds<StepsCadenceRecord> request = 112 new ReadRecordsRequestUsingIds.Builder<>(StepsCadenceRecord.class) 113 .addClientRecordId("abc") 114 .build(); 115 List<StepsCadenceRecord> result = TestUtils.readRecords(request); 116 assertThat(result.size()).isEqualTo(0); 117 } 118 119 @Test testReadStepsCadenceRecordUsingFilters_default()120 public void testReadStepsCadenceRecordUsingFilters_default() throws InterruptedException { 121 List<StepsCadenceRecord> oldStepsCadenceRecords = 122 TestUtils.readRecords( 123 new ReadRecordsRequestUsingFilters.Builder<>(StepsCadenceRecord.class) 124 .build()); 125 StepsCadenceRecord testRecord = getCompleteStepsCadenceRecord(); 126 TestUtils.insertRecords(Collections.singletonList(testRecord)); 127 List<StepsCadenceRecord> newStepsCadenceRecords = 128 TestUtils.readRecords( 129 new ReadRecordsRequestUsingFilters.Builder<>(StepsCadenceRecord.class) 130 .build()); 131 assertThat(newStepsCadenceRecords.size()).isEqualTo(oldStepsCadenceRecords.size() + 1); 132 assertThat(newStepsCadenceRecords.get(newStepsCadenceRecords.size() - 1).equals(testRecord)) 133 .isTrue(); 134 } 135 136 @Test testReadStepsCadenceRecordUsingFilters_timeFilter()137 public void testReadStepsCadenceRecordUsingFilters_timeFilter() throws InterruptedException { 138 TimeInstantRangeFilter filter = 139 new TimeInstantRangeFilter.Builder() 140 .setStartTime(Instant.now()) 141 .setEndTime(Instant.now().plusMillis(3000)) 142 .build(); 143 StepsCadenceRecord testRecord = getCompleteStepsCadenceRecord(); 144 TestUtils.insertRecords(Collections.singletonList(testRecord)); 145 List<StepsCadenceRecord> newStepsCadenceRecords = 146 TestUtils.readRecords( 147 new ReadRecordsRequestUsingFilters.Builder<>(StepsCadenceRecord.class) 148 .setTimeRangeFilter(filter) 149 .build()); 150 assertThat(newStepsCadenceRecords.size()).isEqualTo(1); 151 assertThat(newStepsCadenceRecords.get(newStepsCadenceRecords.size() - 1).equals(testRecord)) 152 .isTrue(); 153 } 154 155 @Test testReadStepsCadenceRecordUsingFilters_dataFilter_correct()156 public void testReadStepsCadenceRecordUsingFilters_dataFilter_correct() 157 throws InterruptedException { 158 Context context = ApplicationProvider.getApplicationContext(); 159 List<StepsCadenceRecord> oldStepsCadenceRecords = 160 TestUtils.readRecords( 161 new ReadRecordsRequestUsingFilters.Builder<>(StepsCadenceRecord.class) 162 .addDataOrigins( 163 new DataOrigin.Builder() 164 .setPackageName(context.getPackageName()) 165 .build()) 166 .build()); 167 StepsCadenceRecord testRecord = getCompleteStepsCadenceRecord(); 168 TestUtils.insertRecords(Collections.singletonList(testRecord)); 169 List<StepsCadenceRecord> newStepsCadenceRecords = 170 TestUtils.readRecords( 171 new ReadRecordsRequestUsingFilters.Builder<>(StepsCadenceRecord.class) 172 .addDataOrigins( 173 new DataOrigin.Builder() 174 .setPackageName(context.getPackageName()) 175 .build()) 176 .build()); 177 assertThat(newStepsCadenceRecords.size() - oldStepsCadenceRecords.size()).isEqualTo(1); 178 assertThat(newStepsCadenceRecords.get(newStepsCadenceRecords.size() - 1).equals(testRecord)) 179 .isTrue(); 180 StepsCadenceRecord newRecord = 181 newStepsCadenceRecords.get(newStepsCadenceRecords.size() - 1); 182 assertThat(newRecord.equals(testRecord)).isTrue(); 183 for (int idx = 0; idx < newRecord.getSamples().size(); idx++) { 184 assertThat(newRecord.getSamples().get(idx).getTime().toEpochMilli()) 185 .isEqualTo(testRecord.getSamples().get(idx).getTime().toEpochMilli()); 186 assertThat(newRecord.getSamples().get(idx).getRate()) 187 .isEqualTo(testRecord.getSamples().get(idx).getRate()); 188 } 189 } 190 191 @Test testReadStepsCadenceRecordUsingFilters_dataFilter_incorrect()192 public void testReadStepsCadenceRecordUsingFilters_dataFilter_incorrect() 193 throws InterruptedException { 194 TestUtils.insertRecords(Collections.singletonList(getCompleteStepsCadenceRecord())); 195 List<StepsCadenceRecord> newStepsCadenceRecords = 196 TestUtils.readRecords( 197 new ReadRecordsRequestUsingFilters.Builder<>(StepsCadenceRecord.class) 198 .addDataOrigins( 199 new DataOrigin.Builder().setPackageName("abc").build()) 200 .build()); 201 assertThat(newStepsCadenceRecords.size()).isEqualTo(0); 202 } 203 204 @Test testDeleteStepsCadenceRecord_no_filters()205 public void testDeleteStepsCadenceRecord_no_filters() throws InterruptedException { 206 String id = TestUtils.insertRecordAndGetId(getCompleteStepsCadenceRecord()); 207 TestUtils.verifyDeleteRecords(new DeleteUsingFiltersRequest.Builder().build()); 208 TestUtils.assertRecordNotFound(id, StepsCadenceRecord.class); 209 } 210 211 @Test testDeleteStepsCadenceRecord_time_filters()212 public void testDeleteStepsCadenceRecord_time_filters() throws InterruptedException { 213 TimeInstantRangeFilter timeRangeFilter = 214 new TimeInstantRangeFilter.Builder() 215 .setStartTime(Instant.now()) 216 .setEndTime(Instant.now().plusMillis(1000)) 217 .build(); 218 String id = TestUtils.insertRecordAndGetId(getCompleteStepsCadenceRecord()); 219 TestUtils.verifyDeleteRecords( 220 new DeleteUsingFiltersRequest.Builder() 221 .addRecordType(StepsCadenceRecord.class) 222 .setTimeRangeFilter(timeRangeFilter) 223 .build()); 224 TestUtils.assertRecordNotFound(id, StepsCadenceRecord.class); 225 } 226 227 @Test testDeleteStepsCadenceRecord_recordId_filters()228 public void testDeleteStepsCadenceRecord_recordId_filters() throws InterruptedException { 229 List<Record> records = 230 List.of(getBaseStepsCadenceRecord(), getCompleteStepsCadenceRecord()); 231 TestUtils.insertRecords(records); 232 233 for (Record record : records) { 234 TestUtils.verifyDeleteRecords( 235 new DeleteUsingFiltersRequest.Builder() 236 .addRecordType(record.getClass()) 237 .build()); 238 TestUtils.assertRecordNotFound(record.getMetadata().getId(), record.getClass()); 239 } 240 } 241 242 @Test testDeleteStepsCadenceRecord_dataOrigin_filters()243 public void testDeleteStepsCadenceRecord_dataOrigin_filters() throws InterruptedException { 244 Context context = ApplicationProvider.getApplicationContext(); 245 String id = TestUtils.insertRecordAndGetId(getCompleteStepsCadenceRecord()); 246 TestUtils.verifyDeleteRecords( 247 new DeleteUsingFiltersRequest.Builder() 248 .addDataOrigin( 249 new DataOrigin.Builder() 250 .setPackageName(context.getPackageName()) 251 .build()) 252 .build()); 253 TestUtils.assertRecordNotFound(id, StepsCadenceRecord.class); 254 } 255 256 @Test testDeleteStepsCadenceRecord_dataOrigin_filter_incorrect()257 public void testDeleteStepsCadenceRecord_dataOrigin_filter_incorrect() 258 throws InterruptedException { 259 String id = TestUtils.insertRecordAndGetId(getCompleteStepsCadenceRecord()); 260 TestUtils.verifyDeleteRecords( 261 new DeleteUsingFiltersRequest.Builder() 262 .addDataOrigin(new DataOrigin.Builder().setPackageName("abc").build()) 263 .build()); 264 TestUtils.assertRecordFound(id, StepsCadenceRecord.class); 265 } 266 267 @Test testDeleteStepsCadenceRecord_usingIds()268 public void testDeleteStepsCadenceRecord_usingIds() throws InterruptedException { 269 List<Record> records = 270 List.of(getBaseStepsCadenceRecord(), getCompleteStepsCadenceRecord()); 271 List<Record> insertedRecord = TestUtils.insertRecords(records); 272 List<RecordIdFilter> recordIds = new ArrayList<>(records.size()); 273 for (Record record : insertedRecord) { 274 recordIds.add(RecordIdFilter.fromId(record.getClass(), record.getMetadata().getId())); 275 } 276 277 TestUtils.verifyDeleteRecords(recordIds); 278 for (Record record : records) { 279 TestUtils.assertRecordNotFound(record.getMetadata().getId(), record.getClass()); 280 } 281 } 282 283 @Test testDeleteStepsCadenceRecord_time_range()284 public void testDeleteStepsCadenceRecord_time_range() throws InterruptedException { 285 TimeInstantRangeFilter timeRangeFilter = 286 new TimeInstantRangeFilter.Builder() 287 .setStartTime(Instant.now()) 288 .setEndTime(Instant.now().plusMillis(1000)) 289 .build(); 290 String id = TestUtils.insertRecordAndGetId(getCompleteStepsCadenceRecord()); 291 TestUtils.verifyDeleteRecords(StepsCadenceRecord.class, timeRangeFilter); 292 TestUtils.assertRecordNotFound(id, StepsCadenceRecord.class); 293 } 294 295 @Test testZoneOffsets()296 public void testZoneOffsets() { 297 final ZoneOffset defaultZoneOffset = 298 ZoneOffset.systemDefault().getRules().getOffset(Instant.now()); 299 final ZoneOffset startZoneOffset = ZoneOffset.UTC; 300 final ZoneOffset endZoneOffset = ZoneOffset.MAX; 301 StepsCadenceRecord.Builder builder = 302 new StepsCadenceRecord.Builder( 303 new Metadata.Builder().build(), 304 Instant.now(), 305 Instant.now().plusMillis(1000), 306 Collections.emptyList()); 307 308 assertThat(builder.setStartZoneOffset(startZoneOffset).build().getStartZoneOffset()) 309 .isEqualTo(startZoneOffset); 310 assertThat(builder.setEndZoneOffset(endZoneOffset).build().getEndZoneOffset()) 311 .isEqualTo(endZoneOffset); 312 assertThat(builder.clearStartZoneOffset().build().getStartZoneOffset()) 313 .isEqualTo(defaultZoneOffset); 314 assertThat(builder.clearEndZoneOffset().build().getEndZoneOffset()) 315 .isEqualTo(defaultZoneOffset); 316 } 317 318 @Test testUpdateRecords_validInput_dataBaseUpdatedSuccessfully()319 public void testUpdateRecords_validInput_dataBaseUpdatedSuccessfully() 320 throws InterruptedException { 321 322 List<Record> insertedRecords = 323 TestUtils.insertRecords( 324 Arrays.asList( 325 getCompleteStepsCadenceRecord(), getCompleteStepsCadenceRecord())); 326 327 // read inserted records and verify that the data is same as inserted. 328 readStepsCadenceRecordUsingIds(insertedRecords); 329 330 // Generate a new set of records that will be used to perform the update operation. 331 List<Record> updateRecords = 332 Arrays.asList(getCompleteStepsCadenceRecord(), getCompleteStepsCadenceRecord()); 333 334 // Modify the uid of the updateRecords to the uuid that was present in the insert records. 335 for (int itr = 0; itr < updateRecords.size(); itr++) { 336 updateRecords.set( 337 itr, 338 getStepsCadenceRecord_update( 339 updateRecords.get(itr), 340 insertedRecords.get(itr).getMetadata().getId(), 341 insertedRecords.get(itr).getMetadata().getClientRecordId())); 342 } 343 344 TestUtils.updateRecords(updateRecords); 345 346 // assert the inserted data has been modified by reading the data. 347 readStepsCadenceRecordUsingIds(updateRecords); 348 } 349 350 @Test testUpdateRecords_invalidInputRecords_noChangeInDataBase()351 public void testUpdateRecords_invalidInputRecords_noChangeInDataBase() 352 throws InterruptedException { 353 List<Record> insertedRecords = 354 TestUtils.insertRecords( 355 Arrays.asList( 356 getCompleteStepsCadenceRecord(), getCompleteStepsCadenceRecord())); 357 358 // read inserted records and verify that the data is same as inserted. 359 readStepsCadenceRecordUsingIds(insertedRecords); 360 361 // Generate a second set of records that will be used to perform the update operation. 362 List<Record> updateRecords = 363 Arrays.asList(getCompleteStepsCadenceRecord(), getCompleteStepsCadenceRecord()); 364 365 // Modify the Uid of the updateRecords to the UUID that was present in the insert records, 366 // leaving out alternate records so that they have a new UUID which is not present in the 367 // dataBase. 368 for (int itr = 0; itr < updateRecords.size(); itr++) { 369 updateRecords.set( 370 itr, 371 getStepsCadenceRecord_update( 372 updateRecords.get(itr), 373 itr % 2 == 0 374 ? insertedRecords.get(itr).getMetadata().getId() 375 : UUID.randomUUID().toString(), 376 itr % 2 == 0 377 ? insertedRecords.get(itr).getMetadata().getId() 378 : UUID.randomUUID().toString())); 379 } 380 381 try { 382 TestUtils.updateRecords(updateRecords); 383 Assert.fail("Expected to fail due to invalid records ids."); 384 } catch (HealthConnectException exception) { 385 assertThat(exception.getErrorCode()) 386 .isEqualTo(HealthConnectException.ERROR_INVALID_ARGUMENT); 387 } 388 389 // assert the inserted data has not been modified by reading the data. 390 readStepsCadenceRecordUsingIds(insertedRecords); 391 } 392 393 @Test testUpdateRecords_recordWithInvalidPackageName_noChangeInDataBase()394 public void testUpdateRecords_recordWithInvalidPackageName_noChangeInDataBase() 395 throws InterruptedException { 396 List<Record> insertedRecords = 397 TestUtils.insertRecords( 398 Arrays.asList( 399 getCompleteStepsCadenceRecord(), getCompleteStepsCadenceRecord())); 400 401 // read inserted records and verify that the data is same as inserted. 402 readStepsCadenceRecordUsingIds(insertedRecords); 403 404 // Generate a second set of records that will be used to perform the update operation. 405 List<Record> updateRecords = 406 Arrays.asList(getCompleteStepsCadenceRecord(), getCompleteStepsCadenceRecord()); 407 408 // Modify the Uuid of the updateRecords to the uuid that was present in the insert records. 409 for (int itr = 0; itr < updateRecords.size(); itr++) { 410 updateRecords.set( 411 itr, 412 getStepsCadenceRecord_update( 413 updateRecords.get(itr), 414 insertedRecords.get(itr).getMetadata().getId(), 415 insertedRecords.get(itr).getMetadata().getClientRecordId())); 416 // adding an entry with invalid packageName. 417 updateRecords.set(itr, getCompleteStepsCadenceRecord()); 418 } 419 420 try { 421 TestUtils.updateRecords(updateRecords); 422 Assert.fail("Expected to fail due to invalid package."); 423 } catch (Exception exception) { 424 // verify that the testcase failed due to invalid argument exception. 425 assertThat(exception).isNotNull(); 426 } 427 428 // assert the inserted data has not been modified by reading the data. 429 readStepsCadenceRecordUsingIds(insertedRecords); 430 } 431 432 @Test testInsertAndDeleteRecord_changelogs()433 public void testInsertAndDeleteRecord_changelogs() throws InterruptedException { 434 Context context = ApplicationProvider.getApplicationContext(); 435 ChangeLogTokenResponse tokenResponse = 436 TestUtils.getChangeLogToken( 437 new ChangeLogTokenRequest.Builder() 438 .addDataOriginFilter( 439 new DataOrigin.Builder() 440 .setPackageName(context.getPackageName()) 441 .build()) 442 .addRecordType(StepsCadenceRecord.class) 443 .build()); 444 ChangeLogsRequest changeLogsRequest = 445 new ChangeLogsRequest.Builder(tokenResponse.getToken()).build(); 446 ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest); 447 assertThat(response.getUpsertedRecords().size()).isEqualTo(0); 448 assertThat(response.getDeletedLogs().size()).isEqualTo(0); 449 450 List<Record> testRecord = Collections.singletonList(getCompleteStepsCadenceRecord()); 451 TestUtils.insertRecords(testRecord); 452 response = TestUtils.getChangeLogs(changeLogsRequest); 453 assertThat(response.getUpsertedRecords().size()).isEqualTo(1); 454 assertThat( 455 response.getUpsertedRecords().stream() 456 .map(Record::getMetadata) 457 .map(Metadata::getId) 458 .toList()) 459 .containsExactlyElementsIn( 460 testRecord.stream().map(Record::getMetadata).map(Metadata::getId).toList()); 461 assertThat(response.getDeletedLogs().size()).isEqualTo(0); 462 463 TestUtils.verifyDeleteRecords( 464 new DeleteUsingFiltersRequest.Builder() 465 .addRecordType(StepsCadenceRecord.class) 466 .build()); 467 response = TestUtils.getChangeLogs(changeLogsRequest); 468 assertThat(response.getDeletedLogs()).isEmpty(); 469 } 470 testReadStepsCadenceRecordIds()471 private void testReadStepsCadenceRecordIds() throws InterruptedException { 472 List<Record> recordList = 473 Arrays.asList(getCompleteStepsCadenceRecord(), getCompleteStepsCadenceRecord()); 474 readStepsCadenceRecordUsingIds(recordList); 475 } 476 readStepsCadenceRecordUsingClientId(List<Record> insertedRecord)477 private void readStepsCadenceRecordUsingClientId(List<Record> insertedRecord) 478 throws InterruptedException { 479 ReadRecordsRequestUsingIds.Builder<StepsCadenceRecord> request = 480 new ReadRecordsRequestUsingIds.Builder<>(StepsCadenceRecord.class); 481 for (Record record : insertedRecord) { 482 request.addClientRecordId(record.getMetadata().getClientRecordId()); 483 } 484 List<StepsCadenceRecord> result = TestUtils.readRecords(request.build()); 485 assertThat(result.size()).isEqualTo(insertedRecord.size()); 486 assertThat(result).containsExactlyElementsIn(insertedRecord); 487 } 488 readStepsCadenceRecordUsingIds(List<Record> recordList)489 private void readStepsCadenceRecordUsingIds(List<Record> recordList) 490 throws InterruptedException { 491 List<Record> insertedRecords = TestUtils.insertRecords(recordList); 492 ReadRecordsRequestUsingIds.Builder<StepsCadenceRecord> request = 493 new ReadRecordsRequestUsingIds.Builder<>(StepsCadenceRecord.class); 494 for (Record record : insertedRecords) { 495 request.addId(record.getMetadata().getId()); 496 } 497 ReadRecordsRequestUsingIds requestUsingIds = request.build(); 498 assertThat(requestUsingIds.getRecordType()).isEqualTo(StepsCadenceRecord.class); 499 assertThat(requestUsingIds.getRecordIdFilters()).isNotNull(); 500 List<StepsCadenceRecord> result = TestUtils.readRecords(requestUsingIds); 501 assertThat(result).hasSize(insertedRecords.size()); 502 assertThat(result.containsAll(insertedRecords)).isTrue(); 503 } 504 505 @Test(expected = IllegalArgumentException.class) testCreateStepsCadenceRecord_invalidValue()506 public void testCreateStepsCadenceRecord_invalidValue() { 507 new StepsCadenceRecord.StepsCadenceRecordSample(10001.0, Instant.now().plusMillis(100)); 508 } 509 510 @Test testInsertWithClientVersion()511 public void testInsertWithClientVersion() throws InterruptedException { 512 List<Record> records = List.of(getStepsCadenceRecordWithClientVersion(10, 1, "testId")); 513 final String id = TestUtils.insertRecords(records).get(0).getMetadata().getId(); 514 ReadRecordsRequestUsingIds<StepsCadenceRecord> request = 515 new ReadRecordsRequestUsingIds.Builder<>(StepsCadenceRecord.class) 516 .addClientRecordId("testId") 517 .build(); 518 StepsCadenceRecord stepsRecord = TestUtils.readRecords(request).get(0); 519 int sampleSize = ((StepsCadenceRecord) records.get(0)).getSamples().size(); 520 assertThat(stepsRecord.getSamples()).hasSize(sampleSize); 521 assertThat(stepsRecord.getSamples().get(0).getRate()).isEqualTo(10); 522 523 records = List.of(getStepsCadenceRecordWithClientVersion(20, 2, "testId")); 524 TestUtils.insertRecords(records); 525 526 stepsRecord = TestUtils.readRecords(request).get(0); 527 assertThat(stepsRecord.getMetadata().getId()).isEqualTo(id); 528 assertThat(stepsRecord.getSamples()).hasSize(sampleSize); 529 assertThat(stepsRecord.getSamples().get(0).getRate()).isEqualTo(20); 530 531 records = List.of(getStepsCadenceRecordWithClientVersion(30, 1, "testId")); 532 TestUtils.insertRecords(records); 533 stepsRecord = TestUtils.readRecords(request).get(0); 534 assertThat(stepsRecord.getMetadata().getId()).isEqualTo(id); 535 assertThat(stepsRecord.getSamples()).hasSize(sampleSize); 536 assertThat(stepsRecord.getSamples().get(0).getRate()).isEqualTo(20); 537 } 538 getStepsCadenceRecord_update( Record record, String id, String clientRecordId)539 StepsCadenceRecord getStepsCadenceRecord_update( 540 Record record, String id, String clientRecordId) { 541 Metadata metadata = record.getMetadata(); 542 Metadata metadataWithId = 543 new Metadata.Builder() 544 .setId(id) 545 .setClientRecordId(clientRecordId) 546 .setClientRecordVersion(metadata.getClientRecordVersion()) 547 .setDataOrigin(metadata.getDataOrigin()) 548 .setDevice(metadata.getDevice()) 549 .setLastModifiedTime(metadata.getLastModifiedTime()) 550 .build(); 551 552 StepsCadenceRecord.StepsCadenceRecordSample stepsCadenceRecordSample = 553 new StepsCadenceRecord.StepsCadenceRecordSample(8.0, Instant.now().plusMillis(100)); 554 555 return new StepsCadenceRecord.Builder( 556 metadataWithId, 557 Instant.now(), 558 Instant.now().plusMillis(2000), 559 List.of(stepsCadenceRecordSample, stepsCadenceRecordSample)) 560 .setStartZoneOffset(ZoneOffset.systemDefault().getRules().getOffset(Instant.now())) 561 .setEndZoneOffset(ZoneOffset.systemDefault().getRules().getOffset(Instant.now())) 562 .build(); 563 } 564 getStepsCadenceRecordWithClientVersion( int rate, int version, String clientRecordId)565 static StepsCadenceRecord getStepsCadenceRecordWithClientVersion( 566 int rate, int version, String clientRecordId) { 567 Metadata.Builder testMetadataBuilder = new Metadata.Builder(); 568 testMetadataBuilder.setClientRecordId(clientRecordId); 569 testMetadataBuilder.setClientRecordVersion(version); 570 Metadata testMetaData = testMetadataBuilder.build(); 571 StepsCadenceRecord.StepsCadenceRecordSample stepsCadenceRecord = 572 new StepsCadenceRecord.StepsCadenceRecordSample( 573 rate, Instant.now().plusMillis(100)); 574 ArrayList<StepsCadenceRecord.StepsCadenceRecordSample> stepsCadenceRecords = 575 new ArrayList<>(); 576 stepsCadenceRecords.add(stepsCadenceRecord); 577 stepsCadenceRecords.add(stepsCadenceRecord); 578 579 return new StepsCadenceRecord.Builder( 580 testMetaData, 581 Instant.now(), 582 Instant.now().plusMillis(1000), 583 stepsCadenceRecords) 584 .build(); 585 } 586 getBaseStepsCadenceRecord()587 private static StepsCadenceRecord getBaseStepsCadenceRecord() { 588 StepsCadenceRecord.StepsCadenceRecordSample stepsCadenceRecord = 589 new StepsCadenceRecord.StepsCadenceRecordSample(1, Instant.now().plusMillis(100)); 590 ArrayList<StepsCadenceRecord.StepsCadenceRecordSample> stepsCadenceRecords = 591 new ArrayList<>(); 592 stepsCadenceRecords.add(stepsCadenceRecord); 593 stepsCadenceRecords.add(stepsCadenceRecord); 594 595 return new StepsCadenceRecord.Builder( 596 new Metadata.Builder().build(), 597 Instant.now(), 598 Instant.now().plusMillis(1000), 599 stepsCadenceRecords) 600 .build(); 601 } 602 getCompleteStepsCadenceRecord()603 private static StepsCadenceRecord getCompleteStepsCadenceRecord() { 604 Device device = 605 new Device.Builder() 606 .setManufacturer("google") 607 .setModel("Pixel4a") 608 .setType(2) 609 .build(); 610 DataOrigin dataOrigin = 611 new DataOrigin.Builder().setPackageName("android.healthconnect.cts").build(); 612 Metadata.Builder testMetadataBuilder = new Metadata.Builder(); 613 testMetadataBuilder.setDevice(device).setDataOrigin(dataOrigin); 614 testMetadataBuilder.setClientRecordId("SCR" + Math.random()); 615 testMetadataBuilder.setRecordingMethod(Metadata.RECORDING_METHOD_ACTIVELY_RECORDED); 616 StepsCadenceRecord.StepsCadenceRecordSample stepsCadenceRecord = 617 new StepsCadenceRecord.StepsCadenceRecordSample(1, Instant.now().plusMillis(100)); 618 ArrayList<StepsCadenceRecord.StepsCadenceRecordSample> stepsCadenceRecords = 619 new ArrayList<>(); 620 stepsCadenceRecords.add(stepsCadenceRecord); 621 stepsCadenceRecords.add(stepsCadenceRecord); 622 623 return new StepsCadenceRecord.Builder( 624 testMetadataBuilder.build(), 625 Instant.now(), 626 Instant.now().plusMillis(1000), 627 stepsCadenceRecords) 628 .build(); 629 } 630 } 631