1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
4 import static android.os.Build.VERSION_CODES.KITKAT;
5 import static android.os.Build.VERSION_CODES.LOLLIPOP;
6 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
7 import static android.os.Build.VERSION_CODES.M;
8 import static com.google.common.truth.Truth.assertThat;
9 import static org.junit.Assert.assertNotNull;
10 import static org.junit.Assert.assertNull;
11 
12 import android.os.Environment;
13 import androidx.test.core.app.ApplicationProvider;
14 import androidx.test.ext.junit.runners.AndroidJUnit4;
15 import java.io.File;
16 import org.junit.After;
17 import org.junit.Ignore;
18 import org.junit.Test;
19 import org.junit.runner.RunWith;
20 import org.robolectric.annotation.Config;
21 
22 @RunWith(AndroidJUnit4.class)
23 public class ShadowEnvironmentTest {
24 
25   @After
tearDown()26   public void tearDown() throws Exception {
27     ShadowEnvironment.setExternalStorageState(Environment.MEDIA_REMOVED);
28   }
29 
30   @Test
getExternalStorageState_shouldReturnStorageState()31   public void getExternalStorageState_shouldReturnStorageState() {
32     assertThat(Environment.getExternalStorageState()).isEqualTo(Environment.MEDIA_REMOVED);
33     ShadowEnvironment.setExternalStorageState(Environment.MEDIA_MOUNTED);
34     assertThat(Environment.getExternalStorageState()).isEqualTo(Environment.MEDIA_MOUNTED);
35   }
36 
37   @Test
getExternalStorageDirectory_shouldReturnDirectory()38   public void getExternalStorageDirectory_shouldReturnDirectory() {
39     assertThat(Environment.getExternalStorageDirectory().exists()).isTrue();
40   }
41 
42   @Test
getExternalStoragePublicDirectory_shouldReturnDirectory()43   public void getExternalStoragePublicDirectory_shouldReturnDirectory() {
44     final File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
45     assertThat(path.exists()).isTrue();
46     assertThat(path).isEqualTo(new File(ShadowEnvironment.EXTERNAL_FILES_DIR.toFile(), Environment.DIRECTORY_MOVIES));
47   }
48 
49   @Test
getExternalStoragePublicDirectory_shouldReturnSameDirectory()50   public void getExternalStoragePublicDirectory_shouldReturnSameDirectory() {
51     File path1 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
52     File path2 = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
53 
54     assertThat(path1).isEqualTo(path2);
55   }
56 
57   @Test
58   @Config(minSdk = M)
isExternalStorageRemovable_primaryShouldReturnSavedValue()59   public void isExternalStorageRemovable_primaryShouldReturnSavedValue() {
60     assertThat(Environment.isExternalStorageRemovable()).isFalse();
61     ShadowEnvironment.setExternalStorageRemovable(Environment.getExternalStorageDirectory(), true);
62     assertThat(Environment.isExternalStorageRemovable()).isTrue();
63   }
64 
65   @Test
66   @Config(minSdk = LOLLIPOP)
isExternalStorageRemovable_shouldReturnSavedValue()67   public void isExternalStorageRemovable_shouldReturnSavedValue() {
68     final File file = new File("/mnt/media/file");
69     assertThat(Environment.isExternalStorageRemovable(file)).isFalse();
70     ShadowEnvironment.setExternalStorageRemovable(file, true);
71     assertThat(Environment.isExternalStorageRemovable(file)).isTrue();
72   }
73 
74   @Test
75   @Config(minSdk = LOLLIPOP)
isExternalStorageEmulated_shouldReturnSavedValue()76   public void isExternalStorageEmulated_shouldReturnSavedValue() {
77     final File file = new File("/mnt/media/file");
78     assertThat(Environment.isExternalStorageEmulated(file)).isFalse();
79     ShadowEnvironment.setExternalStorageEmulated(file, true);
80     assertThat(Environment.isExternalStorageEmulated(file)).isTrue();
81   }
82 
83   @Test
84   @Config(minSdk = LOLLIPOP)
storageIsLazy()85   public void storageIsLazy() {
86     assertNull(ShadowEnvironment.EXTERNAL_CACHE_DIR);
87     assertNull(ShadowEnvironment.EXTERNAL_FILES_DIR);
88 
89     Environment.getExternalStorageDirectory();
90     Environment.getExternalStoragePublicDirectory(null);
91 
92     assertNotNull(ShadowEnvironment.EXTERNAL_CACHE_DIR);
93     assertNotNull(ShadowEnvironment.EXTERNAL_FILES_DIR);
94   }
95 
96   @Test
97   @Config(minSdk = LOLLIPOP)
reset_shouldClearRemovableFiles()98   public void reset_shouldClearRemovableFiles() {
99     final File file = new File("foo");
100     ShadowEnvironment.setExternalStorageRemovable(file, true);
101 
102     assertThat(Environment.isExternalStorageRemovable(file)).isTrue();
103     ShadowEnvironment.reset();
104     assertThat(Environment.isExternalStorageRemovable(file)).isFalse();
105   }
106 
107   @Test
108   @Config(minSdk = LOLLIPOP)
reset_shouldClearEmulatedFiles()109   public void reset_shouldClearEmulatedFiles() {
110     final File file = new File("foo");
111     ShadowEnvironment.setExternalStorageEmulated(file, true);
112 
113     assertThat(Environment.isExternalStorageEmulated(file)).isTrue();
114     ShadowEnvironment.reset();
115     assertThat(Environment.isExternalStorageEmulated(file)).isFalse();
116   }
117 
118   @Test
isExternalStorageEmulatedNoArg_shouldReturnSavedValue()119   public void isExternalStorageEmulatedNoArg_shouldReturnSavedValue() {
120     ShadowEnvironment.setIsExternalStorageEmulated(true);
121     assertThat(Environment.isExternalStorageEmulated()).isTrue();
122     ShadowEnvironment.reset();
123     assertThat(Environment.isExternalStorageEmulated()).isFalse();
124   }
125 
126   // TODO: failing test
127   @Ignore
128   @Test
129   @Config(minSdk = KITKAT)
getExternalFilesDirs()130   public void getExternalFilesDirs() throws Exception {
131     ShadowEnvironment.addExternalDir("external_dir_1");
132     ShadowEnvironment.addExternalDir("external_dir_2");
133 
134     File[] externalFilesDirs =
135         ApplicationProvider.getApplicationContext()
136             .getExternalFilesDirs(Environment.DIRECTORY_MOVIES);
137 
138     assertThat(externalFilesDirs).isNotEmpty();
139     assertThat(externalFilesDirs[0].getCanonicalPath()).contains("external_dir_1");
140     assertThat(externalFilesDirs[1].getCanonicalPath()).contains("external_dir_2");
141 
142     // TODO(jongerrish): This fails because ShadowContext overwrites getExternalFilesDir.
143 //     assertThat(RuntimeEnvironment.application.getExternalFilesDir(Environment.DIRECTORY_MOVIES)
144 //         .getCanonicalPath()).contains("external_dir_1");
145   }
146 
147   @Test
148   @Config(sdk = JELLY_BEAN_MR1)
getExternalStorageStateJB()149   public void getExternalStorageStateJB() throws Exception {
150     ShadowEnvironment.setExternalStorageState("blah");
151     assertThat(ShadowEnvironment.getExternalStorageState()).isEqualTo("blah");
152   }
153 
154   @Test
155   @Config(minSdk = KITKAT, maxSdk = LOLLIPOP)
getExternalStorageStatePreLollipopMR1()156   public void getExternalStorageStatePreLollipopMR1() throws Exception {
157     File storageDir1 = ShadowEnvironment.addExternalDir("dir1");
158     File storageDir2 = ShadowEnvironment.addExternalDir("dir2");
159     ShadowEnvironment.setExternalStorageState(storageDir1, Environment.MEDIA_MOUNTED);
160     ShadowEnvironment.setExternalStorageState(storageDir2, Environment.MEDIA_REMOVED);
161     ShadowEnvironment.setExternalStorageState("blah");
162 
163     assertThat(ShadowEnvironment.getStorageState(storageDir1))
164         .isEqualTo(Environment.MEDIA_MOUNTED);
165     assertThat(ShadowEnvironment.getStorageState(storageDir2))
166         .isEqualTo(Environment.MEDIA_REMOVED);
167     assertThat(ShadowEnvironment.getStorageState(new File(storageDir1, "subpath")))
168         .isEqualTo(Environment.MEDIA_MOUNTED);
169     assertThat(ShadowEnvironment.getExternalStorageState()).isEqualTo("blah");
170   }
171 
172   @Test
173   @Config(minSdk = LOLLIPOP_MR1)
getExternalStorageState()174   public void getExternalStorageState() throws Exception {
175     File storageDir1 = ShadowEnvironment.addExternalDir("dir1");
176     File storageDir2 = ShadowEnvironment.addExternalDir("dir2");
177     ShadowEnvironment.setExternalStorageState(storageDir1, Environment.MEDIA_MOUNTED);
178     ShadowEnvironment.setExternalStorageState(storageDir2, Environment.MEDIA_REMOVED);
179     ShadowEnvironment.setExternalStorageState("blah");
180 
181     assertThat(ShadowEnvironment.getExternalStorageState(storageDir1))
182         .isEqualTo(Environment.MEDIA_MOUNTED);
183     assertThat(ShadowEnvironment.getStorageState(storageDir1))
184         .isEqualTo(Environment.MEDIA_MOUNTED);
185     assertThat(ShadowEnvironment.getExternalStorageState(storageDir2))
186         .isEqualTo(Environment.MEDIA_REMOVED);
187     assertThat(ShadowEnvironment.getStorageState(storageDir2))
188         .isEqualTo(Environment.MEDIA_REMOVED);
189     assertThat(ShadowEnvironment.getExternalStorageState(new File(storageDir1, "subpath")))
190         .isEqualTo(Environment.MEDIA_MOUNTED);
191     assertThat(ShadowEnvironment.getStorageState(new File(storageDir1, "subpath")))
192         .isEqualTo(Environment.MEDIA_MOUNTED);
193     assertThat(ShadowEnvironment.getExternalStorageState()).isEqualTo("blah");
194   }
195 
196   @Test
197   @Config(minSdk = M)
isExternalStorageEmulated()198   public void isExternalStorageEmulated() {
199     ShadowEnvironment.setIsExternalStorageEmulated(true);
200     assertThat(Environment.isExternalStorageEmulated()).isTrue();
201 
202     ShadowEnvironment.setIsExternalStorageEmulated(false);
203     assertThat(Environment.isExternalStorageEmulated()).isFalse();
204   }
205 }
206