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