blob: dc7f410a71f2259847f0ac3a56bc5a5ca36da311 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.healthconnect.cts;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.health.connect.DeleteUsingFiltersRequest;
import android.health.connect.changelog.ChangeLogTokenRequest;
import android.health.connect.changelog.ChangeLogTokenResponse;
import android.health.connect.changelog.ChangeLogsRequest;
import android.health.connect.changelog.ChangeLogsResponse;
import android.health.connect.datatypes.DataOrigin;
import android.health.connect.datatypes.Record;
import android.health.connect.datatypes.StepsRecord;
import android.healthconnect.cts.utils.TestUtils;
import android.platform.test.annotations.AppModeFull;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/** CTS test for API provided by HealthConnectManager. */
@AppModeFull(reason = "HealthConnectManager is not accessible to instant apps")
@RunWith(AndroidJUnit4.class)
public class HealthConnectChangeLogsTests {
@After
public void tearDown() throws InterruptedException {
Context context = ApplicationProvider.getApplicationContext();
String packageName = context.getPackageName();
TestUtils.verifyDeleteRecords(
new DeleteUsingFiltersRequest.Builder()
.addDataOrigin(new DataOrigin.Builder().setPackageName(packageName).build())
.build());
TestUtils.deleteAllStagedRemoteData();
}
@Before
public void setUp() {
// TODO(b/283737434): Update the HC code to use user aware context on permission change.
// Temporary fix to set firstGrantTime for the correct user in HSUM.
TestUtils.deleteAllStagedRemoteData();
}
@Test
public void testGetChangeLogToken() throws InterruptedException {
ChangeLogTokenRequest changeLogTokenRequest = new ChangeLogTokenRequest.Builder().build();
assertThat(TestUtils.getChangeLogToken(changeLogTokenRequest)).isNotNull();
assertThat(changeLogTokenRequest.getRecordTypes()).isNotNull();
assertThat(changeLogTokenRequest.getDataOriginFilters()).isNotNull();
}
@Test
public void testChangeLogs_insert_default() throws InterruptedException {
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(new ChangeLogTokenRequest.Builder().build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
assertThat(changeLogsRequest.getToken()).isNotNull();
assertThat(changeLogsRequest.getPageSize()).isNotNull();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
List<Record> testRecord = TestUtils.insertRecords(TestUtils.getTestRecords());
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(testRecord.size());
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
}
@Test
public void testChangeLogs_insert_dataOrigin_filter_incorrect() throws InterruptedException {
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(
new ChangeLogTokenRequest.Builder()
.addDataOriginFilter(
new DataOrigin.Builder().setPackageName("random").build())
.build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
assertThat(changeLogsRequest.getPageSize()).isNotNull();
assertThat(changeLogsRequest.getToken()).isNotNull();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
TestUtils.insertRecords(TestUtils.getTestRecords());
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
}
@Test
public void testChangeLogs_insert_dataOrigin_filter_correct() throws InterruptedException {
Context context = ApplicationProvider.getApplicationContext();
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(
new ChangeLogTokenRequest.Builder()
.addDataOriginFilter(
new DataOrigin.Builder()
.setPackageName(context.getPackageName())
.build())
.build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
assertThat(changeLogsRequest.getPageSize()).isNotNull();
assertThat(changeLogsRequest.getToken()).isNotNull();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
List<Record> testRecord = TestUtils.insertRecords(TestUtils.getTestRecords());
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(testRecord.size());
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
}
@Test
public void testChangeLogs_insert_record_filter() throws InterruptedException {
Context context = ApplicationProvider.getApplicationContext();
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(
new ChangeLogTokenRequest.Builder()
.addDataOriginFilter(
new DataOrigin.Builder()
.setPackageName(context.getPackageName())
.build())
.addRecordType(StepsRecord.class)
.build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
List<Record> testRecord =
TestUtils.insertRecords(Collections.singletonList(TestUtils.getStepsRecord()));
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(1);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
testRecord =
TestUtils.insertRecords(Collections.singletonList(TestUtils.getHeartRateRecord()));
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(1);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
}
@Test
public void testChangeLogs_insertAndDelete_default() throws InterruptedException {
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(new ChangeLogTokenRequest.Builder().build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
List<Record> testRecord = TestUtils.insertRecords(TestUtils.getTestRecords());
TestUtils.deleteRecords(testRecord);
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(testRecord.size());
List<ChangeLogsResponse.DeletedLog> deletedLogs = response.getDeletedLogs();
ChangeLogsResponse.DeletedLog deletedLog =
new ChangeLogsResponse.DeletedLog("abc", Instant.now().toEpochMilli());
assertThat(deletedLogs).doesNotContain(deletedLog);
for (ChangeLogsResponse.DeletedLog log : deletedLogs) {
assertThat(log.getDeletedRecordId()).isNotNull();
assertThat(log.getDeletedTime()).isNotNull();
assertThat(log.getDeletedRecordId()).isNotEqualTo(deletedLog.getDeletedRecordId());
}
}
@Test
public void testChangeLogs_insertAndDelete_beforePermission() throws InterruptedException {
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(new ChangeLogTokenRequest.Builder().build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
List<Record> testRecord =
TestUtils.insertRecords(
Arrays.asList(
StepsRecordTest.getStepsRecord_minusDays(45),
StepsRecordTest.getStepsRecord_minusDays(20),
StepsRecordTest.getStepsRecord_minusDays(5)));
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(2);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
TestUtils.deleteRecords(testRecord);
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(3);
}
@Test
public void testChangeLogs_insertAndDelete_dataOrigin_filter_incorrect()
throws InterruptedException {
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(
new ChangeLogTokenRequest.Builder()
.addDataOriginFilter(
new DataOrigin.Builder().setPackageName("random").build())
.build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
assertThat(changeLogsRequest.getPageSize()).isNotNull();
assertThat(changeLogsRequest.getToken()).isNotNull();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
List<Record> testRecord = TestUtils.insertRecords(TestUtils.getTestRecords());
TestUtils.deleteRecords(testRecord);
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
}
@Test
public void testChangeLogs_insertAndDelete_dataOrigin_filter_correct()
throws InterruptedException {
Context context = ApplicationProvider.getApplicationContext();
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(
new ChangeLogTokenRequest.Builder()
.addDataOriginFilter(
new DataOrigin.Builder()
.setPackageName(context.getPackageName())
.build())
.build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
assertThat(changeLogsRequest.getPageSize()).isNotNull();
assertThat(changeLogsRequest.getToken()).isNotNull();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
List<Record> testRecord = TestUtils.insertRecords(TestUtils.getTestRecords());
TestUtils.deleteRecords(testRecord);
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(testRecord.size());
}
@Test
public void testChangeLogs_insertAndDelete_record_filter() throws InterruptedException {
Context context = ApplicationProvider.getApplicationContext();
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(
new ChangeLogTokenRequest.Builder()
.addDataOriginFilter(
new DataOrigin.Builder()
.setPackageName(context.getPackageName())
.build())
.addRecordType(StepsRecord.class)
.build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
assertThat(changeLogsRequest.getPageSize()).isNotNull();
assertThat(changeLogsRequest.getToken()).isNotNull();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(0);
List<Record> testRecord =
TestUtils.insertRecords(Collections.singletonList(TestUtils.getStepsRecord()));
TestUtils.deleteRecords(testRecord);
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(1);
testRecord =
TestUtils.insertRecords(Collections.singletonList(TestUtils.getHeartRateRecord()));
TestUtils.deleteRecords(testRecord);
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.getDeletedLogs().size()).isEqualTo(1);
}
@Test
public void testChangeLogs_insert_default_withPageSize() throws InterruptedException {
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(new ChangeLogTokenRequest.Builder().build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).setPageSize(1).build();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
List<Record> testRecord = TestUtils.getTestRecords();
TestUtils.insertRecords(testRecord);
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(1);
}
@Test
public void testChangeLogs_insert_default_withNextPageToken() throws InterruptedException {
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(new ChangeLogTokenRequest.Builder().build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).setPageSize(1).build();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.hasMorePages()).isFalse();
List<Record> testRecord = TestUtils.getTestRecords();
TestUtils.insertRecords(testRecord);
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.hasMorePages()).isTrue();
assertThat(response.getUpsertedRecords().size()).isEqualTo(1);
ChangeLogsRequest nextChangeLogsRequest =
new ChangeLogsRequest.Builder(response.getNextChangesToken())
.setPageSize(1)
.build();
ChangeLogsResponse nextResponse = TestUtils.getChangeLogs(nextChangeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(1);
assertThat(nextResponse.hasMorePages()).isTrue();
assertThat(nextResponse.getNextChangesToken())
.isGreaterThan(response.getNextChangesToken());
nextChangeLogsRequest =
new ChangeLogsRequest.Builder(nextResponse.getNextChangesToken()).build();
nextResponse = TestUtils.getChangeLogs(nextChangeLogsRequest);
assertThat(nextResponse.hasMorePages()).isFalse();
}
@Test
public void testChangeLogs_insert_default_withSamePageToken() throws InterruptedException {
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(new ChangeLogTokenRequest.Builder().build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.hasMorePages()).isFalse();
List<Record> testRecord = TestUtils.insertRecords(TestUtils.getTestRecords());
ChangeLogsResponse newResponse = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(newResponse.getUpsertedRecords().size()).isEqualTo(testRecord.size());
}
// Test added for b/271607816 to make sure that getChangeLogs() method returns the requested
// changelog token as nextPageToken in the response when it is the end of page.
// ( i.e. hasMoreRecords is false)
@Test
public void testChangeLogs_checkToken_hasMorePages_False() throws InterruptedException {
ChangeLogTokenResponse tokenResponse =
TestUtils.getChangeLogToken(new ChangeLogTokenRequest.Builder().build());
ChangeLogsRequest changeLogsRequest =
new ChangeLogsRequest.Builder(tokenResponse.getToken()).build();
ChangeLogsResponse response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(0);
assertThat(response.hasMorePages()).isFalse();
List<Record> testRecord = TestUtils.insertRecords(TestUtils.getTestRecords());
response = TestUtils.getChangeLogs(changeLogsRequest);
assertThat(response.getUpsertedRecords().size()).isEqualTo(testRecord.size());
assertThat(response.hasMorePages()).isFalse();
ChangeLogsRequest changeLogsRequestNew =
new ChangeLogsRequest.Builder(response.getNextChangesToken())
.setPageSize(2)
.build();
ChangeLogsResponse newResponse = TestUtils.getChangeLogs(changeLogsRequestNew);
assertThat(newResponse.getUpsertedRecords().size()).isEqualTo(0);
assertThat(newResponse.hasMorePages()).isFalse();
assertThat(newResponse.getNextChangesToken()).isEqualTo(changeLogsRequestNew.getToken());
}
}