| /* |
| * Copyright (C) 2017 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 com.android.server.timezone; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import android.content.Context; |
| import android.database.sqlite.SQLiteDatabase; |
| import android.support.test.InstrumentationRegistry; |
| import android.support.test.filters.SmallTest; |
| |
| import static junit.framework.Assert.assertTrue; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| |
| @SmallTest |
| public class PackageStatusStorageTest { |
| private static final PackageVersions VALID_PACKAGE_VERSIONS = new PackageVersions(1, 2); |
| |
| private PackageStatusStorage mPackageStatusStorage; |
| |
| @Before |
| public void setUp() throws Exception { |
| Context context = InstrumentationRegistry.getContext(); |
| |
| // Using the instrumentation context means the database is created in a test app-specific |
| // directory. |
| mPackageStatusStorage = new PackageStatusStorage(context); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| mPackageStatusStorage.deleteDatabaseForTests(); |
| } |
| |
| @Test |
| public void getPackageStatus_initialState() { |
| assertNull(mPackageStatusStorage.getPackageStatus()); |
| } |
| |
| @Test |
| public void resetCheckState() { |
| // Assert initial state. |
| assertNull(mPackageStatusStorage.getPackageStatus()); |
| |
| CheckToken token1 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS); |
| |
| // There should now be a state. |
| assertNotNull(mPackageStatusStorage.getPackageStatus()); |
| |
| // Now clear the state. |
| mPackageStatusStorage.resetCheckState(); |
| |
| // After reset, there should be no package state again. |
| assertNull(mPackageStatusStorage.getPackageStatus()); |
| |
| CheckToken token2 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS); |
| |
| // Token after a reset should still be distinct. |
| assertFalse(token1.equals(token2)); |
| |
| // Now clear the state again. |
| mPackageStatusStorage.resetCheckState(); |
| |
| // After reset, there should be no package state again. |
| assertNull(mPackageStatusStorage.getPackageStatus()); |
| |
| CheckToken token3 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS); |
| |
| // A CheckToken generated after a reset should still be distinct. |
| assertFalse(token2.equals(token3)); |
| } |
| |
| @Test |
| public void generateCheckToken_missingRowBehavior() { |
| // Assert initial state. |
| assertNull(mPackageStatusStorage.getPackageStatus()); |
| |
| CheckToken token1 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS); |
| assertNotNull(token1); |
| |
| // There should now be state. |
| assertNotNull(mPackageStatusStorage.getPackageStatus()); |
| |
| // Corrupt the table by removing the one row. |
| mPackageStatusStorage.deleteRowForTests(); |
| |
| // Check that generateCheckToken recovers. |
| assertNotNull(mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS)); |
| } |
| |
| @Test |
| public void getPackageStatus_missingRowBehavior() { |
| // Assert initial state. |
| assertNull(mPackageStatusStorage.getPackageStatus()); |
| |
| CheckToken token1 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS); |
| assertNotNull(token1); |
| |
| // There should now be a state. |
| assertNotNull(mPackageStatusStorage.getPackageStatus()); |
| |
| // Corrupt the table by removing the one row. |
| mPackageStatusStorage.deleteRowForTests(); |
| |
| assertNull(mPackageStatusStorage.getPackageStatus()); |
| } |
| |
| @Test |
| public void markChecked_missingRowBehavior() { |
| // Assert initial state. |
| CheckToken token1 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS); |
| assertNotNull(token1); |
| |
| // There should now be a state. |
| assertNotNull(mPackageStatusStorage.getPackageStatus()); |
| |
| // Corrupt the table by removing the one row. |
| mPackageStatusStorage.deleteRowForTests(); |
| |
| // The missing row should mean token1 is now considered invalid, so we should get a false. |
| assertFalse(mPackageStatusStorage.markChecked(token1, true /* succeeded */)); |
| |
| // The storage should have recovered and we should be able to carry on like before. |
| CheckToken token2 = mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS); |
| assertTrue(mPackageStatusStorage.markChecked(token2, true /* succeeded */)); |
| } |
| |
| @Test |
| public void checkToken_tokenIsUnique() { |
| PackageVersions packageVersions = VALID_PACKAGE_VERSIONS; |
| PackageStatus expectedPackageStatus = |
| new PackageStatus(PackageStatus.CHECK_STARTED, packageVersions); |
| |
| CheckToken token1 = mPackageStatusStorage.generateCheckToken(packageVersions); |
| assertEquals(packageVersions, token1.mPackageVersions); |
| |
| PackageStatus actualPackageStatus1 = mPackageStatusStorage.getPackageStatus(); |
| assertEquals(expectedPackageStatus, actualPackageStatus1); |
| |
| CheckToken token2 = mPackageStatusStorage.generateCheckToken(packageVersions); |
| assertEquals(packageVersions, token1.mPackageVersions); |
| assertFalse(token1.mOptimisticLockId == token2.mOptimisticLockId); |
| assertFalse(token1.equals(token2)); |
| } |
| |
| @Test |
| public void markChecked_checkSucceeded() { |
| PackageVersions packageVersions = VALID_PACKAGE_VERSIONS; |
| |
| CheckToken token = mPackageStatusStorage.generateCheckToken(packageVersions); |
| boolean writeOk = mPackageStatusStorage.markChecked(token, true /* succeeded */); |
| assertTrue(writeOk); |
| |
| PackageStatus expectedPackageStatus = |
| new PackageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions); |
| assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus()); |
| } |
| |
| @Test |
| public void markChecked_checkFailed() { |
| PackageVersions packageVersions = VALID_PACKAGE_VERSIONS; |
| |
| CheckToken token = mPackageStatusStorage.generateCheckToken(packageVersions); |
| boolean writeOk = mPackageStatusStorage.markChecked(token, false /* succeeded */); |
| assertTrue(writeOk); |
| |
| PackageStatus expectedPackageStatus = |
| new PackageStatus(PackageStatus.CHECK_COMPLETED_FAILURE, packageVersions); |
| assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus()); |
| } |
| |
| @Test |
| public void markChecked_optimisticLocking_multipleToken() { |
| PackageVersions packageVersions = VALID_PACKAGE_VERSIONS; |
| CheckToken token1 = mPackageStatusStorage.generateCheckToken(packageVersions); |
| CheckToken token2 = mPackageStatusStorage.generateCheckToken(packageVersions); |
| |
| PackageStatus packageStatusBeforeChecked = mPackageStatusStorage.getPackageStatus(); |
| |
| boolean writeOk1 = mPackageStatusStorage.markChecked(token1, true /* succeeded */); |
| // Generation of token2 should mean that token1 is no longer valid. |
| assertFalse(writeOk1); |
| assertEquals(packageStatusBeforeChecked, mPackageStatusStorage.getPackageStatus()); |
| |
| boolean writeOk2 = mPackageStatusStorage.markChecked(token2, true /* succeeded */); |
| // token2 should still be valid, and the attempt with token1 should have had no effect. |
| assertTrue(writeOk2); |
| PackageStatus expectedPackageStatus = |
| new PackageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions); |
| assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus()); |
| } |
| |
| @Test |
| public void markChecked_optimisticLocking_repeatedTokenUse() { |
| PackageVersions packageVersions = VALID_PACKAGE_VERSIONS; |
| CheckToken token = mPackageStatusStorage.generateCheckToken(packageVersions); |
| |
| boolean writeOk1 = mPackageStatusStorage.markChecked(token, true /* succeeded */); |
| assertTrue(writeOk1); |
| |
| PackageStatus expectedPackageStatus = |
| new PackageStatus(PackageStatus.CHECK_COMPLETED_SUCCESS, packageVersions); |
| assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus()); |
| |
| // token cannot be reused. |
| boolean writeOk2 = mPackageStatusStorage.markChecked(token, true /* succeeded */); |
| assertFalse(writeOk2); |
| assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus()); |
| } |
| } |