diff options
Diffstat (limited to 'app/src')
-rw-r--r-- | app/src/main/java/se/leap/bitmaskclient/ProviderManager.java | 47 | ||||
-rw-r--r-- | app/src/test/java/se/leap/bitmaskclient/ProviderManagerTest.java | 189 |
2 files changed, 225 insertions, 11 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java index 97ba3b98..a36c2dec 100644 --- a/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/ProviderManager.java @@ -1,6 +1,7 @@ package se.leap.bitmaskclient; import android.content.res.AssetManager; +import android.support.annotation.VisibleForTesting; import com.pedrogomez.renderers.AdapteeCollection; @@ -8,9 +9,7 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; @@ -22,6 +21,11 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import static se.leap.bitmaskclient.utils.FileHelper.createFile; +import static se.leap.bitmaskclient.utils.FileHelper.persistFile; +import static se.leap.bitmaskclient.utils.InputStreamHelper.getInputStreamFrom; +import static se.leap.bitmaskclient.utils.InputStreamHelper.loadInputStreamAsString; + /** * Created by parmegv on 4/12/14. */ @@ -37,6 +41,8 @@ public class ProviderManager implements AdapteeCollection<Provider> { private static ProviderManager instance; final private static String URLS = "urls"; + final private static String EXT_JSON = ".json"; + final private static String EXT_PEM = ".pem"; public static ProviderManager getInstance(AssetManager assetsManager, File externalFilesDir) { if (instance == null) @@ -45,6 +51,11 @@ public class ProviderManager implements AdapteeCollection<Provider> { return instance; } + @VisibleForTesting + static void reset() { + instance = null; + } + private ProviderManager(AssetManager assetManager, File externalFilesDir) { this.assetsManager = assetManager; addDefaultProviders(assetManager); @@ -79,8 +90,8 @@ public class ProviderManager implements AdapteeCollection<Provider> { String provider = file.substring(0, file.length() - ".url".length()); InputStream provider_file = assetsManager.open(directory + "/" + file); mainUrl = extractMainUrlFromInputStream(provider_file); - certificate = ConfigHelper.loadInputStreamAsString(assetsManager.open(provider + ".pem")); - providerDefinition = ConfigHelper.loadInputStreamAsString(assetsManager.open(provider + ".json")); + certificate = loadInputStreamAsString(assetsManager.open(provider + EXT_PEM)); + providerDefinition = loadInputStreamAsString(assetsManager.open(provider + EXT_JSON)); } catch (IOException e) { e.printStackTrace(); } @@ -107,7 +118,7 @@ public class ProviderManager implements AdapteeCollection<Provider> { Set<Provider> providers = new HashSet<>(); try { for (String file : files) { - String mainUrl = extractMainUrlFromInputStream(ConfigHelper.getInputStreamFrom(externalFilesDir.getAbsolutePath() + "/" + file)); + String mainUrl = extractMainUrlFromInputStream(getInputStreamFrom(externalFilesDir.getAbsolutePath() + "/" + file)); providers.add(new Provider(new URL(mainUrl))); } } catch (MalformedURLException | FileNotFoundException e) { @@ -219,19 +230,33 @@ public class ProviderManager implements AdapteeCollection<Provider> { defaultProviderURLs.clear(); } - //FIXME: removed custom providers should be deleted here as well void saveCustomProvidersToFile() { try { + deleteLegacyCustomProviders(); + for (Provider provider : customProviders) { - File providerFile = new File(externalFilesDir, provider.getName() + ".json"); + File providerFile = createFile(externalFilesDir, provider.getName() + EXT_JSON); if (!providerFile.exists()) { - FileWriter writer = new FileWriter(providerFile); - writer.write(provider.toJson().toString()); - writer.close(); + persistFile(providerFile, provider.toJson().toString()); } } - } catch (IOException e) { + } catch (IOException | SecurityException e) { e.printStackTrace(); } } + + /** + * Deletes persisted custom providers from from internal storage that are not in customProviders list anymore + */ + private void deleteLegacyCustomProviders() throws IOException, SecurityException { + Set<Provider> persistedCustomProviders = externalFilesDir != null && externalFilesDir.isDirectory() ? + providersFromFiles(externalFilesDir.list()) : new HashSet<Provider>(); + persistedCustomProviders.removeAll(customProviders); + for (Provider providerToDelete : persistedCustomProviders) { + File providerFile = createFile(externalFilesDir, providerToDelete.getName() + EXT_JSON); + if (providerFile.exists()) { + providerFile.delete(); + } + } + } } diff --git a/app/src/test/java/se/leap/bitmaskclient/ProviderManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/ProviderManagerTest.java new file mode 100644 index 00000000..1914f989 --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/ProviderManagerTest.java @@ -0,0 +1,189 @@ +package se.leap.bitmaskclient; + +import android.content.res.AssetManager; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; + +import se.leap.bitmaskclient.utils.ConfigHelper; +import se.leap.bitmaskclient.utils.FileHelper; +import se.leap.bitmaskclient.utils.InputStreamHelper; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.verifyStatic; +import static se.leap.bitmaskclient.testutils.MockHelper.mockFileHelper; +import static se.leap.bitmaskclient.testutils.MockHelper.mockInputStreamHelper; + +/** + * Created by cyberta on 20.02.18. + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({ConfigHelper.class, FileHelper.class, InputStreamHelper.class}) +public class ProviderManagerTest { + + @Mock + private AssetManager assetManager; + @Mock + private File file; + private ProviderManager providerManager; + + @Before + public void setup() throws Exception { + //mock assetManager methods + //-------------------------- + when(assetManager.open(anyString())).thenAnswer(new Answer<InputStream>() { + @Override + public InputStream answer(InvocationOnMock invocation) throws Throwable { + String filename = "preconfigured/" + invocation.getArguments()[0]; + return getClass().getClassLoader().getResourceAsStream(filename); + } + }); + when(assetManager.list(anyString())).thenAnswer(new Answer<String[]>() { + @Override + public String[] answer(InvocationOnMock invocation) throws Throwable { + String path = (String) invocation.getArguments()[0]; + if ("urls".equals(path)) { + String[] preconfiguredUrls = new String[3]; + preconfiguredUrls[0] = "calyx.net.url"; + preconfiguredUrls[1] = "demo.bitmask.net.url"; + preconfiguredUrls[2] = "riseup.net.url"; + return preconfiguredUrls; + } else + throw new IllegalArgumentException("You need to implement the expected path manually!"); + } + }); + + //mock File methods + //------------------ + when(file.isDirectory()).thenReturn(true); + + ArrayList<String> mockedCustomProviderList = new ArrayList<>(); + mockedCustomProviderList.add("leapcolombia.json"); + String[] mockedCustomProviderArray = new String[mockedCustomProviderList.size()]; + mockedCustomProviderArray = mockedCustomProviderList.toArray(mockedCustomProviderArray); + when(file.list()).thenReturn(mockedCustomProviderArray); + + when(file.getAbsolutePath()).thenReturn("externalDir"); + when(file.getPath()).thenReturn("externalDir"); + mockFileHelper(file); + + // mock inputStream + //----------------------------------- + mockInputStreamHelper(); + + } + + @After + public void tearDown() { + ProviderManager.reset(); + } + + @Test + public void testSize_has5ProvidersWithCurrentTestSetup() { + providerManager = ProviderManager.getInstance(assetManager, file); + assertEquals("3 preconfigured, 1 custom provider, 1 dummy provider", 5, providerManager.size()); + } + + @Test + public void testAdd_newCustomProviderThatIsNotPartOfDefaultNorCustomList_returnTrue() throws Exception { + providerManager = ProviderManager.getInstance(assetManager, file); + Provider customProvider = new Provider("https://anewprovider.org"); + assertTrue("custom provider added: ", providerManager.add(customProvider)); + assertEquals("3 preconfigured, 2 custom providers, 1 dummy provider", 6, providerManager.providers().size()); + } + + @Test + public void testAdd_newCustomProviderThatIsNotPartOfDefaultButOfCustomList_returnFalse() throws Exception { + providerManager = ProviderManager.getInstance(assetManager, file); + Provider customProvider = new Provider("https://leapcolombia.org"); + assertFalse("custom provider added: ", providerManager.add(customProvider)); + assertEquals("3 preconfigured, 1 custom provider, 1 dummy provider", 5, providerManager.providers().size()); + } + + @Test + public void testAdd_newCustomProviderThatIsPartOfDefaultButNotOfCustomList_returnFalse() throws Exception { + providerManager = ProviderManager.getInstance(assetManager, file); + Provider customProvider = new Provider("https://demo.bitmask.net"); + assertFalse("custom provider added: ", providerManager.add(customProvider)); + assertEquals("3 preconfigured, 1 custom provider, 1 dummy provider", 5, providerManager.providers().size()); + } + + @Test + public void testRemove_ProviderIsPartOfDefaultButNotCustomList_returnsFalse() throws Exception { + providerManager = ProviderManager.getInstance(assetManager, file); + Provider customProvider = new Provider("https://demo.bitmask.net"); + assertFalse("custom provider not removed: ", providerManager.remove(customProvider)); + assertEquals("3 preconfigured, 1 custom provider, 1 dummy provider", 5, providerManager.providers().size()); + } + + @Test + public void testRemove_ProviderIsNotPartOfDefaultButOfCustomList_returnsTrue() throws Exception { + providerManager = ProviderManager.getInstance(assetManager, file); + Provider customProvider = new Provider("https://leapcolombia.org"); + assertTrue("custom provider not removed: ", providerManager.remove(customProvider)); + assertEquals("3 preconfigured, 0 custom providers, 1 dummy provider", 4, providerManager.providers().size()); + } + + @Test + public void testRemove_ProviderIsNotPartOfDefaultNorOfCustomList_returnsFalse() throws Exception { + providerManager = ProviderManager.getInstance(assetManager, file); + Provider customProvider = new Provider("https://anotherprovider.org"); + assertFalse("custom provider not removed: ", providerManager.remove(customProvider)); + assertEquals("3 preconfigured, 1 custom providers, 1 dummy provider", 5, providerManager.providers().size()); + } + + @Test + public void testClear_ProvidersListHasOnlyDummyProvider() throws Exception { + providerManager = ProviderManager.getInstance(assetManager, file); + providerManager.clear(); + assertEquals("1 providers", 1, providerManager.providers().size()); + assertEquals("provider is dummy element", "https://example.net", providerManager.get(0).getMainUrlString()); + } + + @Test + public void testSaveCustomProvidersToFile_CustomProviderDeleted_deletesFromDir() throws Exception { + when(file.exists()).thenReturn(true); + providerManager = ProviderManager.getInstance(assetManager, file); + //leapcolombia is mocked custom provider from setup + Provider customProvider = new Provider("https://leapcolombia.org"); + providerManager.remove(customProvider); + providerManager.saveCustomProvidersToFile(); + verify(file, times(1)).delete(); + } + + + @Test + public void testSaveCustomProvidersToFile_newCustomProviders_persistNew() throws Exception { + when(file.list()).thenReturn(new String[0]); + when(file.exists()).thenReturn(false); + providerManager = ProviderManager.getInstance(assetManager, file); + Provider customProvider = new Provider("https://anotherprovider.org"); + Provider secondCustomProvider = new Provider("https://yetanotherprovider.org"); + providerManager.add(customProvider); + providerManager.add(secondCustomProvider); + providerManager.saveCustomProvidersToFile(); + + verifyStatic(FileHelper.class, times(2)); + FileHelper.persistFile(any(File.class), anyString()); + } + + +}
\ No newline at end of file |