1 /* 2 * Copyright (C) 2021 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 package com.android.systemui.flags 17 18 import android.content.pm.PackageManager.NameNotFoundException 19 import android.content.res.Resources 20 import android.test.suitebuilder.annotation.SmallTest 21 import com.android.systemui.SysuiTestCase 22 import com.google.common.truth.Truth.assertThat 23 import org.junit.Assert.assertThrows 24 import org.junit.Before 25 import org.junit.Test 26 import org.mockito.Mock 27 import org.mockito.Mockito 28 import org.mockito.Mockito.never 29 import org.mockito.MockitoAnnotations 30 import org.mockito.Mockito.`when` as whenever 31 32 /** 33 * NOTE: This test is for the version of FeatureFlagManager in src-release, which should not allow 34 * overriding, and should never return any value other than the one provided as the default. 35 */ 36 @SmallTest 37 class FeatureFlagsReleaseTest : SysuiTestCase() { 38 private lateinit var featureFlagsRelease: FeatureFlagsRelease 39 40 @Mock private lateinit var mResources: Resources 41 @Mock private lateinit var mSystemProperties: SystemPropertiesHelper 42 @Mock private lateinit var restarter: Restarter 43 private val flagMap = mutableMapOf<String, Flag<*>>() 44 private val serverFlagReader = ServerFlagReaderFake() 45 46 47 private val flagA = ReleasedFlag(name = "a", namespace = "test") 48 49 @Before 50 fun setup() { 51 MockitoAnnotations.initMocks(this) 52 flagMap.put(flagA.name, flagA) 53 featureFlagsRelease = FeatureFlagsRelease( 54 mResources, 55 mSystemProperties, 56 serverFlagReader, 57 flagMap, 58 restarter) 59 60 featureFlagsRelease.init() 61 } 62 63 @Test 64 fun testBooleanResourceFlag() { 65 val flagResourceId = 3 66 val flagName = "213" 67 val flagNamespace = "test" 68 val flag = ResourceBooleanFlag(flagName, flagNamespace, flagResourceId) 69 whenever(mResources.getBoolean(flagResourceId)).thenReturn(true) 70 assertThat(featureFlagsRelease.isEnabled(flag)).isTrue() 71 } 72 73 @Test 74 fun testReadResourceStringFlag() { 75 whenever(mResources.getString(1001)).thenReturn("") 76 whenever(mResources.getString(1002)).thenReturn("res2") 77 whenever(mResources.getString(1003)).thenReturn(null) 78 whenever(mResources.getString(1004)).thenAnswer { throw NameNotFoundException() } 79 80 assertThat(featureFlagsRelease.getString( 81 ResourceStringFlag("1", "test", 1001))).isEqualTo("") 82 assertThat(featureFlagsRelease.getString( 83 ResourceStringFlag("2", "test", 1002))).isEqualTo("res2") 84 85 assertThrows(NullPointerException::class.java) { 86 featureFlagsRelease.getString(ResourceStringFlag("3", "test", 1003)) 87 } 88 assertThrows(NameNotFoundException::class.java) { 89 featureFlagsRelease.getString(ResourceStringFlag("4", "test", 1004)) 90 } 91 } 92 93 @Test 94 fun testSysPropBooleanFlag() { 95 val flagName = "sys_prop_flag" 96 val flagNamespace = "test" 97 val flagDefault = true 98 99 val flag = SysPropBooleanFlag(flagName, flagNamespace, flagDefault) 100 whenever(mSystemProperties.getBoolean(flagName, flagDefault)).thenReturn(flagDefault) 101 assertThat(featureFlagsRelease.isEnabled(flag)).isEqualTo(flagDefault) 102 } 103 104 @Test 105 fun serverSide_OverridesReleased_MakesFalse() { 106 val flag = ReleasedFlag("100", "test") 107 108 serverFlagReader.setFlagValue(flag.namespace, flag.name, false) 109 110 assertThat(featureFlagsRelease.isEnabled(flag)).isFalse() 111 } 112 113 @Test 114 fun serverSide_OverridesUnreleased_Ignored() { 115 val flag = UnreleasedFlag("100", "test") 116 117 serverFlagReader.setFlagValue(flag.namespace, flag.name, true) 118 119 assertThat(featureFlagsRelease.isEnabled(flag)).isFalse() 120 } 121 122 @Test 123 fun serverSide_OverrideUncached_NoRestart() { 124 // No one has read the flag, so it's not in the cache. 125 serverFlagReader.setFlagValue( 126 flagA.namespace, flagA.name, !flagA.default) 127 Mockito.verify(restarter, never()).restartSystemUI(Mockito.anyString()) 128 } 129 130 @Test 131 fun serverSide_Override_Restarts() { 132 // Read it to put it in the cache. 133 featureFlagsRelease.isEnabled(flagA) 134 serverFlagReader.setFlagValue( 135 flagA.namespace, flagA.name, !flagA.default) 136 Mockito.verify(restarter).restartSystemUI(Mockito.anyString()) 137 } 138 139 @Test 140 fun serverSide_RedundantOverride_NoRestart() { 141 // Read it to put it in the cache. 142 featureFlagsRelease.isEnabled(flagA) 143 serverFlagReader.setFlagValue( 144 flagA.namespace, flagA.name, flagA.default) 145 Mockito.verify(restarter, never()).restartSystemUI(Mockito.anyString()) 146 } 147 } 148