diff --git a/libs/SalesforceAnalytics/soemthing.txt b/libs/SalesforceAnalytics/soemthing.txt new file mode 100644 index 0000000000..a16fac05ed --- /dev/null +++ b/libs/SalesforceAnalytics/soemthing.txt @@ -0,0 +1,4 @@ +asdfdsf + + +asdfljsadfklnasdlf diff --git a/libs/SalesforceAnalytics/src/com/salesforce/androidsdk/analytics/dummy.txt b/libs/SalesforceAnalytics/src/com/salesforce/androidsdk/analytics/dummy.txt new file mode 100644 index 0000000000..a3b8cdc9ad --- /dev/null +++ b/libs/SalesforceAnalytics/src/com/salesforce/androidsdk/analytics/dummy.txt @@ -0,0 +1 @@ +this is a dummy file for pr testing diff --git a/libs/SalesforceHybrid/build.gradle b/libs/SalesforceHybrid/build.gradle index 5ea5ce84f5..046330780f 100644 --- a/libs/SalesforceHybrid/build.gradle +++ b/libs/SalesforceHybrid/build.gradle @@ -16,6 +16,8 @@ apply plugin: 'com.jfrog.bintray' dependencies { api project(':libs:SmartSync') api 'org.apache.cordova:framework:7.0.0' + androidTestApi 'com.android.support.test:runner:1.0.1' + androidTestApi 'com.android.support.test:rules:1.0.1' } android { @@ -47,7 +49,7 @@ android { } defaultConfig { testApplicationId "com.salesforce.androidsdk.salesforcehybrid.tests" - testInstrumentationRunner "com.salesforce.androidsdk.analytics.util.test.JUnitReportTestRunner" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } packagingOptions { exclude 'META-INF/LICENSE' diff --git a/libs/SalesforceSDK/test.txt b/libs/SalesforceSDK/test.txt new file mode 100644 index 0000000000..ccd50bf466 --- /dev/null +++ b/libs/SalesforceSDK/test.txt @@ -0,0 +1 @@ +adfasdfsa dsaflnsdkfjlnasdlknfaslkd diff --git a/libs/SmartStore/build.gradle b/libs/SmartStore/build.gradle index 59b036c415..2fb3e5bfbb 100644 --- a/libs/SmartStore/build.gradle +++ b/libs/SmartStore/build.gradle @@ -16,6 +16,9 @@ apply plugin: 'com.jfrog.bintray' dependencies { api project(':libs:SalesforceSDK') api 'net.zetetic:android-database-sqlcipher:3.5.7' + androidTestApi 'com.android.support.test:runner:1.0.1' + androidTestApi 'com.android.support.test:rules:1.0.1' + androidTestApi 'com.android.support.test.espresso:espresso-core:3.0.1' } android { @@ -48,13 +51,14 @@ android { } defaultConfig { testApplicationId "com.salesforce.androidsdk.smartstore.tests" - testInstrumentationRunner "com.salesforce.androidsdk.analytics.util.test.JUnitReportTestRunner" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } packagingOptions { exclude 'META-INF/LICENSE' exclude 'META-INF/LICENSE.txt' exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/NOTICE' + pickFirst 'protobuf.meta' } lintOptions { diff --git a/libs/SmartStore/src/com/salesforce/androidsdk/smartstore/mmmhmmmm.txt b/libs/SmartStore/src/com/salesforce/androidsdk/smartstore/mmmhmmmm.txt new file mode 100644 index 0000000000..3a632f621e --- /dev/null +++ b/libs/SmartStore/src/com/salesforce/androidsdk/smartstore/mmmhmmmm.txt @@ -0,0 +1 @@ +asdflnasdlkfnasndflkn diff --git a/libs/SmartSync/build.gradle b/libs/SmartSync/build.gradle index 7193cb55ee..cb6b8677de 100644 --- a/libs/SmartSync/build.gradle +++ b/libs/SmartSync/build.gradle @@ -15,6 +15,8 @@ apply plugin: 'com.jfrog.bintray' dependencies { api project(':libs:SmartStore') + androidTestApi 'com.android.support.test:runner:1.0.1' + androidTestApi 'com.android.support.test:rules:1.0.1' } android { @@ -47,7 +49,7 @@ android { } defaultConfig { testApplicationId "com.salesforce.androidsdk.smartsync.tests" - testInstrumentationRunner "com.salesforce.androidsdk.analytics.util.test.JUnitReportTestRunner" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } packagingOptions { exclude 'META-INF/LICENSE' diff --git a/libs/test/SalesforceHybridTest/AndroidManifest.xml b/libs/test/SalesforceHybridTest/AndroidManifest.xml index 3d9d87712f..a256856e4d 100644 --- a/libs/test/SalesforceHybridTest/AndroidManifest.xml +++ b/libs/test/SalesforceHybridTest/AndroidManifest.xml @@ -2,34 +2,23 @@ - - - - + android:manageSpaceActivity="com.salesforce.androidsdk.ui.ManageSpaceActivity"> - + + - diff --git a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/ForceJSTest.java b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/ForceJSTest.java index 1e1c8a2559..fc242a77ae 100644 --- a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/ForceJSTest.java +++ b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/ForceJSTest.java @@ -26,69 +26,95 @@ */ package com.salesforce.androidsdk.phonegap; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.Arrays; import java.util.List; -import com.salesforce.androidsdk.phonegap.util.test.JSTestCase; - /** - * Running javascript tests for force.js library + * Running javascript tests for force.js. */ +@RunWith(AndroidJUnit4.class) +@SmallTest public class ForceJSTest extends JSTestCase { public ForceJSTest() { super("ForceJSTestSuite"); } + @Before + public void setUp() throws Exception { + super.setUp(); + } + @Override public List getTestNames() { return Arrays.asList(new String[] { "testParseUrl", "testComputeEndPointIfMissing", - "testOwnedFilesList", "testFilesInUsersGroups", - "testFilesSharedWithUser", "testFileDetails", - "testBatchFileDetails", "testFileShares", "testAddFileShare", - "testDeleteFileShare" }); + "testOwnedFilesList", + "testFilesInUsersGroups", + "testFilesSharedWithUser", + "testFileDetails", + "testBatchFileDetails", + "testFileShares", + "testAddFileShare", + "testDeleteFileShare" + }); } + @Test public void testParseUrl() { runTest("testParseUrl"); } + @Test public void testComputeEndPointIfMissing() { runTest("testComputeEndPointIfMissing"); } + @Test public void testOwnedFilesList() { runTest("testOwnedFilesList"); } + @Test public void testFilesInUsersGroups() { runTest("testFilesInUsersGroups"); } + @Test public void testFilesSharedWithUser() { runTest("testFilesSharedWithUser"); } + @Test public void testFileDetails() { runTest("testFileDetails"); } + @Test public void testBatchFileDetails() { runTest("testBatchFileDetails"); } - + + @Test public void testFileShares() { runTest("testFileShares"); } + @Test public void testAddFileShare() { runTest("testAddFileShare"); } + @Test public void testDeleteFileShare() { runTest("testDeleteFileShare"); } - } diff --git a/libs/SalesforceHybrid/src/com/salesforce/androidsdk/phonegap/util/test/JSTestCase.java b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/JSTestCase.java similarity index 90% rename from libs/SalesforceHybrid/src/com/salesforce/androidsdk/phonegap/util/test/JSTestCase.java rename to libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/JSTestCase.java index a7207c36f6..fa2425e07e 100644 --- a/libs/SalesforceHybrid/src/com/salesforce/androidsdk/phonegap/util/test/JSTestCase.java +++ b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/JSTestCase.java @@ -24,11 +24,11 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -package com.salesforce.androidsdk.phonegap.util.test; +package com.salesforce.androidsdk.phonegap; import android.app.Instrumentation; import android.content.Intent; -import android.test.InstrumentationTestCase; +import android.support.test.InstrumentationRegistry; import com.salesforce.androidsdk.app.SalesforceSDKManager; import com.salesforce.androidsdk.phonegap.plugin.TestRunnerPlugin; @@ -38,6 +38,8 @@ import com.salesforce.androidsdk.util.EventsObservable.EventType; import com.salesforce.androidsdk.util.test.EventsListenerQueue; +import junit.framework.Assert; + import org.apache.cordova.CordovaWebView; import java.util.HashMap; @@ -46,28 +48,24 @@ import java.util.concurrent.TimeUnit; /** - * Extend this class to run tests written in JavaScript + * Extend this class to run tests written in JavaScript. */ -public abstract class JSTestCase extends InstrumentationTestCase { +public abstract class JSTestCase { private static final String TAG = "JSTestCase"; private String jsSuite; private static Map> testResults; - - + public JSTestCase(String jsSuite) { this.jsSuite = jsSuite; } - - @Override + public void setUp() throws Exception { - if (testResults == null || !testResults.containsKey(jsSuite)) { if (testResults == null) { - testResults = new HashMap>(); + testResults = new HashMap<>(); } - if (!testResults.containsKey(jsSuite)) { testResults.put(jsSuite, new HashMap()); } @@ -79,7 +77,7 @@ public void setUp() throws Exception { } // Start main activity - Instrumentation instrumentation = getInstrumentation(); + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); final Intent intent = new Intent(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClassName(instrumentation.getTargetContext(), SalesforceSDKManager.getInstance().getMainActivityClass().getName()); @@ -102,7 +100,7 @@ public void run() { }); } SalesforceHybridLogger.i(TAG, "Running test: " + testName); - + // Block until test completes or times out TestResult result = null; int timeout = getMaxRuntimeInSecondsForTest(testName); @@ -111,12 +109,11 @@ public void run() { if (result == null) { result = new TestResult(testName, false, "Timeout (" + timeout + " seconds) exceeded", timeout); } - } - catch (Exception e) { + } catch (Exception e) { result = new TestResult(testName, false, "Test failed", timeout); } SalesforceHybridLogger.i(TAG, "Finished running test: " + testName); - + // Save result testResults.get(jsSuite).put(testName, result); } @@ -147,7 +144,7 @@ protected int getMaxRuntimeInSecondsForTest(String testName) { */ protected void runTest(String testName) { TestResult result = testResults.get(jsSuite).get(testName); - assertNotNull("No test result", result); - assertTrue(result.testName + " " + result.message, result.success); + Assert.assertNotNull("No test result", result); + Assert.assertTrue(result.testName + " " + result.message, result.success); } } diff --git a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/JavaScriptPluginVersionTest.java b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/JavaScriptPluginVersionTest.java index dd5a0ae530..843d6c80c5 100644 --- a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/JavaScriptPluginVersionTest.java +++ b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/JavaScriptPluginVersionTest.java @@ -26,114 +26,129 @@ */ package com.salesforce.androidsdk.phonegap; -import android.test.InstrumentationTestCase; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import com.salesforce.androidsdk.app.SalesforceSDKManager; import com.salesforce.androidsdk.phonegap.plugin.JavaScriptPluginVersion; +import junit.framework.Assert; + +import org.junit.Test; +import org.junit.runner.RunWith; /** - * Tests for JavaScriptPluginVersion - * + * Tests for JavaScriptPluginVersion. */ -public class JavaScriptPluginVersionTest extends InstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +@SmallTest +public class JavaScriptPluginVersionTest { /** * Test for safeParseInt */ + @Test public void testSafeParseInt() { - assertEquals(1, JavaScriptPluginVersion.safeParseInt("1", -1)); - assertEquals(-1, JavaScriptPluginVersion.safeParseInt("not-a-number", -1)); + Assert.assertEquals(1, JavaScriptPluginVersion.safeParseInt("1", -1)); + Assert.assertEquals(-1, JavaScriptPluginVersion.safeParseInt("not-a-number", -1)); } /** * Test for compare versions when the same versions are passed in */ + @Test public void testCompareVersionsSameVersion() { - assertEquals(0, JavaScriptPluginVersion.compareVersions("1", "1")); - assertEquals(0, JavaScriptPluginVersion.compareVersions("1.2", "1.2")); - assertEquals(0, JavaScriptPluginVersion.compareVersions("2.2.3", "2.2.3")); + Assert.assertEquals(0, JavaScriptPluginVersion.compareVersions("1", "1")); + Assert.assertEquals(0, JavaScriptPluginVersion.compareVersions("1.2", "1.2")); + Assert.assertEquals(0, JavaScriptPluginVersion.compareVersions("2.2.3", "2.2.3")); } /** * Test for compare versions when the same versions are passed in and one is marked as dev * dev version is assumed to be older */ + @Test public void testCompareVersionsSameVersionWithDev() { - assertEquals(-1, JavaScriptPluginVersion.compareVersions("1.dev", "1")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("1", "1.dev")); - assertEquals(-1, JavaScriptPluginVersion.compareVersions("1.2.dev", "1.2")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("1.2", "1.2.dev")); - assertEquals(-1, JavaScriptPluginVersion.compareVersions("2.2.3.dev", "2.2.3")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("2.2.3", "2.2.3.dev")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("1.dev", "1")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("1", "1.dev")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("1.2.dev", "1.2")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("1.2", "1.2.dev")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("2.2.3.dev", "2.2.3")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("2.2.3", "2.2.3.dev")); } /** * Test for compare versions when one version is a patch on the other * NB dev is simply ignored */ + @Test public void testCompareVersionsWithPatch() { - assertEquals(-1, JavaScriptPluginVersion.compareVersions("1", "1.1")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("1.1", "1")); - assertEquals(-1, JavaScriptPluginVersion.compareVersions("2.4", "2.4.2")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("2.4.2", "2.4")); - assertEquals(-1, JavaScriptPluginVersion.compareVersions("3.5.1", "3.5.1.3")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("3.5.1.3", "3.5.1")); - assertEquals(-1, JavaScriptPluginVersion.compareVersions("3.5", "3.5.1.3")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("3.5.1.3", "3.5")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("1", "1.1")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("1.1", "1")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("2.4", "2.4.2")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("2.4.2", "2.4")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("3.5.1", "3.5.1.3")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("3.5.1.3", "3.5.1")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("3.5", "3.5.1.3")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("3.5.1.3", "3.5")); } /** * Test for compare versions with versions with two digits * NB dev is simply ignored */ + @Test public void testCompareVersionsWithTwoDigits() { - assertEquals(-1, JavaScriptPluginVersion.compareVersions("9", "14")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("14", "9")); - assertEquals(-1, JavaScriptPluginVersion.compareVersions("2.9", "2.14")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("2.14", "2.9")); - assertEquals(-1, JavaScriptPluginVersion.compareVersions("1.2.9", "1.2.14")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("1.2.14", "1.2.9")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("9", "14")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("14", "9")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("2.9", "2.14")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("2.14", "2.9")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("1.2.9", "1.2.14")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("1.2.14", "1.2.9")); } /** * Create JavaScriptPluginVersion for empty version (always considered older) */ + @Test public void testJavaScriptPluginVersionsWithNoVersion() { - assertEquals(-1, JavaScriptPluginVersion.compareVersions("", "2.0")); - assertEquals(0, JavaScriptPluginVersion.compareVersions("", "")); - assertEquals(1, JavaScriptPluginVersion.compareVersions("2.0", "")); + Assert.assertEquals(-1, JavaScriptPluginVersion.compareVersions("", "2.0")); + Assert.assertEquals(0, JavaScriptPluginVersion.compareVersions("", "")); + Assert.assertEquals(1, JavaScriptPluginVersion.compareVersions("2.0", "")); } /** * Create JavaScriptPluginVersion for old versions and make sure isCurrent/isOlder/isNewer returns the value expected */ + @Test public void testJavaScriptPluginVersionsWithOldVersions() { for (String version : new String[] {"1.0", "1.1", "1.2", "1.3"}) { - assertTrue((new JavaScriptPluginVersion(version)).isOlder()); - assertFalse((new JavaScriptPluginVersion(version)).isCurrent()); - assertFalse((new JavaScriptPluginVersion(version)).isNewer()); + Assert.assertTrue((new JavaScriptPluginVersion(version)).isOlder()); + Assert.assertFalse((new JavaScriptPluginVersion(version)).isCurrent()); + Assert.assertFalse((new JavaScriptPluginVersion(version)).isNewer()); } } /** * Create JavaScriptPluginVersion for current version and make sure isCurrent/isOlder/isNewer returns the value expected */ + @Test public void testJavaScriptPluginVersionsWithCurrentVersion() { - assertFalse((new JavaScriptPluginVersion(SalesforceSDKManager.SDK_VERSION)).isOlder()); - assertTrue((new JavaScriptPluginVersion(SalesforceSDKManager.SDK_VERSION)).isCurrent()); - assertFalse((new JavaScriptPluginVersion(SalesforceSDKManager.SDK_VERSION)).isNewer()); + Assert.assertFalse((new JavaScriptPluginVersion(SalesforceSDKManager.SDK_VERSION)).isOlder()); + Assert.assertTrue((new JavaScriptPluginVersion(SalesforceSDKManager.SDK_VERSION)).isCurrent()); + Assert.assertFalse((new JavaScriptPluginVersion(SalesforceSDKManager.SDK_VERSION)).isNewer()); } /** * Create JavaScriptPluginVersion for future versions and make sure isCurrent/isOlder/isNewer returns the value expected */ + @Test public void testJavaScriptPluginVersionsWithNewVersion() { for (String version : new String[] {"6.2.0", "6.3.0", "6.4.0"}) { - assertFalse((new JavaScriptPluginVersion(version)).isOlder()); - assertFalse((new JavaScriptPluginVersion(version)).isCurrent()); - assertTrue((new JavaScriptPluginVersion(version)).isNewer()); + Assert.assertFalse((new JavaScriptPluginVersion(version)).isOlder()); + Assert.assertFalse((new JavaScriptPluginVersion(version)).isCurrent()); + Assert.assertTrue((new JavaScriptPluginVersion(version)).isNewer()); } } } diff --git a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SDKInfoJSTest.java b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SDKInfoJSTest.java index c9c78c9886..b290c7554a 100644 --- a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SDKInfoJSTest.java +++ b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SDKInfoJSTest.java @@ -26,26 +26,38 @@ */ package com.salesforce.androidsdk.phonegap; -import java.util.Arrays; -import java.util.List; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; -import com.salesforce.androidsdk.phonegap.util.test.JSTestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import java.util.Arrays; +import java.util.List; /** - * Running javascript tests for SDKInfo plugin + * Running javascript tests for SDKInfo plugin. */ +@RunWith(AndroidJUnit4.class) +@SmallTest public class SDKInfoJSTest extends JSTestCase { public SDKInfoJSTest() { super("SDKInfoTestSuite"); } + @Before + public void setUp() throws Exception { + super.setUp(); + } + @Override public List getTestNames() { return Arrays.asList("testGetInfo"); } - + + @Test public void testGetInfo() { runTest("testGetInfo"); } diff --git a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SDKInfoPluginTest.java b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SDKInfoPluginTest.java index f63e63e2c6..0558edf29c 100644 --- a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SDKInfoPluginTest.java +++ b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SDKInfoPluginTest.java @@ -28,7 +28,9 @@ import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; -import android.test.InstrumentationTestCase; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import com.salesforce.androidsdk.app.SalesforceSDKManager; import com.salesforce.androidsdk.config.BootConfig; @@ -39,80 +41,79 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.List; /** - * Tests for SDKInfoPlugin - * + * Tests for SDKInfoPlugin. */ -public class SDKInfoPluginTest extends InstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +@SmallTest +public class SDKInfoPluginTest { /** * Test for getSDKInfo */ + @Test public void testGetSDKInfo() throws NameNotFoundException, JSONException { - Context ctx = getInstrumentation().getTargetContext(); + Context ctx = InstrumentationRegistry.getTargetContext(); JSONObject sdkInfo = SDKInfoPlugin.getSDKInfo(ctx); BootConfig bootconfig = BootConfig.getBootConfig(ctx); - assertEquals("Wrong app name", "SalesforceHybridTest", sdkInfo.getString("appName")); - assertEquals("Wrong app version", "1.0", sdkInfo.getString("appVersion")); - List sdkInfoPlugins = toList(sdkInfo.getJSONArray("forcePluginsAvailable")); - assertEquals("Wrong number of plugins", 7, sdkInfoPlugins.size()); - assertTrue("network plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.network")); - assertTrue("oauth plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.oauth")); - assertTrue("sdkinfo plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.sdkinfo")); - assertTrue("sfaccountmanager plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.sfaccountmanager")); - assertTrue("smartstore plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.smartstore")); - assertTrue("smartsync plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.smartsync")); - assertTrue("testrunner plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.testrunner")); - assertEquals("Wrong version", SalesforceSDKManager.SDK_VERSION, sdkInfo.getString("sdkVersion")); - + Assert.assertEquals("Wrong app name", "SalesforceHybridTest", sdkInfo.getString("appName")); + Assert.assertEquals("Wrong app version", "1.0", sdkInfo.getString("appVersion")); + List sdkInfoPlugins = toList(sdkInfo.getJSONArray("forcePluginsAvailable")); + Assert.assertEquals("Wrong number of plugins", 7, sdkInfoPlugins.size()); + Assert.assertTrue("network plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.network")); + Assert.assertTrue("oauth plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.oauth")); + Assert.assertTrue("sdkinfo plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.sdkinfo")); + Assert.assertTrue("sfaccountmanager plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.sfaccountmanager")); + Assert.assertTrue("smartstore plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.smartstore")); + Assert.assertTrue("smartsync plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.smartsync")); + Assert.assertTrue("testrunner plugin should have been returned", sdkInfoPlugins.contains("com.salesforce.testrunner")); + Assert.assertEquals("Wrong version", SalesforceSDKManager.SDK_VERSION, sdkInfo.getString("sdkVersion")); JSONObject sdkInfoBootConfig = sdkInfo.getJSONObject("bootConfig"); - assertEquals("Wrong bootconfig shouldAuthenticate", bootconfig.shouldAuthenticate(), sdkInfoBootConfig.getBoolean("shouldAuthenticate")); - assertEquals("Wrong bootconfig attemptOfflineLoad", bootconfig.attemptOfflineLoad(), sdkInfoBootConfig.getBoolean("attemptOfflineLoad")); - assertEquals("Wrong bootconfig isLocal", bootconfig.isLocal(), sdkInfoBootConfig.getBoolean("isLocal")); + Assert.assertEquals("Wrong bootconfig shouldAuthenticate", bootconfig.shouldAuthenticate(), sdkInfoBootConfig.getBoolean("shouldAuthenticate")); + Assert.assertEquals("Wrong bootconfig attemptOfflineLoad", bootconfig.attemptOfflineLoad(), sdkInfoBootConfig.getBoolean("attemptOfflineLoad")); + Assert.assertEquals("Wrong bootconfig isLocal", bootconfig.isLocal(), sdkInfoBootConfig.getBoolean("isLocal")); List sdkInfoOAuthScopes = toList(sdkInfoBootConfig.getJSONArray("oauthScopes")); - assertEquals("Wrong bootconfig oauthScopes", 1, sdkInfoOAuthScopes.size()); - assertTrue("Wrong bootconfig oauthScopes", sdkInfoOAuthScopes.contains("api")); - assertEquals("Wrong bootconfig oauthRedirectURI", bootconfig.getOauthRedirectURI(), sdkInfoBootConfig.getString("oauthRedirectURI")); - assertEquals("Wrong bootconfig remoteAccessConsumerKey", bootconfig.getRemoteAccessConsumerKey(), sdkInfoBootConfig.getString("remoteAccessConsumerKey")); + Assert.assertEquals("Wrong bootconfig oauthScopes", 1, sdkInfoOAuthScopes.size()); + Assert.assertTrue("Wrong bootconfig oauthScopes", sdkInfoOAuthScopes.contains("api")); + Assert.assertEquals("Wrong bootconfig oauthRedirectURI", bootconfig.getOauthRedirectURI(), sdkInfoBootConfig.getString("oauthRedirectURI")); + Assert.assertEquals("Wrong bootconfig remoteAccessConsumerKey", bootconfig.getRemoteAccessConsumerKey(), sdkInfoBootConfig.getString("remoteAccessConsumerKey")); try { sdkInfoBootConfig.getString("androidPushNotificationClientId"); Assert.fail("Wrong bootconfig having androidPushNotificationClientId field"); } catch (Exception ex) { - //don't do anything since the exception is expected + + // don't do anything since the exception is expected } - assertEquals("Wrong bootconfig startPage", "index.html", sdkInfoBootConfig.optString("startPage")); - assertEquals("Wrong bootconfig errorPage", "error.html", sdkInfoBootConfig.optString("errorPage")); + Assert.assertEquals("Wrong bootconfig startPage", "index.html", sdkInfoBootConfig.optString("startPage")); + Assert.assertEquals("Wrong bootconfig errorPage", "error.html", sdkInfoBootConfig.optString("errorPage")); } /** * Test for getForcePluginsFromXML */ + @Test public void testGetForcePluginsFromXML() { - List plugins = SDKInfoPlugin.getForcePluginsFromXML(getInstrumentation().getTargetContext()); - assertEquals("Wrong number of force plugins", 7, plugins.size()); - assertTrue("network plugin should have been returned", plugins.contains("com.salesforce.network")); - assertTrue("oauth plugin should have been returned", plugins.contains("com.salesforce.oauth")); - assertTrue("sdkinfo plugin should have been returned", plugins.contains("com.salesforce.sdkinfo")); - assertTrue("sfaccountmanager plugin should have been returned", plugins.contains("com.salesforce.sfaccountmanager")); - assertTrue("smartstore plugin should have been returned", plugins.contains("com.salesforce.smartstore")); - assertTrue("smartsync plugin should have been returned", plugins.contains("com.salesforce.smartsync")); - assertTrue("testrunner plugin should have been returned", plugins.contains("com.salesforce.testrunner")); + List plugins = SDKInfoPlugin.getForcePluginsFromXML(InstrumentationRegistry.getTargetContext()); + Assert.assertEquals("Wrong number of force plugins", 7, plugins.size()); + Assert.assertTrue("network plugin should have been returned", plugins.contains("com.salesforce.network")); + Assert.assertTrue("oauth plugin should have been returned", plugins.contains("com.salesforce.oauth")); + Assert.assertTrue("sdkinfo plugin should have been returned", plugins.contains("com.salesforce.sdkinfo")); + Assert.assertTrue("sfaccountmanager plugin should have been returned", plugins.contains("com.salesforce.sfaccountmanager")); + Assert.assertTrue("smartstore plugin should have been returned", plugins.contains("com.salesforce.smartstore")); + Assert.assertTrue("smartsync plugin should have been returned", plugins.contains("com.salesforce.smartsync")); + Assert.assertTrue("testrunner plugin should have been returned", plugins.contains("com.salesforce.testrunner")); } - - /** - * Helper method - * @param jsonArray - * @return - * @throws JSONException - */ + private List toList(JSONArray jsonArray) throws JSONException { List list = new ArrayList(jsonArray.length()); - for (int i=0; i getTestNames() { }); } + @Test public void testGetDatabaseSize() { runTest("testGetDatabaseSize"); } + @Test public void testRegisterRemoveSoup() { runTest("testRegisterRemoveSoup"); } + @Test public void testRegisterWithSpec() { runTest("testRegisterRemoveSoup"); } - public void testRegisterRemoveSoupGlobalStore() { + @Test + public void testRegisterRemoveSoupGlobalStore() { runTest("testRegisterRemoveSoupGlobalStore"); } + @Test public void testRegisterBogusSoup() { runTest("testRegisterBogusSoup"); } + @Test public void testRegisterSoupNoIndices() { runTest("testRegisterSoupNoIndices"); } + @Test public void testUpsertSoupEntries() { runTest("testUpsertSoupEntries"); } - public void testUpsertSoupEntriesWithExternalId() { + @Test + public void testUpsertSoupEntriesWithExternalId() { runTest("testUpsertSoupEntriesWithExternalId"); } + @Test public void testUpsertToNonexistentSoup() { runTest("testUpsertToNonexistentSoup"); } + @Test public void testRetrieveSoupEntries() { runTest("testRetrieveSoupEntries"); } + @Test public void testRemoveFromSoup() { runTest("testRemoveFromSoup"); } + @Test public void testRemoveFromSoupByQuery() { runTest("testRemoveFromSoupByQuery"); } + @Test public void testQuerySoupWithExactQuery() { runTest("testQuerySoupWithExactQuery"); } - public void testQuerySoupWithAllQueryDescending() { + @Test + public void testQuerySoupWithAllQueryDescending() { runTest("testQuerySoupWithAllQueryDescending"); } + @Test public void testQuerySoupWithRangeQueryWithOrderPath() { runTest("testQuerySoupWithRangeQueryWithOrderPath"); } + @Test public void testQuerySoupBadQuerySpec() { runTest("testQuerySoupBadQuerySpec"); } + @Test public void testQuerySoupEndKeyNoBeginKey() { runTest("testQuerySoupEndKeyNoBeginKey"); } + @Test public void testQuerySoupBeginKeyNoEndKey() { runTest("testQuerySoupBeginKeyNoEndKey"); } + @Test public void testManipulateCursor() { runTest("testManipulateCursor"); } + @Test public void testMoveCursorToPreviousPageFromFirstPage() { runTest("testMoveCursorToPreviousPageFromFirstPage"); } + @Test public void testMoveCursorToNextPageFromLastPage() { runTest("testMoveCursorToNextPageFromLastPage"); } + @Test public void testArbitrarySoupNames() { runTest("testArbitrarySoupNames"); } + @Test public void testQuerySpecFactories() { runTest("testQuerySpecFactories"); } + @Test public void testLikeQuerySpecStartsWith() { runTest("testLikeQuerySpecStartsWith"); } + @Test public void testLikeQuerySpecEndsWith() { runTest("testLikeQuerySpecEndsWith"); } + @Test public void testLikeQueryInnerText() { runTest("testLikeQueryInnerText"); } + @Test public void testFullTextSearch() { runTest("testFullTextSearch"); } + @Test public void testCompoundQueryPath() { runTest("testCompoundQueryPath"); } + @Test public void testEmptyQuerySpec() { runTest("testEmptyQuerySpec"); } + @Test public void testIntegerQuerySpec() { runTest("testIntegerQuerySpec"); } + @Test public void testSmartQueryWithCount() { runTest("testSmartQueryWithCount"); } + @Test public void testSmartQueryWithSpecialFields() { runTest("testSmartQueryWithSpecialFields"); } + @Test public void testSmartQueryWithIntegerCompare() { runTest("testSmartQueryWithIntegerCompare"); } + @Test public void testSmartQueryWithMultipleFieldsAndWhereInClause() { runTest("testSmartQueryWithMultipleFieldsAndWhereInClause"); } + @Test public void testSmartQueryWithSingleFieldAndWhereInClause() { runTest("testSmartQueryWithSingleFieldAndWhereInClause"); } + @Test public void testSmartQueryWithWhereLikeClause() { runTest("testSmartQueryWithWhereLikeClause"); } + @Test public void testSmartQueryWithWhereLikeClauseOrdered() { runTest("testSmartQueryWithWhereLikeClauseOrdered"); } + @Test public void testGetSoupIndexSpecs() { runTest("testGetSoupIndexSpecs"); } + @Test public void testGetSoupIndexSpecsWithBogusSoupName() { runTest("testGetSoupIndexSpecsWithBogusSoupName"); } + @Test public void testAlterSoupNoReIndexing() { runTest("testAlterSoupNoReIndexing"); } + @Test public void testAlterSoupWithReIndexing() { runTest("testAlterSoupWithReIndexing"); } + @Test public void testAlterSoupWithSpecNoReIndexing() { runTest("testAlterSoupWithSpecNoReIndexing"); } + @Test public void testAlterSoupWithSpecWithReIndexing() { runTest("testAlterSoupWithSpecWithReIndexing"); } + @Test public void testAlterSoupWithBogusSoupName() { runTest("testAlterSoupWithBogusSoupName"); } + @Test public void testReIndexSoup() { runTest("testReIndexSoup"); } + @Test public void testClearSoup() { runTest("testClearSoup"); } - + @Test public void testFullTextSearchAgainstArrayNode() { runTest("testFullTextSearchAgainstArrayNode"); } + @Test public void testLikeQueryAgainstArrayNode() { runTest("testLikeQueryAgainstArrayNode"); } + @Test public void testExactQueryAgainstArrayNode() { runTest("testExactQueryAgainstArrayNode"); } + @Test public void testSmartQueryAgainstArrayNode() { runTest("testSmartQueryAgainstArrayNode"); } + @Test public void testCreateMultipleGlobalStores() { runTest("testCreateMultipleGlobalStores"); } + @Test public void testCreateMultipleUserStores() { runTest("testCreateMultipleUserStores"); } - } diff --git a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SmartStoreLoadJSTest.java b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SmartStoreLoadJSTest.java index 11091afeb5..514a4947f9 100644 --- a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SmartStoreLoadJSTest.java +++ b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SmartStoreLoadJSTest.java @@ -26,26 +26,37 @@ */ package com.salesforce.androidsdk.phonegap; -import java.util.Arrays; -import java.util.List; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; -import com.salesforce.androidsdk.phonegap.util.test.JSTestCase; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import java.util.Arrays; +import java.util.List; /** - * Running javascript tests for SmartStore plugin + * Running javascript tests for SmartStore plugin. */ +@RunWith(AndroidJUnit4.class) +@LargeTest public class SmartStoreLoadJSTest extends JSTestCase { public SmartStoreLoadJSTest() { super("SmartStoreLoadTestSuite"); } - + + @Before + public void setUp() throws Exception { + super.setUp(); + } + @Override protected int getMaxRuntimeInSecondsForTest(String testName) { return 60; - } - + } + @Override public List getTestNames() { return Arrays.asList(new String[] { @@ -57,27 +68,33 @@ public List getTestNames() { "testUpsertConcurrentEntries" }); } - + + @Test public void testNumerousFields() { runTest("testNumerousFields"); } - + + @Test public void testIncreasingFieldLength() { runTest("testIncreasingFieldLength"); } + @Test public void testAddAndRetrieveManyEntries() { runTest("testAddAndRetrieveManyEntries"); } - + + @Test public void testUpsertManyEntries() { runTest("testUpsertManyEntries"); } - + + @Test public void testUpsertAndQueryEntries() { runTest("testUpsertAndQueryEntries"); } - + + @Test public void testUpsertConcurrentEntries() { runTest("testUpsertConcurrentEntries"); } diff --git a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SmartSyncJSTest.java b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SmartSyncJSTest.java index e90a588d5f..41f839b71b 100644 --- a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SmartSyncJSTest.java +++ b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/SmartSyncJSTest.java @@ -26,20 +26,32 @@ */ package com.salesforce.androidsdk.phonegap; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.Arrays; import java.util.List; -import com.salesforce.androidsdk.phonegap.util.test.JSTestCase; - /** - * Running javascript tests for smart sync library. + * Running javascript tests for smart sync plugin. */ +@RunWith(AndroidJUnit4.class) +@LargeTest public class SmartSyncJSTest extends JSTestCase { public SmartSyncJSTest() { super("SmartSyncTestSuite"); } + @Before + public void setUp() throws Exception { + super.setUp(); + } + @Override protected int getMaxRuntimeInSecondsForTest(String testName) { return 30; @@ -112,246 +124,307 @@ public List getTestNames() { }); } + @Test public void testStoreCacheInit() { runTest("testStoreCacheInit"); } + @Test public void testStoreCacheRetrieve() { runTest("testStoreCacheRetrieve"); } + @Test public void testStoreCacheSave() { runTest("testStoreCacheSave"); } + @Test public void testStoreCacheSaveAll() { runTest("testStoreCacheSaveAll"); } + @Test public void testStoreCacheRemove() { runTest("testStoreCacheRemove"); } + @Test public void testStoreCacheFind() { runTest("testStoreCacheFind"); } + @Test public void testStoreCacheAddLocalFields() { runTest("testStoreCacheAddLocalFields"); } + @Test public void testStoreCacheWithGlobalStore() { runTest("testStoreCacheWithGlobalStore"); } + @Test public void testSObjectTypeDescribe() { runTest("testSObjectTypeDescribe"); } + @Test public void testSObjectTypeGetMetadata() { runTest("testSObjectTypeGetMetadata"); } + @Test public void testSObjectTypeDescribeLayout() { runTest("testSObjectTypeDescribeLayout"); } + @Test public void testSObjectTypeCacheOnlyMode() { runTest("testSObjectTypeCacheOnlyMode"); } + @Test public void testSObjectTypeCacheMerge() { runTest("testSObjectTypeCacheMerge"); } + @Test public void testMultiSObjectTypes() { runTest("testMultiSObjectTypes"); } + @Test public void testSObjectTypeReset() { runTest("testSObjectTypeReset"); } + @Test public void testSyncRemoteObjectWithCacheCreate() { runTest("testSyncRemoteObjectWithCacheCreate"); } + @Test public void testSyncRemoteObjectWithCacheRead() { runTest("testSyncRemoteObjectWithCacheRead"); } + @Test public void testSyncRemoteObjectWithCacheUpdate() { runTest("testSyncRemoteObjectWithCacheUpdate"); } + @Test public void testSyncRemoteObjectWithCacheDelete() { runTest("testSyncRemoteObjectWithCacheDelete"); } + @Test public void testSyncSObjectWithServerCreate() { runTest("testSyncSObjectWithServerCreate"); } + @Test public void testSyncSObjectWithServerRead() { runTest("testSyncSObjectWithServerRead"); } + @Test public void testSyncSObjectWithServerUpdate() { runTest("testSyncSObjectWithServerUpdate"); } + @Test public void testSyncSObjectWithServerDelete() { runTest("testSyncSObjectWithServerDelete"); } + @Test public void testSyncSObjectCreate() { runTest("testSyncSObjectCreate"); } + @Test public void testSyncSObjectRetrieve() { runTest("testSyncSObjectRetrieve"); } + @Test public void testSyncSObjectUpdate() { runTest("testSyncSObjectUpdate"); } + @Test public void testSyncSObjectDelete() { runTest("testSyncSObjectDelete"); } + @Test public void testSyncSObjectDetectConflictCreate() { runTest("testSyncSObjectDetectConflictCreate"); } + @Test public void testSyncSObjectDetectConflictRetrieve() { runTest("testSyncSObjectDetectConflictRetrieve"); } + @Test public void testSyncSObjectDetectConflictUpdate() { runTest("testSyncSObjectDetectConflictUpdate"); } + @Test public void testSyncSObjectDetectConflictDelete() { runTest("testSyncSObjectDetectConflictDelete"); } + @Test public void testSObjectFetch() { runTest("testSObjectFetch"); } + @Test public void testSObjectSave() { runTest("testSObjectSave"); } + @Test public void testSObjectDestroy() { runTest("testSObjectDestroy"); } + @Test public void testSyncApexRestObjectWithServerCreate() { runTest("testSyncApexRestObjectWithServerCreate"); } + @Test public void testSyncApexRestObjectWithServerRead() { runTest("testSyncApexRestObjectWithServerRead"); } + @Test public void testSyncApexRestObjectWithServerUpdate() { runTest("testSyncApexRestObjectWithServerUpdate"); } + @Test public void testSyncApexRestObjectWithServerDelete() { runTest("testSyncApexRestObjectWithServerDelete"); } + @Test public void testFetchApexRestObjectsFromServer() { runTest("testFetchApexRestObjectsFromServer"); } + @Test public void testFetchSObjectsFromServer() { runTest("testFetchSObjectsFromServer"); } + @Test public void testFetchSObjects() { runTest("testFetchSObjects"); } + @Test public void testSObjectCollectionFetch() { runTest("testSObjectCollectionFetch"); } + @Test public void testSyncDown() { runTest("testSyncDown"); } + @Test public void testSyncDownToGlobalStore() { runTest("testSyncDownToGlobalStore"); } + @Test public void testSyncDownWithNoOverwrite() { runTest("testSyncDownWithNoOverwrite"); } + @Test public void testReSync() { runTest("testReSync"); } + @Test public void testRefreshSyncDown() { runTest("testRefreshSyncDown"); } + @Test public void testCleanResyncGhosts() { runTest("testCleanResyncGhosts"); } + @Test public void testSyncUpLocallyUpdated() { runTest("testSyncUpLocallyUpdated"); } + @Test public void testSyncUpLocallyUpdatedWithGlobalStore() { runTest("testSyncUpLocallyUpdatedWithGlobalStore"); } + @Test public void testSyncUpLocallyUpdatedWithNoOverwrite() { runTest("testSyncUpLocallyUpdatedWithNoOverwrite"); } + @Test public void testSyncUpLocallyDeleted() { runTest("testSyncUpLocallyDeleted"); } + @Test public void testSyncUpLocallyDeletedWithNoOverwrite() { runTest("testSyncUpLocallyDeletedWithNoOverwrite"); } + @Test public void testSyncUpLocallyCreated() { runTest("testSyncUpLocallyCreated"); } + @Test public void testStoreCacheWithGlobalStoreNamed() { runTest("testStoreCacheWithGlobalStoreNamed"); } + @Test public void testSyncDownToGlobalStoreNamed() { runTest("testSyncDownToGlobalStoreNamed"); } + @Test public void testSyncUpLocallyUpdatedWithGlobalStoreNamed() { runTest("testSyncUpLocallyUpdatedWithGlobalStoreNamed"); } + @Test public void testSyncDownGetSyncDeleteSyncById() { runTest("testSyncDownGetSyncDeleteSyncById"); } + @Test public void testSyncDownGetSyncDeleteSyncByName() { runTest("testSyncDownGetSyncDeleteSyncByName"); } + @Test public void testSyncUpGetSyncDeleteSyncById() { runTest("testSyncUpGetSyncDeleteSyncById"); } + @Test public void testSyncUpGetSyncDeleteSyncByName() { runTest("testSyncUpGetSyncDeleteSyncByName"); } diff --git a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/app/SalesforceHybridTestApp.java b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/app/SalesforceHybridTestApp.java index 63cef61225..7e19ed61e1 100644 --- a/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/app/SalesforceHybridTestApp.java +++ b/libs/test/SalesforceHybridTest/src/com/salesforce/androidsdk/phonegap/app/SalesforceHybridTestApp.java @@ -32,7 +32,7 @@ import com.salesforce.androidsdk.ui.LoginActivity; /** - * Test application for smart store plugin. + * Test application for Salesforce Cordova plugins. */ public class SalesforceHybridTestApp extends Application { diff --git a/libs/test/SalesforceSDKTest/AndroidManifest.xml b/libs/test/SalesforceSDKTest/AndroidManifest.xml index 784cf92ebd..cb48c8ab72 100644 --- a/libs/test/SalesforceSDKTest/AndroidManifest.xml +++ b/libs/test/SalesforceSDKTest/AndroidManifest.xml @@ -8,7 +8,8 @@ android:manageSpaceActivity="com.salesforce.androidsdk.ui.ManageSpaceActivity"> - diff --git a/libs/test/SmartStoreTest/AndroidManifest.xml b/libs/test/SmartStoreTest/AndroidManifest.xml index 799aa53136..27b7b78f27 100644 --- a/libs/test/SmartStoreTest/AndroidManifest.xml +++ b/libs/test/SmartStoreTest/AndroidManifest.xml @@ -1,30 +1,23 @@ + package="com.salesforce.androidsdk.smartstore.tests"> + - - - diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/TestForceApp.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/TestForceApp.java index 98ed79255c..ecff88e68d 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/TestForceApp.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/TestForceApp.java @@ -28,7 +28,6 @@ import android.app.Application; -import com.salesforce.androidsdk.app.SalesforceSDKManager; import com.salesforce.androidsdk.smartstore.app.SmartStoreSDKManager; /** @@ -42,6 +41,6 @@ public class TestForceApp extends Application { public void onCreate() { SmartStoreSDKManager.initNative(getApplicationContext(), MainActivity.class); super.onCreate(); - SalesforceSDKManager.getInstance().setIsTestRun(true); + SmartStoreSDKManager.getInstance().setIsTestRun(true); } } diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/DBOpenHelperTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/DBOpenHelperTest.java index 82f4006385..5b862b5029 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/DBOpenHelperTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/DBOpenHelperTest.java @@ -26,28 +26,38 @@ */ package com.salesforce.androidsdk.store; -import java.io.File; -import java.util.Map; -import java.util.Set; - -import org.json.JSONException; -import org.json.JSONObject; +import android.content.Context; +import android.os.Bundle; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import com.salesforce.androidsdk.accounts.UserAccount; import com.salesforce.androidsdk.analytics.EventBuilderHelper; import com.salesforce.androidsdk.analytics.security.Encryptor; import com.salesforce.androidsdk.smartstore.store.DBOpenHelper; +import junit.framework.Assert; + import net.sqlcipher.database.SQLiteDatabase; -import android.content.Context; -import android.os.Bundle; -import android.test.InstrumentationTestCase; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.Map; +import java.util.Set; /** * Tests for obtaining and deleting databases via the DBOpenHelper. */ -public class DBOpenHelperTest extends InstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +@LargeTest +public class DBOpenHelperTest { // constants used for building a test user account private static final String TEST_USER_ID = "005123"; @@ -60,72 +70,79 @@ public class DBOpenHelperTest extends InstrumentationTestCase { private static final String TEST_DB = "test_db"; private static final String PASSCODE = Encryptor.hash("test_key", "hashing-key"); - @Override - protected void setUp() throws Exception { - this.targetContext = getInstrumentation().getTargetContext(); + @Before + public void setUp() throws Exception { + this.targetContext = InstrumentationRegistry.getTargetContext(); EventBuilderHelper.enableDisable(false); // Delete external blobs folder for test db and test soup DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); helper.removeExternalBlobsDirectory(TEST_SOUP); - - super.setUp(); } - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } + @After + public void tearDown() throws Exception { + final String dbPath = InstrumentationRegistry.getTargetContext().getApplicationInfo().dataDir + "/databases"; + final File fileDir = new File(dbPath); + DBOpenHelper.deleteAllUserDatabases(InstrumentationRegistry.getTargetContext()); + DBOpenHelper.deleteDatabase(InstrumentationRegistry.getTargetContext(), null); + DBOpenHelper.removeAllFiles(fileDir); + } /** * Make sure database name is correct for no account and no communityId. */ + @Test public void testGetHelperForNullAccountNullCommunityId() { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, "somedb", null, null); SQLiteDatabase db = helper.getWritableDatabase(""); String dbName = getBaseName(db); - assertEquals("Database name is not correct.","somedb.db", dbName); + Assert.assertEquals("Database name is not correct.","somedb.db", dbName); } /** * Make sure database name is correct for account without a communityId. */ + @Test public void testGetHelperForAccountNullCommunityId() { UserAccount testAcct = getTestUserAccount(); DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, "somedb", testAcct, null); SQLiteDatabase db = helper.getWritableDatabase(""); String dbName = getBaseName(db); - assertTrue("Database name does not contain org id.",dbName.contains(TEST_ORG_ID)); - assertTrue("Database name does not contain user id.",dbName.contains(TEST_USER_ID)); - assertTrue("Database name does not have default internal community id.",dbName.contains(UserAccount.INTERNAL_COMMUNITY_PATH)); + Assert.assertTrue("Database name does not contain org id.",dbName.contains(TEST_ORG_ID)); + Assert.assertTrue("Database name does not contain user id.",dbName.contains(TEST_USER_ID)); + Assert.assertTrue("Database name does not have default internal community id.",dbName.contains(UserAccount.INTERNAL_COMMUNITY_PATH)); } /** * Ensure that helpers are cached. */ + @Test public void testGetHelperIsCached() { DBOpenHelper helper1 = DBOpenHelper.getOpenHelper(targetContext, "somedb", null, null); DBOpenHelper helper2 = DBOpenHelper.getOpenHelper(targetContext, "somedb", null, null); - assertSame("Helpers should be cached.", helper1, helper2); + Assert.assertSame("Helpers should be cached.", helper1, helper2); } /** * When a database name is not given, the default name should be used. */ + @Test public void testGetHelperUsesDefaultDatabaseName() { UserAccount testAcct = getTestUserAccount(); DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, testAcct, TEST_COMMUNITY_ID); SQLiteDatabase db = helper.getWritableDatabase(""); String dbName = getBaseName(db); - assertTrue("Database name is not correct.", dbName.startsWith(DBOpenHelper.DEFAULT_DB_NAME)); - assertTrue("Database name does not contain org id.",dbName.contains(TEST_ORG_ID)); - assertTrue("Database name does not contain user id.",dbName.contains(TEST_USER_ID)); - assertTrue("Database name does not have default internal community id.",dbName.contains(TEST_COMMUNITY_ID)); + Assert.assertTrue("Database name is not correct.", dbName.startsWith(DBOpenHelper.DEFAULT_DB_NAME)); + Assert.assertTrue("Database name does not contain org id.",dbName.contains(TEST_ORG_ID)); + Assert.assertTrue("Database name does not contain user id.",dbName.contains(TEST_USER_ID)); + Assert.assertTrue("Database name does not have default internal community id.",dbName.contains(TEST_COMMUNITY_ID)); } /** * Ensures the default database is removed correctly. */ + @Test public void testDeleteDatabaseDefault() { // create db @@ -133,13 +150,14 @@ public void testDeleteDatabaseDefault() { SQLiteDatabase db = helper.getWritableDatabase(""); String dbName = getBaseName(db); DBOpenHelper.deleteDatabase(targetContext, null); - assertFalse("Database should not exist.", databaseExists(targetContext, dbName)); + Assert.assertFalse("Database should not exist.", databaseExists(targetContext, dbName)); } /** * Ensures all user databases are removed correctly, and the * global databases are retained. */ + @Test public void testDeleteAllUserDatabases() { final UserAccount testAcct = getTestUserAccount(); @@ -162,36 +180,38 @@ public void testDeleteAllUserDatabases() { // Delete all user databases. DBOpenHelper.deleteAllUserDatabases(targetContext); - assertFalse("Database should have been deleted.", + Assert.assertFalse("Database should have been deleted.", databaseExists(targetContext, dbName1)); - assertFalse("Database should have been deleted.", + Assert.assertFalse("Database should have been deleted.", databaseExists(targetContext, dbName2)); - assertTrue("Database should not have been deleted.", + Assert.assertTrue("Database should not have been deleted.", databaseExists(targetContext, dbName3)); // 1st and 2nd helpers should not be cached, but 3rd should still be cached. final Map helpers = DBOpenHelper.getOpenHelpers(); - assertNotNull("List of helpers should not be null.", helpers); + Assert.assertNotNull("List of helpers should not be null.", helpers); final Set dbNames = helpers.keySet(); - assertNotNull("List of DB names should not be null.", dbNames); - assertFalse("User database should not be cached.", dbNames.contains(dbName1)); - assertFalse("User database should not be cached.", dbNames.contains(dbName2)); - assertTrue("Global database should still be cached.", dbNames.contains(dbName3)); + Assert.assertNotNull("List of DB names should not be null.", dbNames); + Assert.assertFalse("User database should not be cached.", dbNames.contains(dbName1)); + Assert.assertFalse("User database should not be cached.", dbNames.contains(dbName2)); + Assert.assertTrue("Global database should still be cached.", dbNames.contains(dbName3)); } /** * Ensures the database is removed from the cache. */ + @Test public void testDeleteDatabaseRemovesFromCache() { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, null); DBOpenHelper.deleteDatabase(targetContext, null); DBOpenHelper helperPostDelete = DBOpenHelper.getOpenHelper(targetContext, null); - assertNotSame("Helpers should be different instances.", helper, helperPostDelete); + Assert.assertNotSame("Helpers should be different instances.", helper, helperPostDelete); } /** * Ensure that only the single community-specific database is deleted. */ + @Test public void testDeleteDatabaseWithCommunityId() { UserAccount testAcct = getTestUserAccount(); @@ -206,18 +226,19 @@ public void testDeleteDatabaseWithCommunityId() { // now, delete the first database and make sure we didn't remove the second. DBOpenHelper.deleteDatabase(targetContext, testAcct, TEST_COMMUNITY_ID); - assertTrue("Database should not have been deleted.", databaseExists(targetContext, dontDeleteDbName)); + Assert.assertTrue("Database should not have been deleted.", databaseExists(targetContext, dontDeleteDbName)); // 1st helper should not be cached, but 2nd should still be cached DBOpenHelper helperNew = DBOpenHelper.getOpenHelper(targetContext, testAcct, TEST_COMMUNITY_ID); - assertNotSame("Helper should have been removed from cache.", helper, helperNew); + Assert.assertNotSame("Helper should have been removed from cache.", helper, helperNew); DBOpenHelper dontDeleteHelperCached = DBOpenHelper.getOpenHelper(targetContext, testAcct, "other_community_id"); - assertSame("Helper should be same instance.", dontDeleteHelper, dontDeleteHelperCached); + Assert.assertSame("Helper should be same instance.", dontDeleteHelper, dontDeleteHelperCached); } /** * Ensure that all databases related to the account are removed when community id is not specified. */ + @Test public void testDeleteDatabaseWithoutCommunityId() { UserAccount testAcct = getTestUserAccount(); @@ -232,74 +253,79 @@ public void testDeleteDatabaseWithoutCommunityId() { String dbName2 = getBaseName(db2); // now, delete all databases related to accounts and ensure they no longer exist - DBOpenHelper.deleteDatabase(targetContext, testAcct); - - assertFalse("Database should not exist.", databaseExists(targetContext, dbName)); - assertFalse("Database should not exist.", databaseExists(targetContext, dbName2)); + DBOpenHelper.deleteDatabase(targetContext, testAcct); + Assert.assertFalse("Database should not exist.", databaseExists(targetContext, dbName)); + Assert.assertFalse("Database should not exist.", databaseExists(targetContext, dbName2)); // also make sure references to the helpers no longer exist DBOpenHelper helperNew = DBOpenHelper.getOpenHelper(targetContext, testAcct, TEST_COMMUNITY_ID); DBOpenHelper helperNew2 = DBOpenHelper.getOpenHelper(targetContext, testAcct, "other_community_id"); - assertNotSame("Helper should have been removed from cache.", helper, helperNew); - assertNotSame("Helper should have been removed from cache.", helper2, helperNew2); + Assert.assertNotSame("Helper should have been removed from cache.", helper, helperNew); + Assert.assertNotSame("Helper should have been removed from cache.", helper2, helperNew2); } /** * Has smart store for given account returns true. */ + @Test public void testHasSmartStoreIsTrueForDefaultDatabase() { UserAccount testAcct = getTestUserAccount(); DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, testAcct); helper.getWritableDatabase(""); - assertTrue("SmartStore for account should exist.", + Assert.assertTrue("SmartStore for account should exist.", DBOpenHelper.smartStoreExists(targetContext, testAcct, null)); } /** * Has smart store for given account returns false. */ + @Test public void testHasSmartStoreIsFalseForDefaultDatabase() { - assertFalse("SmartStore for account should not exist.", + Assert.assertFalse("SmartStore for account should not exist.", DBOpenHelper.smartStoreExists(targetContext, null, null)); } /** * Has smart store for specified database and account returns true. */ + @Test public void testHasSmartStoreIsTrueForSpecifiedDatabase() { UserAccount testAcct = getTestUserAccount(); DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, "testdb", testAcct, null); helper.getWritableDatabase(""); - assertTrue("SmartStore for account should exist.", + Assert.assertTrue("SmartStore for account should exist.", DBOpenHelper.smartStoreExists(targetContext, "testdb", testAcct, null)); } /** * Has smart store for given account returns false. */ + @Test public void testHasSmartStoreIsFalseForSpecifiedDatabase() { - assertFalse("SmartStore for account should not exist.", + Assert.assertFalse("SmartStore for account should not exist.", DBOpenHelper.smartStoreExists(targetContext, "dbdne", null, null)); } /** * Ensures we get the expected soup blobs path */ + @Test public void testGetExternalSoupBlobsPath() { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); // Test result when soup name is given - assertTrue("Wrong external soup blobs path returned.", + Assert.assertTrue("Wrong external soup blobs path returned.", helper.getExternalSoupBlobsPath(TEST_SOUP).endsWith("com.salesforce.androidsdk.smartstore.tests/databases/" + TEST_DB + ".db_external_soup_blobs/" + TEST_SOUP + "/")); // Test result when soup name is null - assertTrue("Wrong external soup blobs path returned.", + Assert.assertTrue("Wrong external soup blobs path returned.", helper.getExternalSoupBlobsPath(null).endsWith("com.salesforce.androidsdk.smartstore.tests/databases/" + TEST_DB + ".db_external_soup_blobs/")); } /** * Ensures expected folder was created */ + @Test public void testCreateExternalBlobsDirectory() { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); File folder = new File(targetContext.getApplicationInfo().dataDir + "/databases/" + TEST_DB + ".db_external_soup_blobs/" + TEST_SOUP + "/"); @@ -313,8 +339,8 @@ public void testCreateExternalBlobsDirectory() { boolean result = helper.createExternalBlobsDirectory(TEST_SOUP); // Test - assertTrue("Create operation was not successful", result); - assertTrue("Folder for external blobs was not created.", folder.exists()); + Assert.assertTrue("Create operation was not successful", result); + Assert.assertTrue("Folder for external blobs was not created.", folder.exists()); // Clean up folder.delete(); @@ -323,6 +349,7 @@ public void testCreateExternalBlobsDirectory() { /** * Test correct size of entire blobs directory is given */ + @Test public void testGetSizeOfDir() throws JSONException { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); String contents = "{size:9}"; @@ -343,23 +370,25 @@ public void testGetSizeOfDir() throws JSONException { } // Total size of all files should be 2 (since two subdirs) * 100 (since 100 files each) * filesize of each file after encryption - assertEquals("Total file sizes of both subdirectories is not correct.", 2 * 100 * (encryptedContents.length() + 1), helper.getSizeOfDir(null)); + Assert.assertEquals("Total file sizes of both subdirectories is not correct.", 2 * 100 * (encryptedContents.length() + 1), helper.getSizeOfDir(null)); } /** * Test size of entire blobs directory if it doesnt exist */ + @Test public void testGetSizeOfDirDoesntExist() throws JSONException { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); DBOpenHelper.deleteDatabase(targetContext, TEST_DB, null, null); // Total size of directory that doesnt exist should be 0. - assertEquals("Total file size should be zero if directory doesnt exist", 0, helper.getSizeOfDir(null)); + Assert.assertEquals("Total file size should be zero if directory doesnt exist", 0, helper.getSizeOfDir(null)); } /** * Ensures files and all subdirs are removed */ + @Test public void testRemoveAllFiles() throws JSONException { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); String contents = "{size:9}"; @@ -376,31 +405,33 @@ public void testRemoveAllFiles() throws JSONException { // Test that external blobs folder was removed (it cannot be removed unless all subdirectories/files have been removed File folder = new File(targetContext.getApplicationInfo().dataDir + "/databases/" + TEST_DB + ".db_external_soup_blobs/"); - assertFalse("Directory must be removed after calling removeAllFiles.", folder.exists()); + Assert.assertFalse("Directory must be removed after calling removeAllFiles.", folder.exists()); } /** * Ensures external blobs directory was removed */ + @Test public void testRemoveExternalBlobsDirectory() { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); File folder = new File(targetContext.getApplicationInfo().dataDir + "/databases/" + TEST_DB + ".db_external_soup_blobs/" + TEST_SOUP + "/"); // Create external blobs dir helper.createExternalBlobsDirectory(TEST_SOUP); - assertTrue("Folder for external blobs was not created.", folder.exists()); + Assert.assertTrue("Folder for external blobs was not created.", folder.exists()); // Act - delete external blobs dir boolean result = helper.removeExternalBlobsDirectory(TEST_SOUP); // Test - assertTrue("Remove operation was not successful", result); - assertFalse("Folder for external blobs was not removed.", folder.exists()); + Assert.assertTrue("Remove operation was not successful", result); + Assert.assertFalse("Folder for external blobs was not removed.", folder.exists()); } /** * Ensures error is not thrown if dataDir is null */ + @Test public void testRemoveExternalBlobsDirectoryNullDataDir() { String realDataDir = targetContext.getApplicationInfo().dataDir; targetContext.getApplicationInfo().dataDir = null; @@ -410,7 +441,7 @@ public void testRemoveExternalBlobsDirectoryNullDataDir() { boolean result = helper.removeExternalBlobsDirectory(TEST_SOUP); // Test - assertFalse("Remove operation was not successful since dataDir was null", result); + Assert.assertFalse("Remove operation was not successful since dataDir was null", result); // Reset dataDir back to real value (calling getOpenHelper with a new db resets the dataDir) targetContext.getApplicationInfo().dataDir = realDataDir; @@ -420,6 +451,7 @@ public void testRemoveExternalBlobsDirectoryNullDataDir() { /** * Ensures soup was created and stored on the file system. */ + @Test public void testSaveSoupBlob() throws JSONException { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); helper.createExternalBlobsDirectory(TEST_SOUP); @@ -431,7 +463,7 @@ public void testSaveSoupBlob() throws JSONException { // Verify file was created File blobFile = new File(helper.getExternalSoupBlobsPath(TEST_SOUP), "soupelt_" + soupEntryId); - assertTrue("File for blob not found on storage", blobFile.exists()); + Assert.assertTrue("File for blob not found on storage", blobFile.exists()); // Clean up blobFile.delete(); @@ -440,6 +472,7 @@ public void testSaveSoupBlob() throws JSONException { /** * Ensures soup was successfully retrieved from file system */ + @Test public void testLoadSoupBlob() throws JSONException { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); helper.createExternalBlobsDirectory(TEST_SOUP); @@ -453,8 +486,8 @@ public void testLoadSoupBlob() throws JSONException { JSONObject result = helper.loadSoupBlob(TEST_SOUP, soupEntryId, PASSCODE); // Verify - assertTrue("Retrieved soup does not have expected keys.", result.has("testKey")); - assertEquals("Retrieved soup does not have expected values.", soupEntryId, result.getLong("testKey")); + Assert.assertTrue("Retrieved soup does not have expected keys.", result.has("testKey")); + Assert.assertEquals("Retrieved soup does not have expected values.", soupEntryId, result.getLong("testKey")); // Clean up File blobFile = new File(helper.getExternalSoupBlobsPath(TEST_SOUP), "soupelt_" + soupEntryId); @@ -463,6 +496,7 @@ public void testLoadSoupBlob() throws JSONException { /** * Ensures soup was successfully removed from file system */ + @Test public void testRemoveSoupBlob() throws JSONException { DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); helper.createExternalBlobsDirectory(TEST_SOUP); @@ -477,12 +511,13 @@ public void testRemoveSoupBlob() throws JSONException { // Verify File blobFile = new File(helper.getExternalSoupBlobsPath(TEST_SOUP), "soupelt_" + soupEntryId); - assertFalse("File containing blob was not removed from file storage.", blobFile.exists()); + Assert.assertFalse("File containing blob was not removed from file storage.", blobFile.exists()); } /** * Ensures expected folder was created */ + @Test public void testGetSoupBlobFile() { long soupEntryId = System.currentTimeMillis(); DBOpenHelper helper = DBOpenHelper.getOpenHelper(targetContext, TEST_DB, null, null); @@ -491,27 +526,16 @@ public void testGetSoupBlobFile() { File soupBlobFile = helper.getSoupBlobFile(TEST_SOUP, soupEntryId); // Verify - assertTrue("Soup blob file does not have expected path.", + Assert.assertTrue("Soup blob file does not have expected path.", soupBlobFile.getAbsolutePath().endsWith("com.salesforce.androidsdk.smartstore.tests/databases/" + TEST_DB + ".db_external_soup_blobs/" + TEST_SOUP + "/soupelt_" + soupEntryId)); } - /** - * Determines if the given database file exists or not in the database directory. - * - * @param dbName The database name. - * @return - */ private boolean databaseExists(Context ctx, String dbName) { final String dbPath = ctx.getApplicationInfo().dataDir + "/databases/" + dbName; final File file = new File(dbPath); return file.exists(); } - /** - * Builds a user account we can use for test cases. - * - * @return A bare-bones user account. - */ private UserAccount getTestUserAccount() { Bundle bundle = new Bundle(); bundle.putString(UserAccount.USER_ID, TEST_USER_ID); @@ -519,12 +543,6 @@ private UserAccount getTestUserAccount() { return new UserAccount(bundle); } - /** - * Obtain the base filename from a given path. - * - * @param db The full path, including filename. - * @return Just the filename. - */ private String getBaseName(SQLiteDatabase db) { final String[] pathParts = db.getPath().split("/"); return pathParts[pathParts.length - 1]; diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/IndexSpecTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/IndexSpecTest.java index 2170a093d5..c1c9a23488 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/IndexSpecTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/IndexSpecTest.java @@ -26,16 +26,23 @@ */ package com.salesforce.androidsdk.store; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + import com.salesforce.androidsdk.smartstore.store.IndexSpec; import com.salesforce.androidsdk.smartstore.store.SmartStore.Type; -import junit.framework.TestCase; +import junit.framework.Assert; + +import org.junit.Test; +import org.junit.runner.RunWith; /** * Test class for IndexSpec - * */ -public class IndexSpecTest extends TestCase { +@RunWith(AndroidJUnit4.class) +@SmallTest +public class IndexSpecTest { private static final IndexSpec keyStringSpec = new IndexSpec("key", Type.string); private static final IndexSpec keyIntegerSpec = new IndexSpec("key", Type.integer); @@ -52,71 +59,76 @@ public class IndexSpecTest extends TestCase { /** * TEST for equals with same index specs */ + @Test public void testEqualsWithSame() { - assertEquals(keyStringSpec, new IndexSpec("key", Type.string)); - assertEquals(keyIntegerSpec, new IndexSpec("key", Type.integer)); - assertEquals(keyFloatingSpec, new IndexSpec("key", Type.floating)); - assertEquals(keyFullTextSpec, new IndexSpec("key", Type.full_text)); - assertEquals(keyJSON1Spec, new IndexSpec("key", Type.json1)); - assertEquals(keyStringSpecWithCol, new IndexSpec("key", Type.string, "COL_1")); - assertEquals(keyIntegerSpecWithCol, new IndexSpec("key", Type.integer, "COL_1")); - assertEquals(keyFloatingSpecWithCol, new IndexSpec("key", Type.floating, "COL_1")); - assertEquals(keyFullTextSpecWithCol, new IndexSpec("key", Type.full_text, "COL_1")); - assertEquals(keyJSON1SpecWithCol, new IndexSpec("key", Type.json1, "COL_1")); + Assert.assertEquals(keyStringSpec, new IndexSpec("key", Type.string)); + Assert.assertEquals(keyIntegerSpec, new IndexSpec("key", Type.integer)); + Assert.assertEquals(keyFloatingSpec, new IndexSpec("key", Type.floating)); + Assert.assertEquals(keyFullTextSpec, new IndexSpec("key", Type.full_text)); + Assert.assertEquals(keyJSON1Spec, new IndexSpec("key", Type.json1)); + Assert.assertEquals(keyStringSpecWithCol, new IndexSpec("key", Type.string, "COL_1")); + Assert.assertEquals(keyIntegerSpecWithCol, new IndexSpec("key", Type.integer, "COL_1")); + Assert.assertEquals(keyFloatingSpecWithCol, new IndexSpec("key", Type.floating, "COL_1")); + Assert.assertEquals(keyFullTextSpecWithCol, new IndexSpec("key", Type.full_text, "COL_1")); + Assert.assertEquals(keyJSON1SpecWithCol, new IndexSpec("key", Type.json1, "COL_1")); } /** * TEST for equals with index specs that have different paths / types or columnNames */ + @Test public void testEqualsWithDifferent() { + // Different path - assertFalse(keyStringSpec.equals(new IndexSpec("otherKey", Type.string))); + Assert.assertFalse(keyStringSpec.equals(new IndexSpec("otherKey", Type.string))); // Different type - assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.integer))); - assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.floating))); - assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.full_text))); - assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.json1))); + Assert.assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.integer))); + Assert.assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.floating))); + Assert.assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.full_text))); + Assert.assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.json1))); // Different columnName - assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.string, "COL_1"))); - assertFalse(keyStringSpecWithCol.equals(new IndexSpec("key", Type.string))); - assertFalse(keyStringSpecWithCol.equals(new IndexSpec("key", Type.string, "COL_2"))); + Assert.assertFalse(keyStringSpec.equals(new IndexSpec("key", Type.string, "COL_1"))); + Assert.assertFalse(keyStringSpecWithCol.equals(new IndexSpec("key", Type.string))); + Assert.assertFalse(keyStringSpecWithCol.equals(new IndexSpec("key", Type.string, "COL_2"))); } /** * TEST for equals with same index specs */ + @Test public void testHashCodeWithSame() { - assertEquals(keyStringSpec.hashCode(), new IndexSpec("key", Type.string).hashCode()); - assertEquals(keyIntegerSpec.hashCode(), new IndexSpec("key", Type.integer).hashCode()); - assertEquals(keyFloatingSpec.hashCode(), new IndexSpec("key", Type.floating).hashCode()); - assertEquals(keyFullTextSpec.hashCode(), new IndexSpec("key", Type.full_text).hashCode()); - assertEquals(keyJSON1Spec.hashCode(), new IndexSpec("key", Type.json1).hashCode()); - - assertEquals(keyStringSpecWithCol.hashCode(), new IndexSpec("key", Type.string, "COL_1").hashCode()); - assertEquals(keyIntegerSpecWithCol.hashCode(), new IndexSpec("key", Type.integer, "COL_1").hashCode()); - assertEquals(keyFloatingSpecWithCol.hashCode(), new IndexSpec("key", Type.floating, "COL_1").hashCode()); - assertEquals(keyFullTextSpecWithCol.hashCode(), new IndexSpec("key", Type.full_text, "COL_1").hashCode()); - assertEquals(keyJSON1SpecWithCol.hashCode(), new IndexSpec("key", Type.json1, "COL_1").hashCode()); + Assert.assertEquals(keyStringSpec.hashCode(), new IndexSpec("key", Type.string).hashCode()); + Assert.assertEquals(keyIntegerSpec.hashCode(), new IndexSpec("key", Type.integer).hashCode()); + Assert.assertEquals(keyFloatingSpec.hashCode(), new IndexSpec("key", Type.floating).hashCode()); + Assert.assertEquals(keyFullTextSpec.hashCode(), new IndexSpec("key", Type.full_text).hashCode()); + Assert.assertEquals(keyJSON1Spec.hashCode(), new IndexSpec("key", Type.json1).hashCode()); + Assert.assertEquals(keyStringSpecWithCol.hashCode(), new IndexSpec("key", Type.string, "COL_1").hashCode()); + Assert.assertEquals(keyIntegerSpecWithCol.hashCode(), new IndexSpec("key", Type.integer, "COL_1").hashCode()); + Assert.assertEquals(keyFloatingSpecWithCol.hashCode(), new IndexSpec("key", Type.floating, "COL_1").hashCode()); + Assert.assertEquals(keyFullTextSpecWithCol.hashCode(), new IndexSpec("key", Type.full_text, "COL_1").hashCode()); + Assert.assertEquals(keyJSON1SpecWithCol.hashCode(), new IndexSpec("key", Type.json1, "COL_1").hashCode()); } /** * TEST for equals with index specs that have different paths / types or columnNames */ + @Test public void testHashCodeWithDifferent() { + // Different path - assertFalse(keyStringSpec.hashCode() == new IndexSpec("otherKey", Type.string).hashCode()); + Assert.assertFalse(keyStringSpec.hashCode() == new IndexSpec("otherKey", Type.string).hashCode()); // Different type - assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.integer).hashCode()); - assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.floating).hashCode()); - assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.full_text).hashCode()); - assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.json1).hashCode()); + Assert.assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.integer).hashCode()); + Assert.assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.floating).hashCode()); + Assert.assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.full_text).hashCode()); + Assert.assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.json1).hashCode()); // Different columnName - assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.string, "COL_1").hashCode()); - assertFalse(keyStringSpecWithCol.hashCode() == new IndexSpec("key", Type.string).hashCode()); - assertFalse(keyStringSpecWithCol.hashCode() == new IndexSpec("key", Type.string, "COL_2").hashCode()); + Assert.assertFalse(keyStringSpec.hashCode() == new IndexSpec("key", Type.string, "COL_1").hashCode()); + Assert.assertFalse(keyStringSpecWithCol.hashCode() == new IndexSpec("key", Type.string).hashCode()); + Assert.assertFalse(keyStringSpecWithCol.hashCode() == new IndexSpec("key", Type.string, "COL_2").hashCode()); } } diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/QuerySpecTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/QuerySpecTest.java index 451dbd6df7..6e5d492290 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/QuerySpecTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/QuerySpecTest.java @@ -26,129 +26,158 @@ */ package com.salesforce.androidsdk.store; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + import com.salesforce.androidsdk.smartstore.store.QuerySpec; -import junit.framework.TestCase; +import junit.framework.Assert; + +import org.junit.Test; +import org.junit.runner.RunWith; /** * Test class for QuerySpecTest - * */ -public class QuerySpecTest extends TestCase { +@RunWith(AndroidJUnit4.class) +@SmallTest +public class QuerySpecTest { + @Test public void testAllQuerySmartSql() { QuerySpec querySpec = QuerySpec.buildAllQuerySpec("employees", "lastName", QuerySpec.Order.descending, 1); - assertEquals("Wrong smart sql for all query spec", "SELECT {employees:_soup} FROM {employees} ORDER BY {employees:lastName} DESC ", querySpec.smartSql); + Assert.assertEquals("Wrong smart sql for all query spec", "SELECT {employees:_soup} FROM {employees} ORDER BY {employees:lastName} DESC ", querySpec.smartSql); } + @Test public void testAllQuerySmartSqlWithSelectPaths() { QuerySpec querySpec = QuerySpec.buildAllQuerySpec("employees", new String[] {"firstName", "lastName"}, "lastName", QuerySpec.Order.descending, 1); - assertEquals("Wrong smart sql for all query spec", "SELECT {employees:firstName}, {employees:lastName} FROM {employees} ORDER BY {employees:lastName} DESC ", querySpec.smartSql); + Assert.assertEquals("Wrong smart sql for all query spec", "SELECT {employees:firstName}, {employees:lastName} FROM {employees} ORDER BY {employees:lastName} DESC ", querySpec.smartSql); } + @Test public void testAllQueryCountSmartSql() { QuerySpec querySpec = QuerySpec.buildAllQuerySpec("employees", "lastName", QuerySpec.Order.descending, 1); - assertEquals("Wrong count smart sql for all query spec", "SELECT count(*) FROM {employees} ", querySpec.countSmartSql); + Assert.assertEquals("Wrong count smart sql for all query spec", "SELECT count(*) FROM {employees} ", querySpec.countSmartSql); } + @Test public void testAllQueryIdsSmartSql() { QuerySpec querySpec = QuerySpec.buildAllQuerySpec("employees", "lastName", QuerySpec.Order.descending, 1); - assertEquals("Wrong ids smart sql for all query spec", "SELECT id FROM {employees} ORDER BY {employees:lastName} DESC ", querySpec.idsSmartSql); + Assert.assertEquals("Wrong ids smart sql for all query spec", "SELECT id FROM {employees} ORDER BY {employees:lastName} DESC ", querySpec.idsSmartSql); } + @Test public void testRangeQuerySmartSql() { QuerySpec querySpec = QuerySpec.buildRangeQuerySpec("employees", "lastName", "Bond", "Smith", "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong smart sql for range query spec", "SELECT {employees:_soup} FROM {employees} WHERE {employees:lastName} >= ? AND {employees:lastName} <= ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); + Assert.assertEquals("Wrong smart sql for range query spec", "SELECT {employees:_soup} FROM {employees} WHERE {employees:lastName} >= ? AND {employees:lastName} <= ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); } + @Test public void testRangeQuerySmartSqlWithSelectPaths() { QuerySpec querySpec = QuerySpec.buildRangeQuerySpec("employees", new String[] {"firstName"}, "lastName", "Bond", "Smith", "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong smart sql for range query spec", "SELECT {employees:firstName} FROM {employees} WHERE {employees:lastName} >= ? AND {employees:lastName} <= ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); + Assert.assertEquals("Wrong smart sql for range query spec", "SELECT {employees:firstName} FROM {employees} WHERE {employees:lastName} >= ? AND {employees:lastName} <= ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); } + @Test public void testRangeQueryCountSmartSql() { QuerySpec querySpec = QuerySpec.buildRangeQuerySpec("employees", "lastName", "Bond", "Smith", "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong count smart sql for range query spec", "SELECT count(*) FROM {employees} WHERE {employees:lastName} >= ? AND {employees:lastName} <= ? ", querySpec.countSmartSql); + Assert.assertEquals("Wrong count smart sql for range query spec", "SELECT count(*) FROM {employees} WHERE {employees:lastName} >= ? AND {employees:lastName} <= ? ", querySpec.countSmartSql); } + @Test public void testRangeQueryIdsSmartSql() { QuerySpec querySpec = QuerySpec.buildRangeQuerySpec("employees", "lastName", "Bond", "Smith", "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong ids smart sql for range query spec", "SELECT id FROM {employees} WHERE {employees:lastName} >= ? AND {employees:lastName} <= ? ORDER BY {employees:lastName} ASC ", querySpec.idsSmartSql); + Assert.assertEquals("Wrong ids smart sql for range query spec", "SELECT id FROM {employees} WHERE {employees:lastName} >= ? AND {employees:lastName} <= ? ORDER BY {employees:lastName} ASC ", querySpec.idsSmartSql); } + @Test public void testExactQuerySmartSql() { QuerySpec querySpec = QuerySpec.buildExactQuerySpec("employees", "lastName", "Bond", "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong smart sql for exact query spec", "SELECT {employees:_soup} FROM {employees} WHERE {employees:lastName} = ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); + Assert.assertEquals("Wrong smart sql for exact query spec", "SELECT {employees:_soup} FROM {employees} WHERE {employees:lastName} = ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); } + @Test public void testExactQuerySmartSqlWithSelectPaths() { QuerySpec querySpec = QuerySpec.buildExactQuerySpec("employees", new String[]{"firstName", "lastName"}, "lastName", "Bond", "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong smart sql for exact query spec", "SELECT {employees:firstName}, {employees:lastName} FROM {employees} WHERE {employees:lastName} = ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); + Assert.assertEquals("Wrong smart sql for exact query spec", "SELECT {employees:firstName}, {employees:lastName} FROM {employees} WHERE {employees:lastName} = ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); } + @Test public void testExactQueryCountSmartSql() { QuerySpec querySpec = QuerySpec.buildExactQuerySpec("employees", "lastName", "Bond", "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong count smart sql for exact query spec", "SELECT count(*) FROM {employees} WHERE {employees:lastName} = ? ", querySpec.countSmartSql); + Assert.assertEquals("Wrong count smart sql for exact query spec", "SELECT count(*) FROM {employees} WHERE {employees:lastName} = ? ", querySpec.countSmartSql); } + @Test public void testExactQueryIdsSmartSql() { QuerySpec querySpec = QuerySpec.buildExactQuerySpec("employees", "lastName", "Bond", "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong ids smart sql for exact query spec", "SELECT id FROM {employees} WHERE {employees:lastName} = ? ORDER BY {employees:lastName} ASC ", querySpec.idsSmartSql); + Assert.assertEquals("Wrong ids smart sql for exact query spec", "SELECT id FROM {employees} WHERE {employees:lastName} = ? ORDER BY {employees:lastName} ASC ", querySpec.idsSmartSql); } + @Test public void testMatchQuerySmartSql() { QuerySpec querySpec = QuerySpec.buildMatchQuerySpec("employees", "lastName", "Bond", "firstName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong smart sql for match query spec", "SELECT {employees:_soup} FROM {employees} WHERE {employees:_soupEntryId} IN (SELECT rowid FROM {employees}_fts WHERE {employees}_fts MATCH '{employees:lastName}:Bond') ORDER BY {employees:firstName} ASC ", querySpec.smartSql); + Assert.assertEquals("Wrong smart sql for match query spec", "SELECT {employees:_soup} FROM {employees} WHERE {employees:_soupEntryId} IN (SELECT rowid FROM {employees}_fts WHERE {employees}_fts MATCH '{employees:lastName}:Bond') ORDER BY {employees:firstName} ASC ", querySpec.smartSql); } + @Test public void testMatchQuerySmartSqlWithSelectPaths() { QuerySpec querySpec = QuerySpec.buildMatchQuerySpec("employees", new String[]{"firstName", "lastName", "title"}, "lastName", "Bond", "firstName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong smart sql for match query spec", "SELECT {employees:firstName}, {employees:lastName}, {employees:title} FROM {employees} WHERE {employees:_soupEntryId} IN (SELECT rowid FROM {employees}_fts WHERE {employees}_fts MATCH '{employees:lastName}:Bond') ORDER BY {employees:firstName} ASC ", querySpec.smartSql); + Assert.assertEquals("Wrong smart sql for match query spec", "SELECT {employees:firstName}, {employees:lastName}, {employees:title} FROM {employees} WHERE {employees:_soupEntryId} IN (SELECT rowid FROM {employees}_fts WHERE {employees}_fts MATCH '{employees:lastName}:Bond') ORDER BY {employees:firstName} ASC ", querySpec.smartSql); } + @Test public void testMatchQueryCountSmartSql() { QuerySpec querySpec = QuerySpec.buildMatchQuerySpec("employees", "lastName", "Bond", "firstName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong count smart sql for match query spec", "SELECT count(*) FROM {employees} WHERE {employees:_soupEntryId} IN (SELECT rowid FROM {employees}_fts WHERE {employees}_fts MATCH '{employees:lastName}:Bond') ", querySpec.countSmartSql); + Assert.assertEquals("Wrong count smart sql for match query spec", "SELECT count(*) FROM {employees} WHERE {employees:_soupEntryId} IN (SELECT rowid FROM {employees}_fts WHERE {employees}_fts MATCH '{employees:lastName}:Bond') ", querySpec.countSmartSql); } + @Test public void testMatchQueryIdsSmartSql() { QuerySpec querySpec = QuerySpec.buildMatchQuerySpec("employees", "lastName", "Bond", "firstName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong ids smart sql for match query spec", "SELECT id FROM {employees} WHERE {employees:_soupEntryId} IN (SELECT rowid FROM {employees}_fts WHERE {employees}_fts MATCH '{employees:lastName}:Bond') ORDER BY {employees:firstName} ASC ", querySpec.idsSmartSql); + Assert.assertEquals("Wrong ids smart sql for match query spec", "SELECT id FROM {employees} WHERE {employees:_soupEntryId} IN (SELECT rowid FROM {employees}_fts WHERE {employees}_fts MATCH '{employees:lastName}:Bond') ORDER BY {employees:firstName} ASC ", querySpec.idsSmartSql); } + @Test public void testLikeQuerySmartSql() { QuerySpec querySpec = QuerySpec.buildLikeQuerySpec("employees", "lastName", "Bon%" , "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong smart sql for like query spec", "SELECT {employees:_soup} FROM {employees} WHERE {employees:lastName} LIKE ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); + Assert.assertEquals("Wrong smart sql for like query spec", "SELECT {employees:_soup} FROM {employees} WHERE {employees:lastName} LIKE ? ORDER BY {employees:lastName} ASC ", querySpec.smartSql); } + @Test public void testLikeQueryCountSmartSql() { QuerySpec querySpec = QuerySpec.buildLikeQuerySpec("employees", "lastName", "Bon%" , "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong count smart sql for like query spec", "SELECT count(*) FROM {employees} WHERE {employees:lastName} LIKE ? ", querySpec.countSmartSql); + Assert.assertEquals("Wrong count smart sql for like query spec", "SELECT count(*) FROM {employees} WHERE {employees:lastName} LIKE ? ", querySpec.countSmartSql); } + @Test public void testLikeQueryIdsSmartSql() { QuerySpec querySpec = QuerySpec.buildLikeQuerySpec("employees", "lastName", "Bon%" , "lastName", QuerySpec.Order.ascending, 1); - assertEquals("Wrong ids smart sql for like query spec", "SELECT id FROM {employees} WHERE {employees:lastName} LIKE ? ORDER BY {employees:lastName} ASC ", querySpec.idsSmartSql); + Assert.assertEquals("Wrong ids smart sql for like query spec", "SELECT id FROM {employees} WHERE {employees:lastName} LIKE ? ORDER BY {employees:lastName} ASC ", querySpec.idsSmartSql); } + @Test public void testSmartQueryCountSmartSql() { QuerySpec querySpec = QuerySpec.buildSmartQuerySpec("select {employees:salary} from {employees} where {employees:lastName} = 'Haas'", 1); - assertEquals("Wrong count smart sql", "SELECT count(*) FROM (select {employees:salary} from {employees} where {employees:lastName} = 'Haas')", querySpec.countSmartSql); + Assert.assertEquals("Wrong count smart sql", "SELECT count(*) FROM (select {employees:salary} from {employees} where {employees:lastName} = 'Haas')", querySpec.countSmartSql); } + @Test public void testSmartQueryIdsSmartSql() { QuerySpec querySpec = QuerySpec.buildSmartQuerySpec("select {employees:salary} from {employees} where {employees:lastName} = 'Haas'", 1); - assertEquals("Wrong ids smart sql", "SELECT id FROM (select {employees:salary} from {employees} where {employees:lastName} = 'Haas')", querySpec.idsSmartSql); + Assert.assertEquals("Wrong ids smart sql", "SELECT id FROM (select {employees:salary} from {employees} where {employees:lastName} = 'Haas')", querySpec.idsSmartSql); } + @Test public void testQualifyMatchKey() { - assertEquals("Wrong qualified match query", "abc", QuerySpec.qualifyMatchKey(null, "abc")); - assertEquals("Wrong qualified match query", "{soup:path}:abc", QuerySpec.qualifyMatchKey("{soup:path}", "abc")); - assertEquals("Wrong qualified match query", "{soup:path2}:abc", QuerySpec.qualifyMatchKey("{soup:path1}", "{soup:path2}:abc")); - assertEquals("Wrong qualified match query", "{soup:path}:abc AND {soup:path}:def", QuerySpec.qualifyMatchKey("{soup:path}", "abc AND def")); - assertEquals("Wrong qualified match query", "{soup:path}:abc OR {soup:path}:def", QuerySpec.qualifyMatchKey("{soup:path}", "abc OR def")); - assertEquals("Wrong qualified match query", "{soup:path1}:abc OR {soup:path2}:def", QuerySpec.qualifyMatchKey("{soup:path1}", "abc OR {soup:path2}:def")); - assertEquals("Wrong qualified match query", "({soup:path}:abc AND {soup:path}:def) OR {soup:path}:ghi", QuerySpec.qualifyMatchKey("{soup:path}", "(abc AND def) OR ghi")); - assertEquals("Wrong qualified match query", "({soup:path1}:abc AND {soup:path2}:def) OR {soup:path1}:ghi", QuerySpec.qualifyMatchKey("{soup:path1}", "(abc AND {soup:path2}:def) OR ghi")); + Assert.assertEquals("Wrong qualified match query", "abc", QuerySpec.qualifyMatchKey(null, "abc")); + Assert.assertEquals("Wrong qualified match query", "{soup:path}:abc", QuerySpec.qualifyMatchKey("{soup:path}", "abc")); + Assert.assertEquals("Wrong qualified match query", "{soup:path2}:abc", QuerySpec.qualifyMatchKey("{soup:path1}", "{soup:path2}:abc")); + Assert.assertEquals("Wrong qualified match query", "{soup:path}:abc AND {soup:path}:def", QuerySpec.qualifyMatchKey("{soup:path}", "abc AND def")); + Assert.assertEquals("Wrong qualified match query", "{soup:path}:abc OR {soup:path}:def", QuerySpec.qualifyMatchKey("{soup:path}", "abc OR def")); + Assert.assertEquals("Wrong qualified match query", "{soup:path1}:abc OR {soup:path2}:def", QuerySpec.qualifyMatchKey("{soup:path1}", "abc OR {soup:path2}:def")); + Assert.assertEquals("Wrong qualified match query", "({soup:path}:abc AND {soup:path}:def) OR {soup:path}:ghi", QuerySpec.qualifyMatchKey("{soup:path}", "(abc AND def) OR ghi")); + Assert.assertEquals("Wrong qualified match query", "({soup:path1}:abc AND {soup:path2}:def) OR {soup:path1}:ghi", QuerySpec.qualifyMatchKey("{soup:path1}", "(abc AND {soup:path2}:def) OR ghi")); } } diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartSqlExternalStorageTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartSqlExternalStorageTest.java index 0253d8b17a..e2bec11823 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartSqlExternalStorageTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartSqlExternalStorageTest.java @@ -26,9 +26,8 @@ */ package com.salesforce.androidsdk.store; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import com.salesforce.androidsdk.analytics.security.Encryptor; import com.salesforce.androidsdk.smartstore.store.IndexSpec; @@ -39,10 +38,21 @@ import com.salesforce.androidsdk.smartstore.store.SoupSpec; import com.salesforce.androidsdk.util.test.JSONTestHelper; +import junit.framework.Assert; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + /** * Tests for "smart" sql - * */ +@RunWith(AndroidJUnit4.class) +@SmallTest public class SmartSqlExternalStorageTest extends SmartStoreTestCase { private static final String BUDGET = "budget"; @@ -61,10 +71,9 @@ protected String getEncryptionKey() { return Encryptor.hash("test123", "hashing-key"); } - @Override + @Before public void setUp() throws Exception { super.setUp(); - registerSoup(store, EMPLOYEES_SOUP, new IndexSpec[] { // should be TABLE_1 new IndexSpec(FIRST_NAME, Type.string), // should be TABLE_1_0 new IndexSpec(LAST_NAME, Type.string), // should be TABLE_1_1 @@ -72,21 +81,26 @@ public void setUp() throws Exception { new IndexSpec(EMPLOYEE_ID, Type.string), // should be TABLE_1_3 new IndexSpec(MANAGER_ID, Type.string), // should be TABLE_1_4 new IndexSpec(SALARY, Type.integer)}); // should be TABLE_1_5 - registerSoup(store, DEPARTMENTS_SOUP, new IndexSpec[] { // should be TABLE_2 new IndexSpec(DEPT_CODE, Type.string), // should be TABLE_2_0 new IndexSpec(NAME, Type.string), // should be TABLE_2_1 new IndexSpec(BUDGET, Type.integer)}); // should be TABLE_2_2 } + @After + public void tearDown() throws Exception { + super.tearDown(); + } + /** * Testing simple smart sql to sql conversion */ + @Test public void testSimpleConvertSmartSql() { - assertEquals("select TABLE_1_0, TABLE_1_1 from TABLE_1 order by TABLE_1_1", + Assert.assertEquals("select TABLE_1_0, TABLE_1_1 from TABLE_1 order by TABLE_1_1", store.convertSmartSql("select {employees:firstName}, {employees:lastName} from {employees} order by {employees:lastName}")); - assertEquals("select TABLE_2_1 from TABLE_2 order by TABLE_2_0", + Assert.assertEquals("select TABLE_2_1 from TABLE_2 order by TABLE_2_0", store.convertSmartSql("select {departments:name} from {departments} order by {departments:deptCode}")); } @@ -94,8 +108,9 @@ public void testSimpleConvertSmartSql() { /** * Testing smart sql to sql conversion when there is a join */ + @Test public void testConvertSmartSqlWithJoin() { - assertEquals("select TABLE_2_1, TABLE_1_0 || ' ' || TABLE_1_1 " + Assert.assertEquals("select TABLE_2_1, TABLE_1_0 || ' ' || TABLE_1_1 " + "from TABLE_1, TABLE_2 " + "where TABLE_2_0 = TABLE_1_2 " + "order by TABLE_2_1, TABLE_1_1", @@ -109,8 +124,9 @@ public void testConvertSmartSqlWithJoin() { /** * Testing smart sql to sql conversion when there is a self join */ + @Test public void testConvertSmartSqlWithSelfJoin() { - assertEquals("select mgr.TABLE_1_1, e.TABLE_1_1 " + Assert.assertEquals("select mgr.TABLE_1_1, e.TABLE_1_1 " + "from TABLE_1 as mgr, TABLE_1 as e " + "where mgr.TABLE_1_3 = e.TABLE_1_4", store.convertSmartSql("select mgr.{employees:lastName}, e.{employees:lastName} " @@ -122,35 +138,39 @@ public void testConvertSmartSqlWithSelfJoin() { * Testing smart sql to sql conversion when path is: _soup, _soupEntryId or _soupLastModifiedDate * Since this has external storage enabled, _soup column is replaced with value of soup name and soup entry id */ + @Test public void testConvertSmartSqlWithSpecialColumns() { - assertEquals("select TABLE_1.id, TABLE_1.lastModified, 'TABLE_1' as 'externalStorage', TABLE_1.id as '_soupEntryId' from TABLE_1", + Assert.assertEquals("select TABLE_1.id, TABLE_1.lastModified, 'TABLE_1' as 'externalStorage', TABLE_1.id as '_soupEntryId' from TABLE_1", store.convertSmartSql("select {employees:_soupEntryId}, {employees:_soupLastModifiedDate}, {employees:_soup} from {employees}")); } /** * Testing smart sql to sql conversion when path is: _soup, _soupEntryId or _soupLastModifiedDate and there is a join */ + @Test public void testConvertSmartSqlWithSpecialColumnsAndJoin() { - assertEquals("select TABLE_1.id, TABLE_2.id from TABLE_1, TABLE_2", + Assert.assertEquals("select TABLE_1.id, TABLE_2.id from TABLE_1, TABLE_2", store.convertSmartSql("select {employees:_soupEntryId}, {departments:_soupEntryId} from {employees}, {departments}")); } /** * Testing smart sql to sql conversion when path is: _soup, _soupEntryId or _soupLastModifiedDate and there is a join */ + @Test public void testConvertSmartSqlWithSpecialColumnsAndSelfJoin() { - assertEquals("select mgr.id, e.id from TABLE_1 as mgr, TABLE_1 as e", + Assert.assertEquals("select mgr.id, e.id from TABLE_1 as mgr, TABLE_1 as e", store.convertSmartSql("select mgr.{employees:_soupEntryId}, e.{employees:_soupEntryId} from {employees} as mgr, {employees} as e")); } /** * Test smart sql to sql conversation with insert/update/delete: expect exception */ + @Test public void testConvertSmartSqlWithInsertUpdateDelete() { for (String smartSql : new String[] { "insert into {employees}", "update {employees}", "delete from {employees}"}) { try { store.convertSmartSql(smartSql); - fail("Should have thrown exception for " + smartSql); + Assert.fail("Should have thrown exception for " + smartSql); } catch (SmartSqlException e) { // Expected @@ -162,6 +182,7 @@ public void testConvertSmartSqlWithInsertUpdateDelete() { * Test running smart query that does a select count * @throws JSONException */ + @Test public void testSmartQueryDoingCount() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select count(*) from {employees}", 1), 0); @@ -172,6 +193,7 @@ public void testSmartQueryDoingCount() throws JSONException { * Test running smart query that does a select sum * @throws JSONException */ + @Test public void testSmartQueryDoingSum() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select sum({departments:budget}) from {departments}", 1), 0); @@ -182,6 +204,7 @@ public void testSmartQueryDoingSum() throws JSONException { * Test running smart query that return one row with one integer * @throws JSONException */ + @Test public void testSmartQueryReturningOneRowWithOneInteger() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select {employees:salary} from {employees} where {employees:lastName} = 'Haas'", 1), 0); @@ -192,6 +215,7 @@ public void testSmartQueryReturningOneRowWithOneInteger() throws JSONException { * Test running smart query that return one row with two integers * @throws JSONException */ + @Test public void testSmartQueryReturningOneRowWithTwoIntegers() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select mgr.{employees:salary}, e.{employees:salary} from {employees} as mgr, {employees} as e where e.{employees:lastName} = 'Thompson' and mgr.{employees:employeeId} = e.{employees:managerId}", 1), 0); @@ -202,6 +226,7 @@ public void testSmartQueryReturningOneRowWithTwoIntegers() throws JSONException * Test running smart query that return two rows with one integer each * @throws JSONException */ + @Test public void testSmartQueryReturningTwoRowsWithOneIntegerEach() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select {employees:salary} from {employees} where {employees:managerId} = '00010' order by {employees:firstName}", 2), 0); @@ -212,27 +237,27 @@ public void testSmartQueryReturningTwoRowsWithOneIntegerEach() throws JSONExcept * Test running smart query that return a soup along with a string and an integer * @throws JSONException */ + @Test public void testSmartQueryReturningSoupStringAndInteger() throws JSONException { loadData(); JSONObject christineJson = store.query(QuerySpec.buildExactQuerySpec(EMPLOYEES_SOUP, "employeeId", "00010", null, null, 1), 0).getJSONObject(0); - assertEquals("Wrong elt", "Christine", christineJson.getString(FIRST_NAME)); - + Assert.assertEquals("Wrong elt", "Christine", christineJson.getString(FIRST_NAME)); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select {employees:_soup}, {employees:firstName}, {employees:salary} from {employees} where {employees:lastName} = 'Haas'", 1) , 0); - assertEquals("Expected one row", 1, result.length()); + Assert.assertEquals("Expected one row", 1, result.length()); JSONTestHelper.assertSameJSON("Wrong soup", christineJson, result.getJSONArray(0).getJSONObject(0)); - assertEquals("Wrong first name", "Christine", result.getJSONArray(0).getString(1)); - assertEquals("Wrong salary", 200000, result.getJSONArray(0).getInt(2)); + Assert.assertEquals("Wrong first name", "Christine", result.getJSONArray(0).getString(1)); + Assert.assertEquals("Wrong salary", 200000, result.getJSONArray(0).getInt(2)); } /** * Test running smart query with paging * @throws JSONException */ + @Test public void testSmartQueryWithPaging() throws JSONException { loadData(); QuerySpec query = QuerySpec.buildSmartQuerySpec("select {employees:firstName} from {employees} order by {employees:firstName}", 1); - assertEquals("Expected 7 employees", 7, store.countQuery(query)); - + Assert.assertEquals("Expected 7 employees", 7, store.countQuery(query)); String[] expectedResults = new String[] {"Christine", "Eileen", "Eva", "Irving", "John", "Michael", "Sally"}; for (int i = 0; i<7; i++) { JSONArray result = store.query(query , i); @@ -244,25 +269,24 @@ public void testSmartQueryWithPaging() throws JSONException { * Test running smart query that targets _soup, _soupEntryId and _soupLastModifiedDate * @throws JSONException */ + @Test public void testSmartQueryWithSpecialFields() throws JSONException { loadData(); - JSONObject christineJson = store.query(QuerySpec.buildExactQuerySpec(EMPLOYEES_SOUP, "employeeId", "00010", null, null, 1), 0).getJSONObject(0); - assertEquals("Wrong elt", "Christine", christineJson.getString(FIRST_NAME)); - + Assert.assertEquals("Wrong elt", "Christine", christineJson.getString(FIRST_NAME)); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select {employees:_soup}, {employees:_soupEntryId}, {employees:_soupLastModifiedDate}, {employees:salary} from {employees} where {employees:lastName} = 'Haas'", 1) , 0); - assertEquals("Expected one row", 1, result.length()); + Assert.assertEquals("Expected one row", 1, result.length()); JSONTestHelper.assertSameJSON("Wrong soup", christineJson, result.getJSONArray(0).getJSONObject(0)); JSONTestHelper.assertSameJSON("Wrong soupEntryId", christineJson.getString(SmartStore.SOUP_ENTRY_ID), result.getJSONArray(0).getInt(1)); JSONTestHelper.assertSameJSON("Wrong soupLastModifiedDate", christineJson.getString(SmartStore.SOUP_LAST_MODIFIED_DATE), result.getJSONArray(0).getLong(2)); } - /** * Load some datq in the smart store * @throws JSONException */ private void loadData() throws JSONException { + // Employees createEmployee("Christine", "Haas", "A00", "00010", null, 200000); createEmployee("Michael", "Thompson", "A00", "00020", "00010", 120000); diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartSqlTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartSqlTest.java index f45547f866..c880b3dbff 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartSqlTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartSqlTest.java @@ -26,9 +26,8 @@ */ package com.salesforce.androidsdk.store; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; import com.salesforce.androidsdk.smartstore.store.IndexSpec; import com.salesforce.androidsdk.smartstore.store.QuerySpec; @@ -37,10 +36,21 @@ import com.salesforce.androidsdk.smartstore.store.SmartStore.Type; import com.salesforce.androidsdk.util.test.JSONTestHelper; +import junit.framework.Assert; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + /** * Tests for "smart" sql - * */ +@RunWith(AndroidJUnit4.class) +@MediumTest public class SmartSqlTest extends SmartStoreTestCase { private static final String BUDGET = "budget"; @@ -61,10 +71,9 @@ protected String getEncryptionKey() { return ""; } - @Override + @Before public void setUp() throws Exception { super.setUp(); - store.registerSoup(EMPLOYEES_SOUP, new IndexSpec[] { // should be TABLE_1 new IndexSpec(FIRST_NAME, Type.string), // should be TABLE_1_0 new IndexSpec(LAST_NAME, Type.string), // should be TABLE_1_1 @@ -73,23 +82,26 @@ public void setUp() throws Exception { new IndexSpec(MANAGER_ID, Type.string), // should be TABLE_1_4 new IndexSpec(SALARY, Type.integer), // should be TABLE_1_5 new IndexSpec(EDUCATION, Type.json1)}); - - store.registerSoup(DEPARTMENTS_SOUP, new IndexSpec[] { // should be TABLE_2 new IndexSpec(DEPT_CODE, Type.string), // should be TABLE_2_0 new IndexSpec(NAME, Type.string), // should be TABLE_2_1 new IndexSpec(BUDGET, Type.integer), // should be TABLE_2_2 new IndexSpec(BUILDING, Type.json1)}); } - + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + /** * Testing simple smart sql to sql conversion */ + @Test public void testSimpleConvertSmartSql() { - assertEquals("select TABLE_1_0, TABLE_1_1 from TABLE_1 order by TABLE_1_1", + Assert.assertEquals("select TABLE_1_0, TABLE_1_1 from TABLE_1 order by TABLE_1_1", store.convertSmartSql("select {employees:firstName}, {employees:lastName} from {employees} order by {employees:lastName}")); - - assertEquals("select TABLE_2_1 from TABLE_2 order by TABLE_2_0", + Assert.assertEquals("select TABLE_2_1 from TABLE_2 order by TABLE_2_0", store.convertSmartSql("select {departments:name} from {departments} order by {departments:deptCode}")); } @@ -97,8 +109,9 @@ public void testSimpleConvertSmartSql() { /** * Testing smart sql to sql conversion when there is a join */ + @Test public void testConvertSmartSqlWithJoin() { - assertEquals("select TABLE_2_1, TABLE_1_0 || ' ' || TABLE_1_1 " + Assert.assertEquals("select TABLE_2_1, TABLE_1_0 || ' ' || TABLE_1_1 " + "from TABLE_1, TABLE_2 " + "where TABLE_2_0 = TABLE_1_2 " + "order by TABLE_2_1, TABLE_1_1", @@ -112,8 +125,9 @@ public void testConvertSmartSqlWithJoin() { /** * Testing smart sql to sql conversion when there is a self join */ + @Test public void testConvertSmartSqlWithSelfJoin() { - assertEquals("select mgr.TABLE_1_1, e.TABLE_1_1 " + Assert.assertEquals("select mgr.TABLE_1_1, e.TABLE_1_1 " + "from TABLE_1 as mgr, TABLE_1 as e " + "where mgr.TABLE_1_3 = e.TABLE_1_4", store.convertSmartSql("select mgr.{employees:lastName}, e.{employees:lastName} " @@ -124,35 +138,39 @@ public void testConvertSmartSqlWithSelfJoin() { /** * Testing smart sql to sql conversion when path is: _soup, _soupEntryId or _soupLastModifiedDate */ + @Test public void testConvertSmartSqlWithSpecialColumns() { - assertEquals("select TABLE_1.id, TABLE_1.created, TABLE_1.lastModified, TABLE_1.soup from TABLE_1", + Assert.assertEquals("select TABLE_1.id, TABLE_1.created, TABLE_1.lastModified, TABLE_1.soup from TABLE_1", store.convertSmartSql("select {employees:_soupEntryId}, {employees:_soupCreatedDate}, {employees:_soupLastModifiedDate}, {employees:_soup} from {employees}")); } /** * Testing smart sql to sql conversion when path is: _soup, _soupEntryId or _soupLastModifiedDate and there is a join */ + @Test public void testConvertSmartSqlWithSpecialColumnsAndJoin() { - assertEquals("select TABLE_1.id, TABLE_2.id from TABLE_1, TABLE_2", + Assert.assertEquals("select TABLE_1.id, TABLE_2.id from TABLE_1, TABLE_2", store.convertSmartSql("select {employees:_soupEntryId}, {departments:_soupEntryId} from {employees}, {departments}")); } /** * Testing smart sql to sql conversion when path is: _soup, _soupEntryId or _soupLastModifiedDate and there is a join */ + @Test public void testConvertSmartSqlWithSpecialColumnsAndSelfJoin() { - assertEquals("select mgr.id, e.id from TABLE_1 as mgr, TABLE_1 as e", + Assert.assertEquals("select mgr.id, e.id from TABLE_1 as mgr, TABLE_1 as e", store.convertSmartSql("select mgr.{employees:_soupEntryId}, e.{employees:_soupEntryId} from {employees} as mgr, {employees} as e")); } /** * Test smart sql to sql conversation with insert/update/delete: expect exception */ + @Test public void testConvertSmartSqlWithInsertUpdateDelete() { for (String smartSql : new String[] { "insert into {employees}", "update {employees}", "delete from {employees}"}) { try { store.convertSmartSql(smartSql); - fail("Should have thrown exception for " + smartSql); + Assert.fail("Should have thrown exception for " + smartSql); } catch (SmartSqlException e) { // Expected @@ -160,18 +178,21 @@ public void testConvertSmartSqlWithInsertUpdateDelete() { } } + @Test public void testConvertSmartSqlWithJSON1() { - assertEquals("select TABLE_1_1, json_extract(soup, '$.education') from TABLE_1 where json_extract(soup, '$.education') = 'MIT'", + Assert.assertEquals("select TABLE_1_1, json_extract(soup, '$.education') from TABLE_1 where json_extract(soup, '$.education') = 'MIT'", store.convertSmartSql("select {employees:lastName}, {employees:education} from {employees} where {employees:education} = 'MIT'")); } + @Test public void testConvertSmartSqlWithJSON1AndTableQualifiedColumn() { - assertEquals("select json_extract(TABLE_1.soup, '$.education') from TABLE_1 order by json_extract(TABLE_1.soup, '$.education')", + Assert.assertEquals("select json_extract(TABLE_1.soup, '$.education') from TABLE_1 order by json_extract(TABLE_1.soup, '$.education')", store.convertSmartSql("select {employees}.{employees:education} from {employees} order by {employees}.{employees:education}")); } + @Test public void testConvertSmartSqlWithJSON1AndTableAliases() { - assertEquals("select json_extract(e.soup, '$.education'), json_extract(soup, '$.building') from TABLE_1 as e, TABLE_2", + Assert.assertEquals("select json_extract(e.soup, '$.education'), json_extract(soup, '$.building') from TABLE_1 as e, TABLE_2", store.convertSmartSql("select e.{employees:education}, {departments:building} from {employees} as e, {departments}")); // XXX join query with json1 will only run if all the json1 columns are qualified by table or alias @@ -181,6 +202,7 @@ public void testConvertSmartSqlWithJSON1AndTableAliases() { * Test running smart query that does a select count * @throws JSONException */ + @Test public void testSmartQueryDoingCount() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select count(*) from {employees}", 1), 0); @@ -191,6 +213,7 @@ public void testSmartQueryDoingCount() throws JSONException { * Test running smart query that does a select sum * @throws JSONException */ + @Test public void testSmartQueryDoingSum() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select sum({departments:budget}) from {departments}", 1), 0); @@ -201,6 +224,7 @@ public void testSmartQueryDoingSum() throws JSONException { * Test running smart query that return one row with one integer * @throws JSONException */ + @Test public void testSmartQueryReturningOneRowWithOneInteger() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select {employees:salary} from {employees} where {employees:lastName} = 'Haas'", 1), 0); @@ -211,6 +235,7 @@ public void testSmartQueryReturningOneRowWithOneInteger() throws JSONException { * Test running smart query that return one row with two integers * @throws JSONException */ + @Test public void testSmartQueryReturningOneRowWithTwoIntegers() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select mgr.{employees:salary}, e.{employees:salary} from {employees} as mgr, {employees} as e where e.{employees:lastName} = 'Thompson' and mgr.{employees:employeeId} = e.{employees:managerId}", 1), 0); @@ -221,6 +246,7 @@ public void testSmartQueryReturningOneRowWithTwoIntegers() throws JSONException * Test running smart query that return two rows with one integer each * @throws JSONException */ + @Test public void testSmartQueryReturningTwoRowsWithOneIntegerEach() throws JSONException { loadData(); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select {employees:salary} from {employees} where {employees:managerId} = '00010' order by {employees:firstName}", 2), 0); @@ -231,27 +257,27 @@ public void testSmartQueryReturningTwoRowsWithOneIntegerEach() throws JSONExcept * Test running smart query that return a soup along with a string and an integer * @throws JSONException */ + @Test public void testSmartQueryReturningSoupStringAndInteger() throws JSONException { loadData(); JSONObject christineJson = store.query(QuerySpec.buildExactQuerySpec(EMPLOYEES_SOUP, "employeeId", "00010", null, null, 1), 0).getJSONObject(0); - assertEquals("Wrong elt", "Christine", christineJson.getString(FIRST_NAME)); - + Assert.assertEquals("Wrong elt", "Christine", christineJson.getString(FIRST_NAME)); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select {employees:_soup}, {employees:firstName}, {employees:salary} from {employees} where {employees:lastName} = 'Haas'", 1) , 0); - assertEquals("Expected one row", 1, result.length()); + Assert.assertEquals("Expected one row", 1, result.length()); JSONTestHelper.assertSameJSON("Wrong soup", christineJson, result.getJSONArray(0).getJSONObject(0)); - assertEquals("Wrong first name", "Christine", result.getJSONArray(0).getString(1)); - assertEquals("Wrong salary", 200000, result.getJSONArray(0).getInt(2)); + Assert.assertEquals("Wrong first name", "Christine", result.getJSONArray(0).getString(1)); + Assert.assertEquals("Wrong salary", 200000, result.getJSONArray(0).getInt(2)); } /** * Test running smart query with paging * @throws JSONException */ + @Test public void testSmartQueryWithPaging() throws JSONException { loadData(); QuerySpec query = QuerySpec.buildSmartQuerySpec("select {employees:firstName} from {employees} order by {employees:firstName}", 1); - assertEquals("Expected 7 employees", 7, store.countQuery(query)); - + Assert.assertEquals("Expected 7 employees", 7, store.countQuery(query)); String[] expectedResults = new String[] {"Christine", "Eileen", "Eva", "Irving", "John", "Michael", "Sally"}; for (int i = 0; i<7; i++) { JSONArray result = store.query(query , i); @@ -263,25 +289,24 @@ public void testSmartQueryWithPaging() throws JSONException { * Test running smart query that targets _soup, _soupEntryId and _soupLastModifiedDate * @throws JSONException */ + @Test public void testSmartQueryWithSpecialFields() throws JSONException { loadData(); - JSONObject christineJson = store.query(QuerySpec.buildExactQuerySpec(EMPLOYEES_SOUP, "employeeId", "00010", null, null, 1), 0).getJSONObject(0); - assertEquals("Wrong elt", "Christine", christineJson.getString(FIRST_NAME)); - + Assert.assertEquals("Wrong elt", "Christine", christineJson.getString(FIRST_NAME)); JSONArray result = store.query(QuerySpec.buildSmartQuerySpec("select {employees:_soup}, {employees:_soupEntryId}, {employees:_soupLastModifiedDate}, {employees:salary} from {employees} where {employees:lastName} = 'Haas'", 1) , 0); - assertEquals("Expected one row", 1, result.length()); + Assert.assertEquals("Expected one row", 1, result.length()); JSONTestHelper.assertSameJSON("Wrong soup", christineJson, result.getJSONArray(0).getJSONObject(0)); JSONTestHelper.assertSameJSON("Wrong soupEntryId", christineJson.getString(SmartStore.SOUP_ENTRY_ID), result.getJSONArray(0).getInt(1)); JSONTestHelper.assertSameJSON("Wrong soupLastModifiedDate", christineJson.getString(SmartStore.SOUP_LAST_MODIFIED_DATE), result.getJSONArray(0).getLong(2)); } - /** * Load some datq in the smart store * @throws JSONException */ private void loadData() throws JSONException { + // Employees createEmployee("Christine", "Haas", "A00", "00010", null, 200000); createEmployee("Michael", "Thompson", "A00", "00020", "00010", 120000); @@ -315,5 +340,4 @@ private void createDepartment(String deptCode, String name, int budget) throws J department.put(BUDGET, budget); store.create(DEPARTMENTS_SOUP, department); } - } diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreAlterTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreAlterTest.java index c469f1fa86..4e05cc2991 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreAlterTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreAlterTest.java @@ -27,6 +27,8 @@ package com.salesforce.androidsdk.store; import android.database.Cursor; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import com.salesforce.androidsdk.smartstore.store.AlterSoupLongOperation; import com.salesforce.androidsdk.smartstore.store.DBHelper; @@ -38,11 +40,17 @@ import com.salesforce.androidsdk.smartstore.store.SoupSpec; import com.salesforce.androidsdk.util.test.JSONTestHelper; +import junit.framework.Assert; + import net.sqlcipher.database.SQLiteDatabase; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Arrays; @@ -51,6 +59,8 @@ /** * Tests to compare speed of smartstore full-text-search indices with regular indices */ +@RunWith(AndroidJUnit4.class) +@LargeTest public class SmartStoreAlterTest extends SmartStoreTestCase { private static final String TEST_SOUP = "test_soup"; @@ -64,15 +74,27 @@ public class SmartStoreAlterTest extends SmartStoreTestCase { private static final String USA = "United States"; private static final String FRANCE = "France"; + @Override protected String getEncryptionKey() { return ""; } + @Before + public void setUp() throws Exception { + super.setUp(); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + /** * Test for getSoupIndexSpecs * * @throws JSONException */ + @Test public void testGetSoupIndexSpecs() throws JSONException { IndexSpec[] indexSpecs = new IndexSpec[] { new IndexSpec("lastName", SmartStore.Type.string), @@ -82,11 +104,9 @@ public void testGetSoupIndexSpecs() throws JSONException { new IndexSpec("note", SmartStore.Type.full_text), new IndexSpec("other", SmartStore.Type.json1) }; - - assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); + Assert.assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); store.registerSoup(TEST_SOUP, indexSpecs); - assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); checkIndexSpecs(TEST_SOUP, new IndexSpec[] { new IndexSpec("lastName", SmartStore.Type.string, TEST_SOUP_TABLE_NAME + "_0"), new IndexSpec("address.city", SmartStore.Type.string, TEST_SOUP_TABLE_NAME + "_1"), @@ -102,6 +122,7 @@ public void testGetSoupIndexSpecs() throws JSONException { * * @throws JSONException */ + @Test public void testAlterSoupNoReIndexing() throws JSONException { alterSoupHelper(false); } @@ -111,6 +132,7 @@ public void testAlterSoupNoReIndexing() throws JSONException { * * @throws JSONException */ + @Test public void testAlterSoupWithReIndexing() throws JSONException { alterSoupHelper(true); } @@ -120,23 +142,21 @@ public void testAlterSoupWithReIndexing() throws JSONException { * * throws JSONException */ + @Test public void testAlterSoupTypeChangeStringToInteger() throws JSONException { IndexSpec[] indexSpecs = new IndexSpec[] {new IndexSpec("name", SmartStore.Type.string), new IndexSpec("population", SmartStore.Type.string)}; - - assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); + Assert.assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); store.registerSoup(TEST_SOUP, indexSpecs); - assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); JSONObject soupElt1 = new JSONObject("{'name': 'San Francisco', 'population': 825863}"); JSONObject soupElt2 = new JSONObject("{'name': 'Paris', 'population': 2234105}"); - store.create(TEST_SOUP, soupElt1); store.create(TEST_SOUP, soupElt2); // Query all sorted by population ascending - we should get Paris first because we indexed population as a string JSONArray results = store.query(QuerySpec.buildAllQuerySpec(TEST_SOUP, "population", QuerySpec.Order.ascending, 2), 0); - assertEquals("Paris should be first", "Paris", results.getJSONObject(0).get("name")); - assertEquals("San Francisco should be second", "San Francisco", results.getJSONObject(1).get("name")); + Assert.assertEquals("Paris should be first", "Paris", results.getJSONObject(0).get("name")); + Assert.assertEquals("San Francisco should be second", "San Francisco", results.getJSONObject(1).get("name")); // Alter soup - index population as integer IndexSpec[] indexSpecsNew = new IndexSpec[] {new IndexSpec("name", SmartStore.Type.string), new IndexSpec("population", SmartStore.Type.integer)}; @@ -144,8 +164,8 @@ public void testAlterSoupTypeChangeStringToInteger() throws JSONException { // Query all sorted by population ascending - we should get San Francisco first because we indexed population as an integer JSONArray results2 = store.query(QuerySpec.buildAllQuerySpec(TEST_SOUP, "population", QuerySpec.Order.ascending, 2), 0); - assertEquals("San Francisco should be first", "San Francisco", results2.getJSONObject(0).get("name")); - assertEquals("Paris should be first", "Paris", results2.getJSONObject(1).get("name")); + Assert.assertEquals("San Francisco should be first", "San Francisco", results2.getJSONObject(0).get("name")); + Assert.assertEquals("Paris should be first", "Paris", results2.getJSONObject(1).get("name")); } /** @@ -153,6 +173,7 @@ public void testAlterSoupTypeChangeStringToInteger() throws JSONException { * * throws JSONException */ + @Test public void testAlterSoupTypeChangeStringToFullText() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.string, SmartStore.Type.full_text); } @@ -162,6 +183,7 @@ public void testAlterSoupTypeChangeStringToFullText() throws JSONException { * * throws JSONException */ + @Test public void testAlterSoupTypeChangeFullTextToString() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.full_text, SmartStore.Type.string); } @@ -171,6 +193,7 @@ public void testAlterSoupTypeChangeFullTextToString() throws JSONException { * * throws JSONException */ + @Test public void testAlterSoupTypeChangeStringToJSON1() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.string, SmartStore.Type.json1); } @@ -180,6 +203,7 @@ public void testAlterSoupTypeChangeStringToJSON1() throws JSONException { * * throws JSONException */ + @Test public void testAlterSoupTypeChangeJSON1toString() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.json1, SmartStore.Type.string); } @@ -189,6 +213,7 @@ public void testAlterSoupTypeChangeJSON1toString() throws JSONException { * * throws JSONException */ + @Test public void testAlterSoupTypeChangeFullTextToJSON1() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.full_text, SmartStore.Type.json1); } @@ -198,6 +223,7 @@ public void testAlterSoupTypeChangeFullTextToJSON1() throws JSONException { * * throws JSONException */ + @Test public void testAlterSoupTypeChangeJSON1toFullText() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.json1, SmartStore.Type.full_text); } @@ -207,6 +233,7 @@ public void testAlterSoupTypeChangeJSON1toFullText() throws JSONException { * Test for alterSoup with column type change from string to json1 * and storage goes from external to internal */ + @Test public void testAlterSoupTypeChangeStringToJSON1ExternalToInternal() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.string, SmartStore.Type.json1, false, true, true); } @@ -215,6 +242,7 @@ public void testAlterSoupTypeChangeStringToJSON1ExternalToInternal() throws JSON * Test for alterSoup with column type change from json1 to string * and storage change from internal to external */ + @Test public void testAlterSoupTypeChangeJSON1ToStringInternalToExternal() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.json1, SmartStore.Type.string, true, true, false); } @@ -223,6 +251,7 @@ public void testAlterSoupTypeChangeJSON1ToStringInternalToExternal() throws JSON * Test for alterSoup with column type change from string to full_text * and storage change from external to internal */ + @Test public void testAlterSoupTypeChangeStringToFullTextExternalToInternal() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.string, SmartStore.Type.full_text, false, true, true); } @@ -231,6 +260,7 @@ public void testAlterSoupTypeChangeStringToFullTextExternalToInternal() throws J * Test for alterSoup with column type change from full_text to string * and storage change from internal to external */ + @Test public void testAlterSoupTypeChangeFullTextToStringInternalToExternal() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.full_text, SmartStore.Type.string, true, true, false); } @@ -239,6 +269,7 @@ public void testAlterSoupTypeChangeFullTextToStringInternalToExternal() throws J * Test for alterSoup with string column * and storage change from internal to external to internal */ + @Test public void testAlterSoupStringInternalToExternalToInternal() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.string, SmartStore.Type.string, true, false, true); } @@ -247,6 +278,7 @@ public void testAlterSoupStringInternalToExternalToInternal() throws JSONExcepti * Test for alterSoup with full_text column * and storage change from internal to external to internal */ + @Test public void testAlterSoupFullTextInternalToExternalToInternal() throws JSONException { tryAlterSoupTypeChange(SmartStore.Type.full_text, SmartStore.Type.string, true, false, true); } @@ -256,6 +288,7 @@ public void testAlterSoupFullTextInternalToExternalToInternal() throws JSONExcep * Make sure db table / indexes are recreated * That way soup created before 4.2 can get the new indexes (create/lastModified) by calling alterSoup */ + @Test public void testAlterSoupWithStringIndexesToGetIndexesOnCreatedAndLastModified() throws JSONException{ tryAlterSoupToGetIndexesOnCreatedAndLastModified(SmartStore.Type.string); } @@ -265,6 +298,7 @@ public void testAlterSoupWithStringIndexesToGetIndexesOnCreatedAndLastModified() * Make sure db table / indexes are recreated * That way soup created before 4.2 can get the new indexes (create/lastModified) by calling alterSoup */ + @Test public void testAlterSoupWithJSON1IndexesToGetIndexesOnCreatedAndLastModified() throws JSONException { tryAlterSoupToGetIndexesOnCreatedAndLastModified(SmartStore.Type.json1); } @@ -274,6 +308,7 @@ public void testAlterSoupWithJSON1IndexesToGetIndexesOnCreatedAndLastModified() * Make sure db table / indexes are recreated * That way soup created before 4.2 can get the new indexes (create/lastModified) by calling alterSoup */ + @Test public void testAlterSoupWithFullTextIndexesToGetIndexesOnCreatedAndLastModified() throws JSONException { tryAlterSoupToGetIndexesOnCreatedAndLastModified(SmartStore.Type.full_text); } @@ -285,23 +320,21 @@ public void testAlterSoupWithFullTextIndexesToGetIndexesOnCreatedAndLastModified * That way soup created before 4.2 (using fts4 virutal table) can be migrated to fts5 by calling alterSoup * @throws JSONException */ + @Test public void testAlterSoupwithFullTextIndexesFromFts4ToFts5() throws JSONException { IndexSpec[] indexSpecs = new IndexSpec[] {new IndexSpec(CITY, SmartStore.Type.full_text), new IndexSpec(COUNTRY, SmartStore.Type.full_text)}; // Using fts4 to simulate pre 4.2 sdk store.setFtsExtension(SmartStore.FtsExtension.fts4); - - assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); + Assert.assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); store.registerSoup(TEST_SOUP, indexSpecs); - assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); JSONObject soupElt1 = new JSONObject(); soupElt1.put(CITY, SAN_FRANCISCO); soupElt1.put(COUNTRY, USA); JSONObject soupElt2 = new JSONObject(); soupElt2.put(CITY, PARIS); soupElt2.put(COUNTRY, FRANCE); - long elt1Id = idOf(store.create(TEST_SOUP, soupElt1)); long elt2Id = idOf(store.create(TEST_SOUP, soupElt2)); @@ -327,18 +360,15 @@ public void testAlterSoupwithFullTextIndexesFromFts4ToFts5() throws JSONExceptio private void tryAlterSoupToGetIndexesOnCreatedAndLastModified(SmartStore.Type indexType) throws JSONException { IndexSpec[] indexSpecs = new IndexSpec[]{new IndexSpec(CITY, indexType), new IndexSpec(COUNTRY, indexType)}; - - assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); + Assert.assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); store.registerSoup(TEST_SOUP, indexSpecs); - assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); JSONObject soupElt1 = new JSONObject(); soupElt1.put(CITY, SAN_FRANCISCO); soupElt1.put(COUNTRY, USA); JSONObject soupElt2 = new JSONObject(); soupElt2.put(CITY, PARIS); soupElt2.put(COUNTRY, FRANCE); - long elt1Id = idOf(store.create(TEST_SOUP, soupElt1)); long elt2Id = idOf(store.create(TEST_SOUP, soupElt2)); @@ -354,7 +384,6 @@ private void tryAlterSoupToGetIndexesOnCreatedAndLastModified(SmartStore.Type in // Check db indexes after the drop - created and lastModified should be gone String expectedCityCol = indexType == SmartStore.Type.json1 ? String.format("json_extract(soup, '$.%s')", CITY) : CITY_COL; String expectedCountryCol = indexType == SmartStore.Type.json1 ? String.format("json_extract(soup, '$.%s')", COUNTRY) : COUNTRY_COL; - checkDatabaseIndexes(TEST_SOUP_TABLE_NAME, Arrays.asList(new String[]{ "CREATE INDEX " + TEST_SOUP_TABLE_NAME + "_0_idx on " + TEST_SOUP_TABLE_NAME + " ( " + expectedCityCol + " )", "CREATE INDEX " + TEST_SOUP_TABLE_NAME + "_1_idx on " + TEST_SOUP_TABLE_NAME + " ( " + expectedCountryCol + " )", @@ -367,49 +396,23 @@ private void tryAlterSoupToGetIndexesOnCreatedAndLastModified(SmartStore.Type in checkDb(new long[]{elt1Id, elt2Id}, indexSpecs[0].type, indexSpecs[1].type); } - /** - * Start with country and city as fromType - * Alter soup to have country as toType - * Alter soup a second time to have city as toType - * - * Only use internal storage - * - * @param fromType - * @param toType - * @throws JSONException - */ - public void tryAlterSoupTypeChange(SmartStore.Type fromType, SmartStore.Type toType) throws JSONException { + private void tryAlterSoupTypeChange(SmartStore.Type fromType, SmartStore.Type toType) throws JSONException { tryAlterSoupTypeChange(fromType, toType, true, true, true); } - /** - * Start with soup with country and city as fromType and storage based on fromStorageInternal - * Alter soup to have country as toType and storage based on toStorageInternal - * Alter soup a second time to have city as toType and storage based on toStorageInternal2 - * - * @param fromType - * @param toType - * @param fromStorageInternal - * @param toStorageInternal - * @param toStorageInternal2 - * @throws JSONException - */ - public void tryAlterSoupTypeChange(SmartStore.Type fromType, SmartStore.Type toType, boolean fromStorageInternal, + private void tryAlterSoupTypeChange(SmartStore.Type fromType, SmartStore.Type toType, boolean fromStorageInternal, boolean toStorageInternal, boolean toStorageInternal2) throws JSONException { IndexSpec[] indexSpecs = new IndexSpec[] {new IndexSpec(CITY, fromType), new IndexSpec(COUNTRY, fromType)}; - - assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); + Assert.assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); SoupSpec soupSpec = fromStorageInternal ? new SoupSpec(TEST_SOUP) : new SoupSpec(TEST_SOUP, SoupSpec.FEATURE_EXTERNAL_STORAGE); store.registerSoupWithSpec(soupSpec, indexSpecs); - assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); JSONObject soupElt1 = new JSONObject(); soupElt1.put(CITY, SAN_FRANCISCO); soupElt1.put(COUNTRY, USA); JSONObject soupElt2 = new JSONObject(); soupElt2.put(CITY, PARIS); soupElt2.put(COUNTRY, FRANCE); - long elt1Id = idOf(store.create(TEST_SOUP, soupElt1)); long elt2Id = idOf(store.create(TEST_SOUP, soupElt2)); @@ -454,7 +457,6 @@ private void checkDb(long[] expectedIds, SmartStore.Type cityColType, SmartStore List expectedColumnNames = useInternalStorage ? new ArrayList<>(Arrays.asList("id", "soup", "created", "lastModified")) : new ArrayList<>(Arrays.asList("id", "created", "lastModified")); - if (cityColType != SmartStore.Type.json1) expectedColumnNames.add(CITY_COL); if (countryColType != SmartStore.Type.json1) expectedColumnNames.add(COUNTRY_COL); checkColumns(TEST_SOUP_TABLE_NAME, expectedColumnNames); @@ -478,15 +480,14 @@ private void checkDb(long[] expectedIds, SmartStore.Type cityColType, SmartStore try { final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); c = DBHelper.getInstance(db).query(db, TEST_SOUP_TABLE_NAME, expectedColumnNames.toArray(new String[0]), "id ASC", null, null); - assertTrue("Expected a row", c.moveToFirst()); - assertEquals("Wrong number of rows", expectedIds.length, c.getCount()); - + Assert.assertTrue("Expected a row", c.moveToFirst()); + Assert.assertEquals("Wrong number of rows", expectedIds.length, c.getCount()); for (int i = 0; i < expectedIds.length; i++) { - assertEquals("Wrong id", expectedIds[i], c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong id", expectedIds[i], c.getLong(c.getColumnIndex("id"))); if (cityColType != SmartStore.Type.json1) - assertEquals("Wrong value in index column", cities[i], c.getString(c.getColumnIndex(CITY_COL))); + Assert.assertEquals("Wrong value in index column", cities[i], c.getString(c.getColumnIndex(CITY_COL))); if (countryColType != SmartStore.Type.json1) - assertEquals("Wrong value in index column", countries[i], c.getString(c.getColumnIndex(COUNTRY_COL))); + Assert.assertEquals("Wrong value in index column", countries[i], c.getString(c.getColumnIndex(COUNTRY_COL))); c.moveToNext(); } } @@ -496,8 +497,7 @@ private void checkDb(long[] expectedIds, SmartStore.Type cityColType, SmartStore // Check fts table exists boolean hasFts = cityColType == SmartStore.Type.full_text || countryColType == SmartStore.Type.full_text; - assertEquals(hasFts, hasTable(TEST_SOUP_TABLE_NAME + SmartStore.FTS_SUFFIX)); - + Assert.assertEquals(hasFts, hasTable(TEST_SOUP_TABLE_NAME + SmartStore.FTS_SUFFIX)); if (!hasFts) { return; } @@ -513,19 +513,18 @@ private void checkDb(long[] expectedIds, SmartStore.Type cityColType, SmartStore final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); expectedFtsColumnNames.add(0, "rowid"); c = DBHelper.getInstance(db).query(db, TEST_SOUP_TABLE_NAME + SmartStore.FTS_SUFFIX, expectedFtsColumnNames.toArray(new String[0]), "rowid ASC", null, null); - assertTrue("Expected a row", c.moveToFirst()); - assertEquals("Wrong number of rows", expectedIds.length, c.getCount()); - + Assert.assertTrue("Expected a row", c.moveToFirst()); + Assert.assertEquals("Wrong number of rows", expectedIds.length, c.getCount()); for (int i = 0; i < expectedIds.length; i++) { - assertEquals("Wrong rowid", expectedIds[i], c.getLong(c.getColumnIndex("rowid"))); + Assert.assertEquals("Wrong rowid", expectedIds[i], c.getLong(c.getColumnIndex("rowid"))); if (cityColType == SmartStore.Type.full_text) - assertEquals("Wrong value in index column", cities[i], c.getString(c.getColumnIndex(CITY_COL))); + Assert.assertEquals("Wrong value in index column", cities[i], c.getString(c.getColumnIndex(CITY_COL))); if (countryColType == SmartStore.Type.full_text) - assertEquals("Wrong value in index column", countries[i], c.getString(c.getColumnIndex(COUNTRY_COL))); + Assert.assertEquals("Wrong value in index column", countries[i], c.getString(c.getColumnIndex(COUNTRY_COL))); c.moveToNext(); } } - finally{ + finally { safeClose(c); } } @@ -537,10 +536,9 @@ private void checkDb(long[] expectedIds, SmartStore.Type cityColType, SmartStore */ private void alterSoupHelper(boolean reIndexData) throws JSONException { IndexSpec[] indexSpecs = new IndexSpec[] {new IndexSpec("lastName", SmartStore.Type.string), new IndexSpec("address.city", SmartStore.Type.string)}; - - assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); + Assert.assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); store.registerSoup(TEST_SOUP, indexSpecs); - assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); + Assert.assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); // Populate soup JSONObject soupElt1Created = store.create(TEST_SOUP, new JSONObject("{'lastName':'Doe', 'address':{'city':'San Francisco','street':'1 market'}}")); @@ -562,40 +560,36 @@ private void alterSoupHelper(boolean reIndexData) throws JSONException { try { final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); String soupTableName = getSoupTableName(TEST_SOUP); - assertEquals("Wrong table for test_soup", TEST_SOUP_TABLE_NAME, soupTableName); - assertTrue("Table for test_soup should now exist", hasTable(TEST_SOUP_TABLE_NAME)); - + Assert.assertEquals("Wrong table for test_soup", TEST_SOUP_TABLE_NAME, soupTableName); + Assert.assertTrue("Table for test_soup should now exist", hasTable(TEST_SOUP_TABLE_NAME)); c = DBHelper.getInstance(db).query(db, soupTableName, null, "id ASC", null, null); - assertTrue("Expected a soup element", c.moveToFirst()); - assertEquals("Expected three soup elements", 3, c.getCount()); - - assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt1Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Wrong value in index column", "Doe", c.getString(c.getColumnIndex(soupTableName + "_0"))); + Assert.assertTrue("Expected a soup element", c.moveToFirst()); + Assert.assertEquals("Expected three soup elements", 3, c.getCount()); + Assert.assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt1Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong value in index column", "Doe", c.getString(c.getColumnIndex(soupTableName + "_0"))); if (reIndexData) - assertEquals("Wrong value in index column", "1 market", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertEquals("Wrong value in index column", "1 market", c.getString(c.getColumnIndex(soupTableName + "_1"))); else - assertNull("Wrong value in index column", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertNull("Wrong value in index column", c.getString(c.getColumnIndex(soupTableName + "_1"))); JSONTestHelper.assertSameJSON("Wrong value in soup column", soupElt1Created, new JSONObject(c.getString(c.getColumnIndex("soup")))); - c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt2Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt2Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Wrong value in index column", "Jackson", c.getString(c.getColumnIndex(soupTableName + "_0"))); + Assert.assertEquals("Wrong id", idOf(soupElt2Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt2Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong value in index column", "Jackson", c.getString(c.getColumnIndex(soupTableName + "_0"))); if (reIndexData) - assertEquals("Wrong value in index column", "100 mission", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertEquals("Wrong value in index column", "100 mission", c.getString(c.getColumnIndex(soupTableName + "_1"))); else - assertNull("Wrong value in index column", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertNull("Wrong value in index column", c.getString(c.getColumnIndex(soupTableName + "_1"))); JSONTestHelper.assertSameJSON("Wrong value in soup column", soupElt2Created, new JSONObject(c.getString(c.getColumnIndex("soup")))); - c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt3Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Wrong value in index column", "Watson", c.getString(c.getColumnIndex(soupTableName + "_0"))); + Assert.assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt3Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong value in index column", "Watson", c.getString(c.getColumnIndex(soupTableName + "_0"))); if (reIndexData) - assertEquals("Wrong value in index column", "50 market", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertEquals("Wrong value in index column", "50 market", c.getString(c.getColumnIndex(soupTableName + "_1"))); else - assertNull("Wrong value in index column", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertNull("Wrong value in index column", c.getString(c.getColumnIndex(soupTableName + "_1"))); JSONTestHelper.assertSameJSON("Wrong value in soup column", soupElt3Created, new JSONObject(c.getString(c.getColumnIndex("soup")))); } @@ -608,15 +602,13 @@ private void alterSoupHelper(boolean reIndexData) throws JSONException { * Test reIndexSoup * @throws JSONException */ + @Test public void testReIndexSoup() throws JSONException { IndexSpec[] indexSpecs = new IndexSpec[] {new IndexSpec("lastName", SmartStore.Type.string)}; - - assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); + Assert.assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); store.registerSoup(TEST_SOUP, indexSpecs); - assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); JSONObject soupElt1 = new JSONObject("{'lastName':'Doe', 'address':{'city':'San Francisco','street':'1 market'}}"); - store.create(TEST_SOUP, soupElt1); // Find by last name @@ -625,7 +617,7 @@ public void testReIndexSoup() throws JSONException { // Find by city - error expected - field is not yet indexed try { assertRowCount(1, "address.city", "San Francisco"); - fail("Expected smart sql exception"); + Assert.fail("Expected smart sql exception"); } catch (SmartSqlHelper.SmartSqlException e) { // as expected @@ -664,13 +656,14 @@ public void testReIndexSoup() throws JSONException { private void assertRowCount(int expectedCount, String field, String value) throws JSONException { String smartSql = "SELECT count(*) FROM {" + TEST_SOUP + "} WHERE {" + TEST_SOUP + ":" + field + "} = '" + value + "'"; int actualCount = store.query(QuerySpec.buildSmartQuerySpec(smartSql, 1), 0).getJSONArray(0).getInt(0); - assertEquals("Should have found " + expectedCount + " rows", expectedCount, actualCount); + Assert.assertEquals("Should have found " + expectedCount + " rows", expectedCount, actualCount); } /** * Test alter soup interrupted and resumed after step RENAME_OLD_SOUP_TABLE * @throws JSONException */ + @Test public void testAlterSoupResumeAfterRenameOldSoupTable() throws JSONException { tryAlterSoupInterruptResume(AlterSoupLongOperation.AlterSoupStep.RENAME_OLD_SOUP_TABLE); } @@ -679,6 +672,7 @@ public void testAlterSoupResumeAfterRenameOldSoupTable() throws JSONException { * Test alter soup interrupted and resumed after step DROP_OLD_INDEXES * @throws JSONException */ + @Test public void testAlterSoupResumeAfterDropOldIndexed() throws JSONException { tryAlterSoupInterruptResume(AlterSoupLongOperation.AlterSoupStep.DROP_OLD_INDEXES); } @@ -687,6 +681,7 @@ public void testAlterSoupResumeAfterDropOldIndexed() throws JSONException { * Test alter soup interrupted and resumed after step REGISTER_SOUP_USING_TABLE_NAME * @throws JSONException */ + @Test public void testAlterSoupResumeAfterRegisterSoupUsingTableName() throws JSONException { tryAlterSoupInterruptResume(AlterSoupLongOperation.AlterSoupStep.REGISTER_SOUP_USING_TABLE_NAME); } @@ -695,6 +690,7 @@ public void testAlterSoupResumeAfterRegisterSoupUsingTableName() throws JSONExce * Test alter soup interrupted and resumed after step COPY_TABLE * @throws JSONException */ + @Test public void testAlterSoupResumeAfterCopyTable() throws JSONException { tryAlterSoupInterruptResume(AlterSoupLongOperation.AlterSoupStep.COPY_TABLE); } @@ -703,6 +699,7 @@ public void testAlterSoupResumeAfterCopyTable() throws JSONException { * Test alter soup interrupted and resumed after step RE_INDEX_SOUP * @throws JSONException */ + @Test public void testAlterSoupResumeAfterReIndexSoup() throws JSONException { tryAlterSoupInterruptResume(AlterSoupLongOperation.AlterSoupStep.RE_INDEX_SOUP); } @@ -711,6 +708,7 @@ public void testAlterSoupResumeAfterReIndexSoup() throws JSONException { * Test alter soup interrupted and resumed after step DROP_OLD_TABLE * @throws JSONException */ + @Test public void testAlterSoupResumeAfterDropOldTable() throws JSONException { tryAlterSoupInterruptResume(AlterSoupLongOperation.AlterSoupStep.DROP_OLD_TABLE); } @@ -721,12 +719,12 @@ public void testAlterSoupResumeAfterDropOldTable() throws JSONException { */ private void tryAlterSoupInterruptResume(AlterSoupLongOperation.AlterSoupStep toStep) throws JSONException { final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); - assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); + Assert.assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); IndexSpec[] indexSpecs = new IndexSpec[] {new IndexSpec("lastName", SmartStore.Type.string)}; store.registerSoup(TEST_SOUP, indexSpecs); IndexSpec[] oldIndexSpecs = store.getSoupIndexSpecs(TEST_SOUP); // with column names String soupTableName = getSoupTableName(TEST_SOUP); - assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); + Assert.assertTrue("Register soup call failed", store.hasSoup(TEST_SOUP)); // Populate soup JSONObject soupElt1Created = store.create(TEST_SOUP, new JSONObject("{'lastName':'Doe', 'address':{'city':'San Francisco','street':'1 market'}}")); @@ -740,19 +738,20 @@ private void tryAlterSoupInterruptResume(AlterSoupLongOperation.AlterSoupStep to // Validate long_operations_status table LongOperation[] operations = store.getLongOperations(); int expectedCount = (toStep == AlterSoupLongOperation.AlterSoupStep.LAST ? 0 : 1); - assertEquals("Wrong number of long operations found", expectedCount, operations.length); - + Assert.assertEquals("Wrong number of long operations found", expectedCount, operations.length); if (operations.length > 0) { + // Check details JSONObject actualDetails = operations[0].getDetails(); - assertEquals("Wrong soup name", TEST_SOUP, actualDetails.getString("soupName")); - assertEquals("Wrong soup table name", soupTableName, actualDetails.getString("soupTableName")); + Assert.assertEquals("Wrong soup name", TEST_SOUP, actualDetails.getString("soupName")); + Assert.assertEquals("Wrong soup table name", soupTableName, actualDetails.getString("soupTableName")); JSONTestHelper.assertSameJSON("Wrong old indexes", IndexSpec.toJSON(oldIndexSpecs), actualDetails.getJSONArray("oldIndexSpecs")); + // new index specs in details might or might not have column names based on step so not comparing with JSONTestHelper.assertSameJSON however checkIndexSpecs below should catch any discrepancies - assertEquals("Wrong re-index data", true, actualDetails.getBoolean("reIndexData")); + Assert.assertEquals("Wrong re-index data", true, actualDetails.getBoolean("reIndexData")); // Check last step completed - assertEquals("Wrong step", toStep, ((AlterSoupLongOperation) operations[0]).getLastStepCompleted()); + Assert.assertEquals("Wrong step", toStep, ((AlterSoupLongOperation) operations[0]).getLastStepCompleted()); // Simulate restart (clear cache and call resumeLongOperations) DBHelper.getInstance(db).clearMemoryCache(); @@ -768,26 +767,23 @@ private void tryAlterSoupInterruptResume(AlterSoupLongOperation.AlterSoupStep to // Check DB Cursor c = null; try { - assertEquals("Wrong table for test_soup", TEST_SOUP_TABLE_NAME, soupTableName); - assertTrue("Table for test_soup should now exist", hasTable(TEST_SOUP_TABLE_NAME)); - + Assert.assertEquals("Wrong table for test_soup", TEST_SOUP_TABLE_NAME, soupTableName); + Assert.assertTrue("Table for test_soup should now exist", hasTable(TEST_SOUP_TABLE_NAME)); c = DBHelper.getInstance(db).query(db, soupTableName, null, "id ASC", null, null); - assertTrue("Expected a soup element", c.moveToFirst()); - assertEquals("Expected three soup elements", 2, c.getCount()); - - assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt1Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Wrong value in index column", "Doe", c.getString(c.getColumnIndex(soupTableName + "_0"))); - assertEquals("Wrong value in index column", "San Francisco", c.getString(c.getColumnIndex(soupTableName + "_1"))); - assertEquals("Wrong value in index column", "1 market", c.getString(c.getColumnIndex(soupTableName + "_2"))); + Assert.assertTrue("Expected a soup element", c.moveToFirst()); + Assert.assertEquals("Expected three soup elements", 2, c.getCount()); + Assert.assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt1Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong value in index column", "Doe", c.getString(c.getColumnIndex(soupTableName + "_0"))); + Assert.assertEquals("Wrong value in index column", "San Francisco", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertEquals("Wrong value in index column", "1 market", c.getString(c.getColumnIndex(soupTableName + "_2"))); JSONTestHelper.assertSameJSON("Wrong value in soup column", soupElt1Created, new JSONObject(c.getString(c.getColumnIndex("soup")))); - c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt2Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt2Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Wrong value in index column", "Jackson", c.getString(c.getColumnIndex(soupTableName + "_0"))); - assertEquals("Wrong value in index column", "Los Angeles", c.getString(c.getColumnIndex(soupTableName + "_1"))); - assertEquals("Wrong value in index column", "100 mission", c.getString(c.getColumnIndex(soupTableName + "_2"))); + Assert.assertEquals("Wrong id", idOf(soupElt2Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt2Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong value in index column", "Jackson", c.getString(c.getColumnIndex(soupTableName + "_0"))); + Assert.assertEquals("Wrong value in index column", "Los Angeles", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertEquals("Wrong value in index column", "100 mission", c.getString(c.getColumnIndex(soupTableName + "_2"))); JSONTestHelper.assertSameJSON("Wrong value in soup column", soupElt2Created, new JSONObject(c.getString(c.getColumnIndex("soup")))); } finally { diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreExternalStorageTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreExternalStorageTest.java index 11a66492c9..c9dd525c70 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreExternalStorageTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreExternalStorageTest.java @@ -28,6 +28,8 @@ import android.database.Cursor; +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; import com.salesforce.androidsdk.analytics.security.Encryptor; import com.salesforce.androidsdk.smartstore.store.DBOpenHelper; @@ -39,11 +41,15 @@ import com.salesforce.androidsdk.smartstore.store.SoupSpec; import com.salesforce.androidsdk.util.test.JSONTestHelper; +import junit.framework.Assert; + import net.sqlcipher.database.SQLiteDatabase; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; import java.io.File; import java.util.ArrayList; @@ -52,6 +58,8 @@ /** * Tests for encrypted smart store with external storage */ +@RunWith(AndroidJUnit4.class) +@MediumTest public class SmartStoreExternalStorageTest extends SmartStoreTest { @Override @@ -72,21 +80,23 @@ protected void assertSameSoupAsDB(JSONObject soup, Cursor c, String soupTableNam /** * Ensure that a soup cannot be using external storage and JSON1 */ + @Test public void testRegisterSoupWithExternalStorageAndJSON1() { - assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); + Assert.assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); try { registerSoup(store, OTHER_TEST_SOUP, new IndexSpec[]{new IndexSpec("lastName", Type.json1), new IndexSpec("address.city", Type.string)}); - fail("Registering soup with external storage and json1 should have thrown an exception"); + Assert.fail("Registering soup with external storage and json1 should have thrown an exception"); } catch (SmartStore.SmartStoreException e) { - assertEquals("Wrong exception", "Can't have JSON1 index specs in externally stored soup:" + OTHER_TEST_SOUP, e.getMessage()); + Assert.assertEquals("Wrong exception", "Can't have JSON1 index specs in externally stored soup:" + OTHER_TEST_SOUP, e.getMessage()); } - assertFalse("Register soup call should have failed", store.hasSoup(OTHER_TEST_SOUP)); + Assert.assertFalse("Register soup call should have failed", store.hasSoup(OTHER_TEST_SOUP)); } /** * Ensure data is still accessible after changing key */ + @Test public void testChangeKey() throws JSONException { JSONObject soupElt = new JSONObject("{'key':'ka2', 'value':'testValue'}"); String newPasscode = Encryptor.hash("123test", "hashing-key"); @@ -101,7 +111,7 @@ public void testChangeKey() throws JSONException { // Verify that data is still accessible JSONArray result = store.query(QuerySpec.buildExactQuerySpec(TEST_SOUP, "key", "ka2", null, null, 10), 0); - assertEquals("One result expected", 1, result.length()); + Assert.assertEquals("One result expected", 1, result.length()); JSONTestHelper.assertSameJSON("Wrong result for query", soupElt, result.getJSONObject(0)); } @@ -111,14 +121,16 @@ public void testChangeKey() throws JSONException { * @throws JSONException */ @Override + @Test public void testGetDatabaseSize() throws JSONException { - // Get initial values + + // Get initial values int totalSizeBefore = store.getDatabaseSize(); int dBFileSizeBefore = (int) (new File(dbOpenHelper.getWritableDatabase(getEncryptionKey()).getPath()).length()); int dbBlobsDirSizeBefore = totalSizeBefore - dBFileSizeBefore; // Populate db with several entries - for (int i=0; i<100; i++) { + for (int i = 0; i < 100; i++) { JSONObject soupElt = new JSONObject("{'key':'abcd" + i + "', 'value':'va" + i + "', 'otherValue':'ova" + i + "'}"); store.create(TEST_SOUP, soupElt); } @@ -127,40 +139,44 @@ public void testGetDatabaseSize() throws JSONException { int totalSizeAfter = store.getDatabaseSize(); int dbFileSizeAfter = (int) (new File(dbOpenHelper.getWritableDatabase(getEncryptionKey()).getPath()).length()); int dbBlobsDirSizeAfter = totalSizeAfter - dbFileSizeAfter; - - assertTrue("Database file should be larger", dbFileSizeAfter > dBFileSizeBefore); - assertTrue("Soup blobs directory should be larger", dbBlobsDirSizeAfter > dbBlobsDirSizeBefore); - assertTrue("Total database size should be larger than just db file", totalSizeAfter > totalSizeBefore); + Assert.assertTrue("Database file should be larger", dbFileSizeAfter > dBFileSizeBefore); + Assert.assertTrue("Soup blobs directory should be larger", dbBlobsDirSizeAfter > dbBlobsDirSizeBefore); + Assert.assertTrue("Total database size should be larger than just db file", totalSizeAfter > totalSizeBefore); } @Override + @Test public void testAggregateQueryOnJSON1IndexedField() throws JSONException { // json1 is not compatible with external storage. } @Override + @Test public void testCountQueryWithGroupByUsingJSON1Indexes() throws JSONException { // json1 is not compatible with external storage. } @Override + @Test public void testUpsertWithNullInJSON1IndexedField() throws JSONException { // json1 is not compatible with external storage. } @Override + @Test public void testSelectWithNullInJSON1IndexedField() throws JSONException { // json1 is not compatible with external storage. } @Override + @Test public void testDeleteAgainstChangedSoup() throws JSONException { + //create a new soup with multiple entries JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); JSONObject soupElt4 = new JSONObject("{'key':'ka4', 'value':'va4'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); @@ -175,6 +191,7 @@ public void testDeleteAgainstChangedSoup() throws JSONException { @Override protected void tryAllQueryOnChangedSoupWithUpdate(String soupName, JSONObject deletedEntry, String orderPath, IndexSpec[] newIndexSpecs, JSONObject... expectedResults) throws JSONException { + //alert the soup store.alterSoup(soupName, new SoupSpec(soupName, SoupSpec.FEATURE_EXTERNAL_STORAGE), newIndexSpecs, true); @@ -188,12 +205,13 @@ protected void tryAllQueryOnChangedSoupWithUpdate(String soupName, JSONObject de } @Override + @Test public void testExactQueryAgainstChangedSoup() throws JSONException { + //create a new soup with multiple entries JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka1-', 'value':'va1*'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka1 ', 'value':'va1%'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); @@ -207,7 +225,8 @@ public void testExactQueryAgainstChangedSoup() throws JSONException { @Override protected void tryExactQueryOnChangedSoup(String soupName, String orderPath, String value, IndexSpec[] newIndexSpecs, JSONObject expectedResult) throws JSONException { - //alert the soup + + //alert the soup store.alterSoup(soupName, new SoupSpec(soupName, SoupSpec.FEATURE_EXTERNAL_STORAGE), newIndexSpecs, true); // Exact Query @@ -217,24 +236,25 @@ protected void tryExactQueryOnChangedSoup(String soupName, String orderPath, Str } @Override + @Test public void testUpsertAgainstChangedSoup() throws JSONException { //create a new soup with multiple entries JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); - JSONObject soupElt1ForUpsert = new JSONObject("{'key':'ka1u', 'value':'va1u'}"); JSONObject soupElt2ForUpsert = new JSONObject("{'key':'ka2u', 'value':'va2u'}"); JSONObject soupElt3ForUpsert = new JSONObject("{'key':'ka3u', 'value':'va3u'}"); //CASE 1: index spec from key to value store.alterSoup(TEST_SOUP, new SoupSpec(TEST_SOUP, SoupSpec.FEATURE_EXTERNAL_STORAGE), new IndexSpec[]{new IndexSpec("value", Type.string)}, true); + //upsert an entry JSONObject soupElt1Upserted = store.upsert(TEST_SOUP, soupElt1ForUpsert); + // Query all - small page runQueryCheckResultsAndExplainPlan(TEST_SOUP, QuerySpec.buildAllQuerySpec(TEST_SOUP, "value", Order.ascending, 10), @@ -242,6 +262,7 @@ public void testUpsertAgainstChangedSoup() throws JSONException { } @Override + @Test public void testDeleteByQuery() throws JSONException { List idsDeleted = new ArrayList<>(); List idsNotDeleted = new ArrayList<>(); diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreFTSExternalStorageTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreFTSExternalStorageTest.java index a66c5dd4f6..9222470304 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreFTSExternalStorageTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreFTSExternalStorageTest.java @@ -27,13 +27,20 @@ package com.salesforce.androidsdk.store; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + import com.salesforce.androidsdk.smartstore.store.IndexSpec; import com.salesforce.androidsdk.smartstore.store.SmartStore; import com.salesforce.androidsdk.smartstore.store.SoupSpec; +import org.junit.runner.RunWith; + /** * Tests for full-text search in smartstore soups using external storage */ +@RunWith(AndroidJUnit4.class) +@SmallTest public class SmartStoreFTSExternalStorageTest extends SmartStoreFullTextSearchTest { @Override @@ -45,5 +52,4 @@ protected void registerSoup(SmartStore store, String soupName, IndexSpec[] index protected String[] getExpectedColumns() { return new String[]{"id", "created", "lastModified", FIRST_NAME_COL, LAST_NAME_COL, EMPLOYEE_ID_COL}; } - -} \ No newline at end of file +} diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreFullTextSearchSpeedTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreFullTextSearchSpeedTest.java index 876e18b5b7..d93b98d69e 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreFullTextSearchSpeedTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreFullTextSearchSpeedTest.java @@ -26,26 +26,29 @@ */ package com.salesforce.androidsdk.store; -import android.content.Context; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import android.util.Log; -import com.salesforce.androidsdk.smartstore.store.DBHelper; -import com.salesforce.androidsdk.smartstore.store.DBOpenHelper; import com.salesforce.androidsdk.smartstore.store.IndexSpec; import com.salesforce.androidsdk.smartstore.store.QuerySpec; -import com.salesforce.androidsdk.smartstore.store.SmartStore; import com.salesforce.androidsdk.smartstore.store.SmartStore.Type; -import net.sqlcipher.database.SQLiteDatabase; -import net.sqlcipher.database.SQLiteOpenHelper; +import junit.framework.Assert; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; /** * Tests to compare speed of smartstore full-text-search indices with regular indices */ +@RunWith(AndroidJUnit4.class) +@SmallTest public class SmartStoreFullTextSearchSpeedTest extends SmartStoreTestCase { public static final String TAG = "SmartStoreFTSSpeedTest"; @@ -62,22 +65,37 @@ public class SmartStoreFullTextSearchSpeedTest extends SmartStoreTestCase { public static final String ANIMALS_SOUP = "animals"; public static final String TEXT_COL = "text"; + @Before + public void setUp() throws Exception { + super.setUp(); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + + @Override protected String getEncryptionKey() { return ""; } + @Test public void testSearch1000RowsOneMatch() throws JSONException { trySearch(40, 1); } + @Test public void testSearch1000RowsManyMatches() throws JSONException { trySearch(40, 40); } + @Test public void testSearch10000RowsOneMatch() throws JSONException { trySearch(400, 1); } + @Test public void testSearch10000RowsManyMatches() throws JSONException { trySearch(400, 400); } @@ -96,8 +114,7 @@ private void trySearch(int rowsPerAnimal, int matchingRowsPerAnimal) throws JSON double totalInsertTimeFullText = setupData(Type.full_text, rowsPerAnimal, matchingRowsPerAnimal); double avgQueryTimeFullText = queryData(Type.full_text, rowsPerAnimal, matchingRowsPerAnimal); store.dropAllSoups(); - - Log.i(TAG, String.format("Search rows=%d matchingRows=%d avgQueryTimeString=%.4fs avgQueryTimeFullText=%.4fs (%.2f%%) totalInsertTimeString=%.3fs totalInsertTimeFullText=%.3fs (%.2f%%)", + Log.i(TAG, String.format("Search rows=%d matchingRows=%d avgQueryTimeString=%.4fs avgQueryTimeFullText=%.4fs (%.2f%%) totalInsertTimeString=%.3fs totalInsertTimeFullText=%.3fs (%.2f%%)", rowsPerAnimal * 25, matchingRowsPerAnimal, avgQueryTimeString, @@ -116,7 +133,6 @@ private double setupData(Type textFieldType, int rowsPerAnimal, int matchingRows store.registerSoup(ANIMALS_SOUP, new IndexSpec[]{new IndexSpec(TEXT_COL, textFieldType)}); try { store.beginTransaction(); - for (int i=0; i < 25; i++) { int charToMatch = i + 'a'; for (int j=0; j < rowsPerAnimal; j++) { @@ -134,7 +150,6 @@ private double setupData(Type textFieldType, int rowsPerAnimal, int matchingRows totalInsertTime += System.nanoTime() - start; } } - store.setTransactionSuccessful(); } finally { store.endTransaction(); @@ -150,7 +165,6 @@ private double queryData(Type textFieldType, int rowsPerAnimal, int matchingRows for (String animal : ANIMALS) { String prefix = String.format("%07d", (int) (Math.random()*(rowsPerAnimal/matchingRowsPerAnimal))); String stringToMatch = prefix + animal; - QuerySpec querySpec = textFieldType == Type.full_text ? QuerySpec.buildMatchQuerySpec(ANIMALS_SOUP, TEXT_COL, stringToMatch, null, null, rowsPerAnimal) : QuerySpec.buildLikeQuerySpec(ANIMALS_SOUP, TEXT_COL, "%" + stringToMatch + "%", null, null, rowsPerAnimal); @@ -159,19 +173,17 @@ private double queryData(Type textFieldType, int rowsPerAnimal, int matchingRows totalQueryTime += System.nanoTime() - start; validateResults(matchingRowsPerAnimal, stringToMatch, results); } - return nanosToSeconds(totalQueryTime)/ANIMALS.length; } private void validateResults(int expectedRows, String stringToMatch, JSONArray results) throws JSONException { - assertEquals("Wrong number of results", expectedRows, results.length()); + Assert.assertEquals("Wrong number of results", expectedRows, results.length()); for (int i=0; i 0) { - assertEquals("Wrong number of field returned", 1, results.getJSONArray(0).length()); + Assert.assertEquals("Wrong number of field returned", 1, results.getJSONArray(0).length()); } - assertEquals("Wrong number of results", expectedIds.length, results.length()); - for (int i=0; i { +@RunWith(AndroidJUnit4.class) +@MediumTest +public class SmartStoreInspectorActivityTest { private static final String TEST_SOUP = "test_soup"; private static final String OTHER_TEST_SOUP = "other_test_soup"; @@ -65,16 +79,13 @@ public class SmartStoreInspectorActivityTest extends private Context targetContext; private SmartStore store; - public SmartStoreInspectorActivityTest() { - super(SmartStoreInspectorActivity.class); - } + @Rule + public ActivityTestRule smartStoreInspectorActivityTestRule = new ActivityTestRule<>(SmartStoreInspectorActivity.class); - @Override + @Before public void setUp() throws Exception { - super.setUp(); EventBuilderHelper.enableDisable(false); - setActivityInitialTouchMode(false); - targetContext = getInstrumentation().getTargetContext(); + targetContext = InstrumentationRegistry.getTargetContext(); createStore(); createSoups(); populateSoup(TEST_SOUP, NUMBER_ROWS_TEST_SOUP); @@ -87,10 +98,10 @@ public void setUp() throws Exception { /** * Testing "clear" button */ + @Test public void testClickingClear() { clickButton(R.id.sf__inspector_indices_button); - assertNotNull(getActivity().getLastResults()); - + Assert.assertNotNull(smartStoreInspectorActivityTestRule.getActivity().getLastResults()); clickButton(R.id.sf__inspector_clear_button); checkInspectorIsReset(); } @@ -98,6 +109,7 @@ public void testClickingClear() { /** * Testing "soups" button */ + @Test public void testClickingSoups() { clickButton(R.id.sf__inspector_soups_button); checkInspectorState( @@ -109,6 +121,7 @@ public void testClickingSoups() { /** * Testing "indices" button */ + @Test public void testClickingIndices() { clickButton(R.id.sf__inspector_indices_button); checkInspectorState( @@ -120,6 +133,7 @@ public void testClickingIndices() { /** * Testing "run" button without specifying a query */ + @Test public void testClickingRunWithoutQuery() { clickButton(R.id.sf__inspector_run_button); checkInspectorState("", "", "", null, "No query specified", null); @@ -128,6 +142,7 @@ public void testClickingRunWithoutQuery() { /** * Testing "run" button with invalid query */ + @Test public void testClickingRunWithInvalidQuery() { String query = "SELECT {test_soup:key} FROM {test_soup2}"; setText(R.id.sf__inspector_query_text, query); @@ -139,28 +154,29 @@ public void testClickingRunWithInvalidQuery() { /** * Testing "run" button with a valid query that returns no results */ + @Test public void testClickingRunWithValidQueryNoResults() { String query = "SELECT {test_soup:key} FROM {test_soup} WHERE {test_soup:key} == 'non-existent-key'"; setText(R.id.sf__inspector_query_text, query); clickButton(R.id.sf__inspector_run_button); - checkInspectorState(query, "", "", null, "No rows returned", "[]"); } /** * Testing "run" button with a valid query */ + @Test public void testClickingRunWithValidQuery() { String query = "SELECT {test_soup:key} FROM {test_soup} WHERE {test_soup:key} == 'k_test_soup_1'"; setText(R.id.sf__inspector_query_text, query); clickButton(R.id.sf__inspector_run_button); - checkInspectorState(query, "", "", null, null, "[[\"k_test_soup_1\"]]"); } /** * Testing "run" button with a valid query and specified page size */ + @Test public void testClickingRunWithValidQueryAndPageSize() { String query = "SELECT {test_soup:key} FROM {test_soup} ORDER BY {test_soup:key}"; String pageSize = "2"; @@ -175,6 +191,7 @@ public void testClickingRunWithValidQueryAndPageSize() { * Testing "run" button with a valid query and specified page size and page * index */ + @Test public void testClickingRunWithValidQueryAndPageSizeAndPageIndex() { String query = "SELECT {test_soup:key} FROM {test_soup} ORDER BY {test_soup:key}"; String pageSize = "2"; @@ -190,15 +207,15 @@ public void testClickingRunWithValidQueryAndPageSizeAndPageIndex() { /** * Testing autocomplete */ + @Test public void testAutoComplete() { - MultiAutoCompleteTextView queryTextView = (MultiAutoCompleteTextView) getActivity() + MultiAutoCompleteTextView queryTextView = smartStoreInspectorActivityTestRule.getActivity() .findViewById(R.id.sf__inspector_query_text); ListAdapter adapter = queryTextView.getAdapter(); - Set values = new HashSet(); + Set values = new HashSet<>(); for (int i = 0; i < adapter.getCount(); i++) { values.add((String) adapter.getItem(i)); } - String[] expectedValues = { "select", "from", "where", "group by", "order by", "{test_soup}", "{test_soup:key}", "{test_soup:_soupEntryId}", "{test_soup:_soup}", @@ -207,7 +224,7 @@ public void testAutoComplete() { "{other_test_soup:_soup}", "{other_test_soup:_soupLastModifiedDate}" }; for (String expectedValue : expectedValues) { - assertTrue("Autocomplete should offer " + expectedValue, + Assert.assertTrue("Autocomplete should offer " + expectedValue, values.contains(expectedValue)); } } @@ -221,11 +238,11 @@ private void createStore() { private void createSoups() { for (String soupName : new String[] { TEST_SOUP, OTHER_TEST_SOUP }) { - assertFalse("Soup " + soupName + " should not exist", + Assert.assertFalse("Soup " + soupName + " should not exist", store.hasSoup(soupName)); store.registerSoup(soupName, new IndexSpec[] { new IndexSpec("key", Type.string) }); - assertTrue("Soup " + soupName + " should now exist", + Assert.assertTrue("Soup " + soupName + " should now exist", store.hasSoup(soupName)); } } @@ -240,39 +257,23 @@ private void populateSoup(String soupName, int numberRows) } private void clickButton(int id) { - clickView(getActivity().findViewById(id)); - waitSome(); - } + onView(withId(id)).perform(click()); + } private void checkText(String message, int id, String expectedString) { - TextView view = (TextView) getActivity().findViewById(id); - assertNotNull("TextView not found", view); - assertEquals(message, expectedString, view.getText().toString()); + final TextView view = smartStoreInspectorActivityTestRule.getActivity().findViewById(id); + Assert.assertNotNull("TextView not found", view); + Assert.assertEquals(message, expectedString, view.getText().toString()); } private void checkInspectorIsReset() { checkInspectorState("", "", "", null, null, null); } - /** - * Check inspector state - * - * @param query - * expected value for query input field - * @param pageSize - * expected value for page size input field - * @param pageIndex - * expected value for page index input field - * @param expectedAlertTitle - * expected value for last alert title - * @param expectedAlertMessageSubstring - * expected substring of last alert message - * @param expectedResultsAsString - * expected results (stringified) - */ private void checkInspectorState(String query, String pageSize, String pageIndex, String expectedAlertTitle, String expectedAlertMessageSubstring, String expectedResultsAsString) { + // Check input fields checkText("Wrong query", R.id.sf__inspector_query_text, query); checkText("Wrong page size", R.id.sf__inspector_pagesize_text, pageSize); @@ -281,59 +282,31 @@ private void checkInspectorState(String query, String pageSize, // Check results if (expectedResultsAsString == null) { - assertNull("Wrong results", getActivity().getLastResults()); + Assert.assertNull("Wrong results", smartStoreInspectorActivityTestRule.getActivity().getLastResults()); } else { - assertEquals("Wrong results", expectedResultsAsString, - getActivity().getLastResults().toString()); + Assert.assertEquals("Wrong results", expectedResultsAsString, + smartStoreInspectorActivityTestRule.getActivity().getLastResults().toString()); } // Check alert - assertEquals("Wrong alert title", expectedAlertTitle, getActivity() + Assert.assertEquals("Wrong alert title", expectedAlertTitle, smartStoreInspectorActivityTestRule.getActivity() .getLastAlertTitle()); - String actualAlertMessage = getActivity().getLastAlertMessage(); + String actualAlertMessage = smartStoreInspectorActivityTestRule.getActivity().getLastAlertMessage(); if (expectedAlertMessageSubstring == null || expectedAlertMessageSubstring.length() == 0) { - assertEquals("Wrong alert message", expectedAlertMessageSubstring, + Assert.assertEquals("Wrong alert message", expectedAlertMessageSubstring, actualAlertMessage); } else { - assertTrue("Wrong alert message", + Assert.assertTrue("Wrong alert message", actualAlertMessage.contains(expectedAlertMessageSubstring)); } } - - private void clickView(final View v) { - try { - runTestOnUiThread(new Runnable() { - @Override - public void run() { - v.performClick(); - } - }); - } catch (Throwable t) { - fail("Failed to click view " + v); - } - } private void setText(final int textViewId, final String text) { try { - runTestOnUiThread(new Runnable() { - @Override public void run() { - TextView v = (TextView) getActivity().findViewById(textViewId); - v.setText(text); - if (v instanceof EditText) - ((EditText) v).setSelection(v.getText().length()); - } - }); + onView(withId(textViewId)).perform(replaceText(text), closeSoftKeyboard()); } catch (Throwable t) { - fail("Failed to set text " + text); - } - } - - private void waitSome() { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - fail("Test interrupted"); + Assert.fail("Failed to set text " + text); } } } diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreLoadExternalStorageTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreLoadExternalStorageTest.java index 4cbf47a9db..fa3ce4a650 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreLoadExternalStorageTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreLoadExternalStorageTest.java @@ -26,25 +26,54 @@ */ package com.salesforce.androidsdk.store; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; +import android.util.Log; import com.salesforce.androidsdk.analytics.security.Encryptor; +import com.salesforce.androidsdk.smartstore.store.DBOpenHelper; import com.salesforce.androidsdk.smartstore.store.IndexSpec; import com.salesforce.androidsdk.smartstore.store.SmartStore; import com.salesforce.androidsdk.smartstore.store.SmartStore.Type; import com.salesforce.androidsdk.smartstore.store.SoupSpec; -import android.util.Log; +import junit.framework.Assert; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; /** * Set of tests for the smart store loading numerous and/or large entries and querying them back */ +@RunWith(AndroidJUnit4.class) +@MediumTest public class SmartStoreLoadExternalStorageTest extends SmartStoreLoadTest { static final int LARGE_BYTES = 512 * 1024; + @Before + public void setUp() throws Exception { + final String dbPath = InstrumentationRegistry.getTargetContext().getApplicationInfo().dataDir + "/databases"; + final File fileDir = new File(dbPath); + DBOpenHelper.deleteAllUserDatabases(InstrumentationRegistry.getTargetContext()); + DBOpenHelper.deleteDatabase(InstrumentationRegistry.getTargetContext(), null); + DBOpenHelper.removeAllFiles(fileDir); + super.setUp(); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + @Override protected String getEncryptionKey() { return Encryptor.hash("test123", "hashing-key"); @@ -56,11 +85,10 @@ protected void registerSoup(SmartStore store, String soupName, IndexSpec[] index } // Test very large payloads for smartstore + @Test public void testUpsertLargePayload() throws JSONException { setupSoup(TEST_SOUP, 1, Type.string); - JSONObject entry = new JSONObject(); - for (int i = 0; i < 5; i++) { StringBuilder sb = new StringBuilder(); for (int j = 0; j < LARGE_BYTES; j++) { @@ -79,9 +107,8 @@ public void testUpsertLargePayload() throws JSONException { // Verify JSONArray result = store.retrieve(TEST_SOUP, 1L); - for (int i = 0; i < 5; i++) { - assertTrue("Value at index " + i + " is incorrect", result.getJSONObject(0).getString("value_" + i).startsWith("" + i)); + Assert.assertTrue("Value at index " + i + " is incorrect", result.getJSONObject(0).getString("value_" + i).startsWith("" + i)); } } diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreLoadTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreLoadTest.java index fde482d6b7..c6bce5d36e 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreLoadTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreLoadTest.java @@ -26,23 +26,22 @@ */ package com.salesforce.androidsdk.store; -import android.content.Context; -import android.test.InstrumentationTestCase; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import android.util.Log; -import com.salesforce.androidsdk.smartstore.store.DBHelper; -import com.salesforce.androidsdk.smartstore.store.DBOpenHelper; import com.salesforce.androidsdk.smartstore.store.IndexSpec; import com.salesforce.androidsdk.smartstore.store.QuerySpec; import com.salesforce.androidsdk.smartstore.store.SmartStore; import com.salesforce.androidsdk.smartstore.store.SmartStore.Type; -import net.sqlcipher.database.SQLiteDatabase; -import net.sqlcipher.database.SQLiteOpenHelper; - import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.List; @@ -50,6 +49,8 @@ /** * Set of tests for the smart store loading numerous and/or large entries and querying them back */ +@RunWith(AndroidJUnit4.class) +@SmallTest public class SmartStoreLoadTest extends SmartStoreTestCase { protected static final String TEST_SOUP = "test_soup"; @@ -58,54 +59,66 @@ public class SmartStoreLoadTest extends SmartStoreTestCase { private static final int NUMBER_ENTRIES_PER_BATCH = 100; private static final int NS_IN_MS = 1000000; - // - // Tests - // + @Before + public void setUp() throws Exception { + super.setUp(); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + @Test public void testUpsertQuery1StringIndex1field20characters() throws JSONException { tryUpsertQuery(Type.string, NUMBER_ENTRIES, 1, 20, 1); } + @Test public void testUpsertQuery1StringIndex1field1000characters() throws JSONException { tryUpsertQuery(Type.string, NUMBER_ENTRIES, 1, 1000, 1); } + @Test public void testUpsertQuery1StringIndex10fields20characters() throws JSONException { tryUpsertQuery(Type.string, NUMBER_ENTRIES, 10, 20, 1); } + @Test public void testUpsertQuery10StringIndexes10fields20characters() throws JSONException { tryUpsertQuery(Type.string, NUMBER_ENTRIES, 10, 20, 10); } + @Test public void testUpsertQuery1JSON1Index1field20characters() throws JSONException { tryUpsertQuery(Type.json1, NUMBER_ENTRIES, 1, 20, 1); } + @Test public void testUpsertQuery1JSON1Index1field1000characters() throws JSONException { tryUpsertQuery(Type.json1, NUMBER_ENTRIES, 1, 1000, 1); } + @Test public void testUpsertQuery1JSON1Index10fields20characters() throws JSONException { tryUpsertQuery(Type.json1, NUMBER_ENTRIES, 10, 20, 1); } + @Test public void testUpsertQuery10JSON1Indexes10fields20characters() throws JSONException { tryUpsertQuery(Type.json1, NUMBER_ENTRIES, 10, 20, 10); } + @Test public void testAlterSoupClassicIndexing() throws JSONException { tryAlterSoup(Type.string); } + @Test public void testAlterSoupJSON1Indexing() throws JSONException { tryAlterSoup(Type.json1); } - - // - // Helper methods - // protected String getEncryptionKey() { return ""; } @@ -153,6 +166,7 @@ private void upsertEntries(int numberBatches, int numberEntriesPerBatch, int num } private void queryEntries() throws JSONException { + // Should find all queryEntries(QuerySpec.buildAllQuerySpec(TEST_SOUP, null, null, 1)); queryEntries(QuerySpec.buildAllQuerySpec(TEST_SOUP, null, null, 10)); @@ -171,7 +185,6 @@ private void queryEntries() throws JSONException { queryEntries(QuerySpec.buildExactQuerySpec(TEST_SOUP, "k_0", "missing", null, null, 1)); } - private void queryEntries(QuerySpec querySpec) throws JSONException { List times = new ArrayList(); int countMatches = 0; diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreTest.java index 91bee92566..3a61a9135e 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreTest.java @@ -28,9 +28,10 @@ import android.database.Cursor; import android.os.SystemClock; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import com.salesforce.androidsdk.smartstore.store.DBHelper; -import com.salesforce.androidsdk.smartstore.store.DBOpenHelper; import com.salesforce.androidsdk.smartstore.store.IndexSpec; import com.salesforce.androidsdk.smartstore.store.QuerySpec; import com.salesforce.androidsdk.smartstore.store.QuerySpec.Order; @@ -39,19 +40,26 @@ import com.salesforce.androidsdk.smartstore.store.SoupSpec; import com.salesforce.androidsdk.util.test.JSONTestHelper; +import junit.framework.Assert; + import net.sqlcipher.database.SQLiteDatabase; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; import java.util.Arrays; import java.util.List; /** * Main test suite for SmartStore - * */ +@RunWith(AndroidJUnit4.class) +@LargeTest public class SmartStoreTest extends SmartStoreTestCase { protected static final String TEST_SOUP = "test_soup"; @@ -59,18 +67,23 @@ public class SmartStoreTest extends SmartStoreTestCase { private static final String THIRD_TEST_SOUP = "third_test_soup"; private static final String FOURTH_TEST_SOUP = "fourth_test_soup"; - @Override + @Before public void setUp() throws Exception { super.setUp(); store.setCaptureExplainQueryPlan(true); - assertFalse("Table for test_soup should not exist", hasTable("TABLE_1")); - assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); + Assert.assertFalse("Table for test_soup should not exist", hasTable("TABLE_1")); + Assert.assertFalse("Soup test_soup should not exist", store.hasSoup(TEST_SOUP)); registerSoup(store, TEST_SOUP, new IndexSpec[] { new IndexSpec("key", Type.string) }); - assertEquals("Table for test_soup was expected to be called TABLE_1", "TABLE_1", getSoupTableName(TEST_SOUP)); - assertTrue("Table for test_soup should now exist", hasTable("TABLE_1")); - assertTrue("Soup test_soup should now exist", store.hasSoup(TEST_SOUP)); + Assert.assertEquals("Table for test_soup was expected to be called TABLE_1", "TABLE_1", getSoupTableName(TEST_SOUP)); + Assert.assertTrue("Table for test_soup should now exist", hasTable("TABLE_1")); + Assert.assertTrue("Soup test_soup should now exist", store.hasSoup(TEST_SOUP)); } + @After + public void tearDown() throws Exception { + super.tearDown(); + } + @Override protected String getEncryptionKey() { return "test123"; @@ -79,13 +92,13 @@ protected String getEncryptionKey() { /** * Checking compile options */ + @Test public void testCompileOptions() { List compileOptions = store.getCompileOptions(); - - assertTrue("ENABLE_FTS4 flag not found in compile options", compileOptions.contains("ENABLE_FTS4")); - assertTrue("ENABLE_FTS3_PARENTHESIS flag not found in compile options", compileOptions.contains("ENABLE_FTS3_PARENTHESIS")); - assertTrue("ENABLE_FTS5 flag not found in compile options", compileOptions.contains("ENABLE_FTS5")); - assertTrue("ENABLE_JSON1 flag not found in compile options", compileOptions.contains("ENABLE_JSON1")); + Assert.assertTrue("ENABLE_FTS4 flag not found in compile options", compileOptions.contains("ENABLE_FTS4")); + Assert.assertTrue("ENABLE_FTS3_PARENTHESIS flag not found in compile options", compileOptions.contains("ENABLE_FTS3_PARENTHESIS")); + Assert.assertTrue("ENABLE_FTS5 flag not found in compile options", compileOptions.contains("ENABLE_FTS5")); + Assert.assertTrue("ENABLE_JSON1 flag not found in compile options", compileOptions.contains("ENABLE_JSON1")); } /** @@ -99,19 +112,20 @@ protected void assertSameSoupAsDB(JSONObject soup, Cursor c, String soupName, Lo * Testing method with paths to top level string/integer/array/map as well as edge cases (null object/null or empty path) * @throws JSONException */ + @Test public void testProjectTopLevel() throws JSONException { JSONObject json = new JSONObject("{'a':'va', 'b':2, 'c':[0,1,2], 'd': {'d1':'vd1', 'd2':'vd2', 'd3':[1,2], 'd4':{'e':5}}}"); // Null object - assertNull("Should have been null", SmartStore.project(null, "path")); + Assert.assertNull("Should have been null", SmartStore.project(null, "path")); // Root JSONTestHelper.assertSameJSON("Should have returned whole object", json, SmartStore.project(json, null)); JSONTestHelper.assertSameJSON("Should have returned whole object", json, SmartStore.project(json, "")); // Top-level elements - assertEquals("Wrong value for key a", "va", SmartStore.project(json, "a")); - assertEquals("Wrong value for key b", 2, SmartStore.project(json, "b")); + Assert.assertEquals("Wrong value for key a", "va", SmartStore.project(json, "a")); + Assert.assertEquals("Wrong value for key b", 2, SmartStore.project(json, "b")); JSONTestHelper.assertSameJSON("Wrong value for key c", new JSONArray("[0,1,2]"), SmartStore.project(json, "c")); JSONTestHelper.assertSameJSON("Wrong value for key d", new JSONObject("{'d1':'vd1','d2':'vd2','d3':[1,2],'d4':{'e':5}}"), (JSONObject) SmartStore.project(json, "d")); } @@ -120,24 +134,25 @@ public void testProjectTopLevel() throws JSONException { * Testing method with paths to non-top level string/integer/array/map * @throws JSONException */ + @Test public void testProjectNested() throws JSONException { JSONObject json = new JSONObject("{'a':'va', 'b':2, 'c':[0,1,2], 'd': {'d1':'vd1', 'd2':'vd2', 'd3':[1,2], 'd4':{'e':5}}}"); // Nested elements - assertEquals("Wrong value for key d.d1", "vd1", SmartStore.project(json, "d.d1")); - assertEquals("Wrong value for key d.d2", "vd2", SmartStore.project(json, "d.d2")); + Assert.assertEquals("Wrong value for key d.d1", "vd1", SmartStore.project(json, "d.d1")); + Assert.assertEquals("Wrong value for key d.d2", "vd2", SmartStore.project(json, "d.d2")); JSONTestHelper.assertSameJSON("Wrong value for key d.d3", new JSONArray("[1,2]"), SmartStore.project(json, "d.d3")); JSONTestHelper.assertSameJSON("Wrong value for key d.d4", new JSONObject("{'e':5}"), SmartStore.project(json, "d.d4")); - assertEquals("Wrong value for key d.d4.e", 5, SmartStore.project(json, "d.d4.e")); + Assert.assertEquals("Wrong value for key d.d4.e", 5, SmartStore.project(json, "d.d4.e")); } /** * Testing method with path through arrays * @throws JSONException */ + @Test public void testProjectThroughArrays() throws JSONException { JSONObject json = new JSONObject("{\"a\":\"a1\", \"b\":2, \"c\":[{\"cc\":\"cc1\"}, {\"cc\":2}, {\"cc\":[1,2,3]}, {}, {\"cc\":{\"cc5\":5}}], \"d\":[{\"dd\":[{\"ddd\":\"ddd11\"},{\"ddd\":\"ddd12\"}]}, {\"dd\":[{\"ddd\":\"ddd21\"}]}, {\"dd\":[{\"ddd\":\"ddd31\"},{\"ddd3\":\"ddd32\"}]}]}"); - JSONTestHelper.assertSameJSON("Wrong value for key c", new JSONArray("[{\"cc\":\"cc1\"}, {\"cc\":2}, {\"cc\":[1,2,3]}, {}, {\"cc\":{\"cc5\":5}}]"), SmartStore.project(json, "c")); JSONTestHelper.assertSameJSON("Wrong value for key c.cc", new JSONArray("[\"cc1\",2, [1,2,3], {\"cc5\":5}]"), SmartStore.project(json, "c.cc")); JSONTestHelper.assertSameJSON("Wrong value for key c.cc.cc5", new JSONArray("[5]"), SmartStore.project(json, "c.cc.cc5")); @@ -147,37 +162,39 @@ public void testProjectThroughArrays() throws JSONException { JSONTestHelper.assertSameJSON("Wrong value for key d.dd.ddd3", new JSONArray("[[\"ddd32\"]]"), SmartStore.project(json, "d.dd.ddd3")); } - /** * Check that the meta data table (soup index map) has been created */ + @Test public void testMetaDataTableCreated() { - assertTrue("Table soup_index_map not found", hasTable("soup_index_map")); + Assert.assertTrue("Table soup_index_map not found", hasTable("soup_index_map")); } /** * Test register/drop soup */ + @Test public void testRegisterDropSoup() { + // Before - assertNull("getSoupTableName should have returned null", getSoupTableName(THIRD_TEST_SOUP)); - assertFalse("Soup third_test_soup should not exist", store.hasSoup(THIRD_TEST_SOUP)); + Assert.assertNull("getSoupTableName should have returned null", getSoupTableName(THIRD_TEST_SOUP)); + Assert.assertFalse("Soup third_test_soup should not exist", store.hasSoup(THIRD_TEST_SOUP)); // Register registerSoup(store, THIRD_TEST_SOUP, new IndexSpec[] { new IndexSpec("key", Type.string), new IndexSpec("value", Type.string) }); String soupTableName = getSoupTableName(THIRD_TEST_SOUP); - assertEquals("getSoupTableName should have returned TABLE_2", "TABLE_2", soupTableName); - assertTrue("Table for soup third_test_soup does exist", hasTable(soupTableName)); - assertTrue("Register soup call failed", store.hasSoup(THIRD_TEST_SOUP)); + Assert.assertEquals("getSoupTableName should have returned TABLE_2", "TABLE_2", soupTableName); + Assert.assertTrue("Table for soup third_test_soup does exist", hasTable(soupTableName)); + Assert.assertTrue("Register soup call failed", store.hasSoup(THIRD_TEST_SOUP)); // Check soup indexes final IndexSpec[] indexSpecs = store.getSoupIndexSpecs(THIRD_TEST_SOUP); - assertEquals("Wrong path", "key", indexSpecs[0].path); - assertEquals("Wrong type", Type.string, indexSpecs[0].type); - assertEquals("Wrong column name", soupTableName + "_0", indexSpecs[0].columnName); - assertEquals("Wrong path", "value", indexSpecs[1].path); - assertEquals("Wrong type", Type.string, indexSpecs[1].type); - assertEquals("Wrong column name", soupTableName + "_1", indexSpecs[1].columnName); + Assert.assertEquals("Wrong path", "key", indexSpecs[0].path); + Assert.assertEquals("Wrong type", Type.string, indexSpecs[0].type); + Assert.assertEquals("Wrong column name", soupTableName + "_0", indexSpecs[0].columnName); + Assert.assertEquals("Wrong path", "value", indexSpecs[1].path); + Assert.assertEquals("Wrong type", Type.string, indexSpecs[1].type); + Assert.assertEquals("Wrong column name", soupTableName + "_1", indexSpecs[1].columnName); // Check db indexes checkDatabaseIndexes(soupTableName, Arrays.asList(new String[] { @@ -191,52 +208,56 @@ public void testRegisterDropSoup() { store.dropSoup(THIRD_TEST_SOUP); // After - assertFalse("Soup third_test_soup should no longer exist", store.hasSoup(THIRD_TEST_SOUP)); - assertNull("getSoupTableName should have returned null", getSoupTableName(THIRD_TEST_SOUP)); - assertFalse("Table for soup third_test_soup does exist", hasTable(soupTableName)); + Assert.assertFalse("Soup third_test_soup should no longer exist", store.hasSoup(THIRD_TEST_SOUP)); + Assert.assertNull("getSoupTableName should have returned null", getSoupTableName(THIRD_TEST_SOUP)); + Assert.assertFalse("Table for soup third_test_soup does exist", hasTable(soupTableName)); } /** * Testing getAllSoupNames: register a new soup and then drop it and call getAllSoupNames before and after */ + @Test public void testGetAllSoupNames() { + // Before - assertEquals("One soup name expected", 1, store.getAllSoupNames().size()); - assertTrue(TEST_SOUP + " should have been returned by getAllSoupNames", store.getAllSoupNames().contains(TEST_SOUP)); + Assert.assertEquals("One soup name expected", 1, store.getAllSoupNames().size()); + Assert.assertTrue(TEST_SOUP + " should have been returned by getAllSoupNames", store.getAllSoupNames().contains(TEST_SOUP)); // Register another soup registerSoup(store, THIRD_TEST_SOUP, new IndexSpec[] { new IndexSpec("key", Type.string), new IndexSpec("value", Type.string) }); - assertEquals("Two soup names expected", 2, store.getAllSoupNames().size()); - assertTrue(TEST_SOUP + " should have been returned by getAllSoupNames", store.getAllSoupNames().contains(TEST_SOUP)); - assertTrue(THIRD_TEST_SOUP + " should have been returned by getAllSoupNames", store.getAllSoupNames().contains(THIRD_TEST_SOUP)); + Assert.assertEquals("Two soup names expected", 2, store.getAllSoupNames().size()); + Assert.assertTrue(TEST_SOUP + " should have been returned by getAllSoupNames", store.getAllSoupNames().contains(TEST_SOUP)); + Assert.assertTrue(THIRD_TEST_SOUP + " should have been returned by getAllSoupNames", store.getAllSoupNames().contains(THIRD_TEST_SOUP)); // Drop the latest soup store.dropSoup(THIRD_TEST_SOUP); - assertEquals("One soup name expected", 1, store.getAllSoupNames().size()); - assertTrue(TEST_SOUP + " should have been returned by getAllSoupNames", store.getAllSoupNames().contains(TEST_SOUP)); + Assert.assertEquals("One soup name expected", 1, store.getAllSoupNames().size()); + Assert.assertTrue(TEST_SOUP + " should have been returned by getAllSoupNames", store.getAllSoupNames().contains(TEST_SOUP)); } /** * Testing dropAllSoups: register a couple of soups then drop them all */ + @Test public void testDropAllSoups() { + // Register another soup - assertEquals("One soup name expected", 1, store.getAllSoupNames().size()); + Assert.assertEquals("One soup name expected", 1, store.getAllSoupNames().size()); registerSoup(store, THIRD_TEST_SOUP, new IndexSpec[] { new IndexSpec("key", Type.string), new IndexSpec("value", Type.string) }); - assertEquals("Two soup names expected", 2, store.getAllSoupNames().size()); + Assert.assertEquals("Two soup names expected", 2, store.getAllSoupNames().size()); // Drop all store.dropAllSoups(); - assertEquals("No soup name expected", 0, store.getAllSoupNames().size()); - assertFalse("Soup " + THIRD_TEST_SOUP + " should no longer exist", store.hasSoup(THIRD_TEST_SOUP)); - assertFalse("Soup " + TEST_SOUP + " should no longer exist", store.hasSoup(TEST_SOUP)); + Assert.assertEquals("No soup name expected", 0, store.getAllSoupNames().size()); + Assert.assertFalse("Soup " + THIRD_TEST_SOUP + " should no longer exist", store.hasSoup(THIRD_TEST_SOUP)); + Assert.assertFalse("Soup " + TEST_SOUP + " should no longer exist", store.hasSoup(TEST_SOUP)); } - - + /** * Testing create: create a single element with a single index pointing to a top level attribute * @throws JSONException */ + @Test public void testCreateOne() throws JSONException { JSONObject soupElt = new JSONObject("{'key':'ka', 'value':'va'}"); JSONObject soupEltCreated = store.create(TEST_SOUP, soupElt); @@ -247,13 +268,13 @@ public void testCreateOne() throws JSONException { final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); String soupTableName = getSoupTableName(TEST_SOUP); c = DBHelper.getInstance(db).query(db, soupTableName, null, null, null, null); - assertTrue("Expected a soup element", c.moveToFirst()); - assertEquals("Expected one soup element only", 1, c.getCount()); - assertEquals("Wrong id", idOf(soupEltCreated), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupEltCreated.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Wrong value in index column", "ka", c.getString(c.getColumnIndex(soupTableName + "_0"))); + Assert.assertTrue("Expected a soup element", c.moveToFirst()); + Assert.assertEquals("Expected one soup element only", 1, c.getCount()); + Assert.assertEquals("Wrong id", idOf(soupEltCreated), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupEltCreated.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong value in index column", "ka", c.getString(c.getColumnIndex(soupTableName + "_0"))); assertSameSoupAsDB(soupEltCreated, c, soupTableName, idOf(soupEltCreated)); - assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); } finally { safeClose(c); @@ -264,15 +285,14 @@ public void testCreateOne() throws JSONException { * Testing create: create multiple elements with multiple indices not just pointing to top level attributes * @throws JSONException */ + @Test public void testCreateMultiple() throws JSONException { - assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); + Assert.assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); registerSoup(store, OTHER_TEST_SOUP, new IndexSpec[] { new IndexSpec("lastName", Type.string), new IndexSpec("address.city", Type.string) }); - assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); JSONObject soupElt1 = new JSONObject("{'lastName':'Doe', 'address':{'city':'San Francisco','street':'1 market'}}"); JSONObject soupElt2 = new JSONObject("{'lastName':'Jackson', 'address':{'city':'Los Angeles','street':'100 mission'}}"); JSONObject soupElt3 = new JSONObject("{'lastName':'Watson', 'address':{'city':'London','street':'50 market'}}"); - JSONObject soupElt1Created = store.create(OTHER_TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(OTHER_TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(OTHER_TEST_SOUP, soupElt3); @@ -281,33 +301,29 @@ public void testCreateMultiple() throws JSONException { Cursor c = null; try { String soupTableName = getSoupTableName(OTHER_TEST_SOUP); - assertEquals("Table for other_test_soup was expected to be called TABLE_2", "TABLE_2", soupTableName); - assertTrue("Table for other_test_soup should now exist", hasTable("TABLE_2")); + Assert.assertEquals("Table for other_test_soup was expected to be called TABLE_2", "TABLE_2", soupTableName); + Assert.assertTrue("Table for other_test_soup should now exist", hasTable("TABLE_2")); final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); c = DBHelper.getInstance(db).query(db, soupTableName, null, "id ASC", null, null); - assertTrue("Expected a soup element", c.moveToFirst()); - assertEquals("Expected three soup elements", 3, c.getCount()); - - assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt1Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Wrong value in index column", "Doe", c.getString(c.getColumnIndex(soupTableName + "_0"))); - assertEquals("Wrong value in index column", "San Francisco", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertTrue("Expected a soup element", c.moveToFirst()); + Assert.assertEquals("Expected three soup elements", 3, c.getCount()); + Assert.assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt1Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong value in index column", "Doe", c.getString(c.getColumnIndex(soupTableName + "_0"))); + Assert.assertEquals("Wrong value in index column", "San Francisco", c.getString(c.getColumnIndex(soupTableName + "_1"))); assertSameSoupAsDB(soupElt1Created, c, soupTableName, idOf(soupElt1Created)); - c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt2Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt2Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Wrong value in index column", "Jackson", c.getString(c.getColumnIndex(soupTableName + "_0"))); - assertEquals("Wrong value in index column", "Los Angeles", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertEquals("Wrong id", idOf(soupElt2Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt2Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong value in index column", "Jackson", c.getString(c.getColumnIndex(soupTableName + "_0"))); + Assert.assertEquals("Wrong value in index column", "Los Angeles", c.getString(c.getColumnIndex(soupTableName + "_1"))); assertSameSoupAsDB(soupElt2Created, c, soupTableName, idOf(soupElt2Created)); - c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt3Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Wrong value in index column", "Watson", c.getString(c.getColumnIndex(soupTableName + "_0"))); - assertEquals("Wrong value in index column", "London", c.getString(c.getColumnIndex(soupTableName + "_1"))); + Assert.assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt3Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong value in index column", "Watson", c.getString(c.getColumnIndex(soupTableName + "_0"))); + Assert.assertEquals("Wrong value in index column", "London", c.getString(c.getColumnIndex(soupTableName + "_1"))); assertSameSoupAsDB(soupElt3Created, c, soupTableName, idOf(soupElt3Created)); - } finally { safeClose(c); @@ -318,23 +334,20 @@ public void testCreateMultiple() throws JSONException { * Testing update: create multiple soup elements and update one of them, check them all * @throws JSONException */ + @Test public void testUpdate() throws JSONException { JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); - SystemClock.sleep(10); // to get a different last modified date JSONObject soupElt2ForUpdate = new JSONObject("{'key':'ka2u', 'value':'va2u'}"); JSONObject soupElt2Updated = store.update(TEST_SOUP, soupElt2ForUpdate, idOf(soupElt2Created)); - JSONObject soupElt1Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt1Created)).getJSONObject(0); JSONObject soupElt2Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt2Created)).getJSONObject(0); JSONObject soupElt3Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt3Created)).getJSONObject(0); - JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt1Created, soupElt1Retrieved); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt2Updated, soupElt2Retrieved); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt3Created, soupElt3Retrieved); @@ -345,22 +358,19 @@ public void testUpdate() throws JSONException { final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); String soupTableName = getSoupTableName(TEST_SOUP); c = DBHelper.getInstance(db).query(db, soupTableName, null, "id ASC", null, null); - assertTrue("Expected a soup element", c.moveToFirst()); - assertEquals("Expected three soup elements", 3, c.getCount()); - - assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt1Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); - + Assert.assertTrue("Expected a soup element", c.moveToFirst()); + Assert.assertEquals("Expected three soup elements", 3, c.getCount()); + Assert.assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt1Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt2Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt2Updated.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertTrue("Last modified date should be more recent than created date", c.getLong(c.getColumnIndex("created")) < c.getLong(c.getColumnIndex("lastModified"))); - + Assert.assertEquals("Wrong id", idOf(soupElt2Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt2Updated.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertTrue("Last modified date should be more recent than created date", c.getLong(c.getColumnIndex("created")) < c.getLong(c.getColumnIndex("lastModified"))); c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt3Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt3Created.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); } finally { safeClose(c); @@ -371,23 +381,20 @@ public void testUpdate() throws JSONException { * Testing upsert: upsert multiple soup elements and re-upsert one of them, check them all * @throws JSONException */ + @Test public void testUpsert() throws JSONException { JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); - JSONObject soupElt1Upserted = store.upsert(TEST_SOUP, soupElt1); JSONObject soupElt2Upserted = store.upsert(TEST_SOUP, soupElt2); JSONObject soupElt3Upserted = store.upsert(TEST_SOUP, soupElt3); - SystemClock.sleep(10); // to get a different last modified date JSONObject soupElt2ForUpdate = new JSONObject("{'key':'ka2u', 'value':'va2u', '_soupEntryId': " + idOf(soupElt2Upserted) + "}"); JSONObject soupElt2Updated = store.upsert(TEST_SOUP, soupElt2ForUpdate); - JSONObject soupElt1Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt1Upserted)).getJSONObject(0); JSONObject soupElt2Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt2Upserted)).getJSONObject(0); JSONObject soupElt3Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt3Upserted)).getJSONObject(0); - JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt1Upserted, soupElt1Retrieved); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt2Updated, soupElt2Retrieved); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt3Upserted, soupElt3Retrieved); @@ -398,22 +405,19 @@ public void testUpsert() throws JSONException { final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); String soupTableName = getSoupTableName(TEST_SOUP); c = DBHelper.getInstance(db).query(db, soupTableName, null, "id ASC", null, null); - assertTrue("Expected a soup element", c.moveToFirst()); - assertEquals("Expected three soup elements", 3, c.getCount()); - - assertEquals("Wrong id", idOf(soupElt1Upserted), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt1Upserted.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); - + Assert.assertTrue("Expected a soup element", c.moveToFirst()); + Assert.assertEquals("Expected three soup elements", 3, c.getCount()); + Assert.assertEquals("Wrong id", idOf(soupElt1Upserted), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt1Upserted.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt2Upserted), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt2Updated.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertTrue("Last modified date should be more recent than created date", c.getLong(c.getColumnIndex("created")) < c.getLong(c.getColumnIndex("lastModified"))); - + Assert.assertEquals("Wrong id", idOf(soupElt2Upserted), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt2Updated.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertTrue("Last modified date should be more recent than created date", c.getLong(c.getColumnIndex("created")) < c.getLong(c.getColumnIndex("lastModified"))); c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt3Upserted), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt3Upserted.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong id", idOf(soupElt3Upserted), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt3Upserted.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); } finally { safeClose(c); @@ -424,23 +428,20 @@ public void testUpsert() throws JSONException { * Testing upsert with external id: upsert multiple soup elements and re-upsert one of them, check them all * @throws JSONException */ + @Test public void testUpsertWithExternalId() throws JSONException { JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); - JSONObject soupElt1Upserted = store.upsert(TEST_SOUP, soupElt1, "key"); JSONObject soupElt2Upserted = store.upsert(TEST_SOUP, soupElt2, "key"); JSONObject soupElt3Upserted = store.upsert(TEST_SOUP, soupElt3, "key"); - SystemClock.sleep(10); // to get a different last modified date JSONObject soupElt2ForUpdate = new JSONObject("{'key':'ka2', 'value':'va2u'}"); JSONObject soupElt2Updated = store.upsert(TEST_SOUP, soupElt2ForUpdate, "key"); - JSONObject soupElt1Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt1Upserted)).getJSONObject(0); JSONObject soupElt2Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt2Upserted)).getJSONObject(0); JSONObject soupElt3Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt3Upserted)).getJSONObject(0); - JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt1Upserted, soupElt1Retrieved); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt2Updated, soupElt2Retrieved); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt3Upserted, soupElt3Retrieved); @@ -451,40 +452,37 @@ public void testUpsertWithExternalId() throws JSONException { final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); String soupTableName = getSoupTableName(TEST_SOUP); c = DBHelper.getInstance(db).query(db, soupTableName, null, "id ASC", null, null); - assertTrue("Expected a soup element", c.moveToFirst()); - assertEquals("Expected three soup elements", 3, c.getCount()); - - assertEquals("Wrong id", idOf(soupElt1Upserted), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt1Upserted.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); - + Assert.assertTrue("Expected a soup element", c.moveToFirst()); + Assert.assertEquals("Expected three soup elements", 3, c.getCount()); + Assert.assertEquals("Wrong id", idOf(soupElt1Upserted), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt1Upserted.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt2Upserted), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt2Updated.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertTrue("Last modified date should be more recent than created date", c.getLong(c.getColumnIndex("created")) < c.getLong(c.getColumnIndex("lastModified"))); - + Assert.assertEquals("Wrong id", idOf(soupElt2Upserted), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt2Updated.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertTrue("Last modified date should be more recent than created date", c.getLong(c.getColumnIndex("created")) < c.getLong(c.getColumnIndex("lastModified"))); c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt3Upserted), c.getLong(c.getColumnIndex("id"))); - assertEquals("Wrong created date", soupElt3Upserted.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); - assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Wrong id", idOf(soupElt3Upserted), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong created date", soupElt3Upserted.getLong(SmartStore.SOUP_LAST_MODIFIED_DATE), c.getLong(c.getColumnIndex("lastModified"))); + Assert.assertEquals("Created date and last modified date should be equal", c.getLong(c.getColumnIndex("created")), c.getLong(c.getColumnIndex("lastModified"))); } finally { safeClose(c); } } - - + /** * Testing upsert passing a non-indexed path for the external id (should fail) * @throws JSONException */ + @Test public void testUpsertWithNonIndexedExternalId() throws JSONException { JSONObject soupElt = new JSONObject("{'key':'ka1', 'value':'va1'}"); try { store.upsert(TEST_SOUP, soupElt, "value"); - fail("Exception was expected: value is not an indexed field"); + Assert.fail("Exception was expected: value is not an indexed field"); } catch (RuntimeException e) { - assertTrue("Wrong exception", e.getMessage().contains("does not have an index")); + Assert.assertTrue("Wrong exception", e.getMessage().contains("does not have an index")); } } @@ -492,25 +490,22 @@ public void testUpsertWithNonIndexedExternalId() throws JSONException { * Testing upsert with an external id that is not unique in the soup * @throws JSONException */ + @Test public void testUpsertWithNonUniqueExternalId() throws JSONException { JSONObject soupElt1 = new JSONObject("{'key':'ka', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka', 'value':'va3'}"); - JSONObject soupElt1Upserted = store.upsert(TEST_SOUP, soupElt1); JSONObject soupElt2Upserted = store.upsert(TEST_SOUP, soupElt2); - JSONObject soupElt1Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt1Upserted)).getJSONObject(0); JSONObject soupElt2Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt2Upserted)).getJSONObject(0); - JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt1Upserted, soupElt1Retrieved); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt2Upserted, soupElt2Retrieved); - try { store.upsert(TEST_SOUP, soupElt3, "key"); - fail("Exception was expected: key is not unique in the soup"); + Assert.fail("Exception was expected: key is not unique in the soup"); } catch (RuntimeException e) { - assertTrue("Wrong exception", e.getMessage().contains("are more than one soup elements")); + Assert.assertTrue("Wrong exception", e.getMessage().contains("are more than one soup elements")); } } @@ -518,19 +513,17 @@ public void testUpsertWithNonUniqueExternalId() throws JSONException { * Testing retrieve: create multiple soup elements and retrieves them back * @throws JSONException */ + @Test public void testRetrieve() throws JSONException { JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); - JSONObject soupElt1Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt1Created)).getJSONObject(0); JSONObject soupElt2Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt2Created)).getJSONObject(0); JSONObject soupElt3Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt3Created)).getJSONObject(0); - JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt1Created, soupElt1Retrieved); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt2Created, soupElt2Retrieved); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt3Created, soupElt3Retrieved); @@ -540,23 +533,20 @@ public void testRetrieve() throws JSONException { * Testing delete: create soup elements, delete element by id and check database directly that it is in fact gone * @throws JSONException */ + @Test public void testDelete() throws JSONException { JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); - store.delete(TEST_SOUP, idOf(soupElt2Created)); - JSONObject soupElt1Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt1Created)).getJSONObject(0); JSONArray soupElt2Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt2Created)); JSONObject soupElt3Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt3Created)).getJSONObject(0); - JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt1Created, soupElt1Retrieved); - assertEquals("Should be empty", 0, soupElt2Retrieved.length()); + Assert.assertEquals("Should be empty", 0, soupElt2Retrieved.length()); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt3Created, soupElt3Retrieved); // Check DB @@ -565,13 +555,11 @@ public void testDelete() throws JSONException { final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); String soupTableName = getSoupTableName(TEST_SOUP); c = DBHelper.getInstance(db).query(db, soupTableName, null, "id ASC", null, null); - assertTrue("Expected a soup element", c.moveToFirst()); - assertEquals("Expected two soup elements", 2, c.getCount()); - - assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); - + Assert.assertTrue("Expected a soup element", c.moveToFirst()); + Assert.assertEquals("Expected two soup elements", 2, c.getCount()); + Assert.assertEquals("Wrong id", idOf(soupElt1Created), c.getLong(c.getColumnIndex("id"))); c.moveToNext(); - assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); } finally { safeClose(c); } @@ -581,6 +569,7 @@ public void testDelete() throws JSONException { * Testing delete: create soup elements, delete by query and check database directly that deleted entries are in fact gone * @throws JSONException */ + @Test public void testDeleteByQuery() throws JSONException { tryDeleteByQuery(null, null); } @@ -595,25 +584,19 @@ protected void tryDeleteByQuery(List idsDeleted, List idsNotDeleted) JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); - long id1 = soupElt1Created.getLong(SmartStore.SOUP_ENTRY_ID); long id2 = soupElt2Created.getLong(SmartStore.SOUP_ENTRY_ID); long id3 = soupElt3Created.getLong(SmartStore.SOUP_ENTRY_ID); - QuerySpec querySpec = QuerySpec.buildRangeQuerySpec(TEST_SOUP, "key", "ka1", "ka2", "key", Order.ascending, 2); - store.deleteByQuery(TEST_SOUP, querySpec); - JSONArray soupElt1Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt1Created)); JSONArray soupElt2Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt2Created)); JSONObject soupElt3Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt3Created)).getJSONObject(0); - - assertEquals("Should be empty", 0, soupElt1Retrieved.length()); - assertEquals("Should be empty", 0, soupElt2Retrieved.length()); + Assert.assertEquals("Should be empty", 0, soupElt1Retrieved.length()); + Assert.assertEquals("Should be empty", 0, soupElt2Retrieved.length()); JSONTestHelper.assertSameJSON("Retrieve mismatch", soupElt3Created, soupElt3Retrieved); // Check DB @@ -622,14 +605,13 @@ protected void tryDeleteByQuery(List idsDeleted, List idsNotDeleted) final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); String soupTableName = getSoupTableName(TEST_SOUP); c = DBHelper.getInstance(db).query(db, soupTableName, null, "id ASC", null, null); - assertTrue("Expected a soup element", c.moveToFirst()); - assertEquals("Expected one soup elements", 1, c.getCount()); - assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); + Assert.assertTrue("Expected a soup element", c.moveToFirst()); + Assert.assertEquals("Expected one soup elements", 1, c.getCount()); + Assert.assertEquals("Wrong id", idOf(soupElt3Created), c.getLong(c.getColumnIndex("id"))); } finally { safeClose(c); } - // Populate idsDeleted if (idsDeleted != null) { idsDeleted.add(id1); @@ -646,24 +628,21 @@ protected void tryDeleteByQuery(List idsDeleted, List idsNotDeleted) * Testing clear soup: create soup elements, clear soup and check database directly that there are in fact gone * @throws JSONException */ + @Test public void testClearSoup() throws JSONException { JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); - store.clearSoup(TEST_SOUP); - JSONArray soupElt1Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt1Created)); JSONArray soupElt2Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt2Created)); JSONArray soupElt3Retrieved = store.retrieve(TEST_SOUP, idOf(soupElt3Created)); - - assertEquals("Should be empty", 0, soupElt1Retrieved.length()); - assertEquals("Should be empty", 0, soupElt2Retrieved.length()); - assertEquals("Should be empty", 0, soupElt3Retrieved.length()); + Assert.assertEquals("Should be empty", 0, soupElt1Retrieved.length()); + Assert.assertEquals("Should be empty", 0, soupElt2Retrieved.length()); + Assert.assertEquals("Should be empty", 0, soupElt3Retrieved.length()); // Check DB Cursor c = null; @@ -671,7 +650,7 @@ public void testClearSoup() throws JSONException { final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); String soupTableName = getSoupTableName(TEST_SOUP); c = DBHelper.getInstance(db).query(db, soupTableName, null, "id ASC", null, null); - assertFalse("Expected no soup element", c.moveToFirst()); + Assert.assertFalse("Expected no soup element", c.moveToFirst()); } finally { safeClose(c); } @@ -681,6 +660,7 @@ public void testClearSoup() throws JSONException { * Test query when looking for all elements when soup has string index * @throws JSONException */ + @Test public void testAllQueryWithStringIndex() throws JSONException { tryAllQuery(Type.string); } @@ -689,6 +669,7 @@ public void testAllQueryWithStringIndex() throws JSONException { * Test query when looking for all elements when soup has json1 index * @throws JSONException */ + @Test public void testAllQueryWithJSON1Index() throws JSONException { tryAllQuery(Type.json1); } @@ -698,17 +679,16 @@ public void testAllQueryWithJSON1Index() throws JSONException { * @throws JSONException */ public void tryAllQuery(Type type) throws JSONException { + // Before - assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); + Assert.assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); // Register store.registerSoup(OTHER_TEST_SOUP, new IndexSpec[] {new IndexSpec("key", type)}); - assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1', 'otherValue':'ova1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2', 'otherValue':'ova2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3', 'otherValue':'ova3'}"); - JSONObject soupElt1Created = store.create(OTHER_TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(OTHER_TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(OTHER_TEST_SOUP, soupElt3); @@ -738,6 +718,7 @@ public void tryAllQuery(Type type) throws JSONException { * Test query when looking for a specific element with a string index * @throws JSONException */ + @Test public void testExactQueryWithStringIndex() throws JSONException { tryExactQuery(Type.string); } @@ -746,22 +727,22 @@ public void testExactQueryWithStringIndex() throws JSONException { * Test query when looking for a specific element with a json1 index * @throws JSONException */ + @Test public void testExactQueryWithJSON1Index() throws JSONException { tryExactQuery(Type.json1); } private void tryExactQuery(Type type) throws JSONException { + // Before - assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); + Assert.assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); // Register store.registerSoup(OTHER_TEST_SOUP, new IndexSpec[] {new IndexSpec("key", type)}); - assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1', 'otherValue':'ova1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2', 'otherValue':'ova2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3', 'otherValue':'ova3'}"); - store.create(OTHER_TEST_SOUP, soupElt1); JSONObject soupElt2Created= store.create(OTHER_TEST_SOUP, soupElt2); store.create(OTHER_TEST_SOUP, soupElt3); @@ -772,11 +753,11 @@ private void tryExactQuery(Type type) throws JSONException { 0, false, "SEARCH", soupElt2Created); } - /** * Query test looking for a range of elements (with ascending or descending ordering) with a string index * @throws JSONException */ + @Test public void testRangeQueryWithStringIndex() throws JSONException { tryRangeQuery(Type.string); } @@ -785,24 +766,24 @@ public void testRangeQueryWithStringIndex() throws JSONException { * Query test looking for a range of elements (with ascending or descending ordering) with a json1 index * @throws JSONException */ + @Test public void testRangeQueryWithJSON1Index() throws JSONException { tryRangeQuery(Type.json1); } private void tryRangeQuery(Type type) throws JSONException { + // Before - assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); + Assert.assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); // Register store.registerSoup(OTHER_TEST_SOUP, new IndexSpec[] {new IndexSpec("key", type)}); - assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); - - + Assert.assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1', 'otherValue':'ova1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2', 'otherValue':'ova2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3', 'otherValue':'ova3'}"); - /*JSONObjectsoupElt1Created = */store.create(OTHER_TEST_SOUP, soupElt1); + store.create(OTHER_TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(OTHER_TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(OTHER_TEST_SOUP, soupElt3); @@ -820,13 +801,13 @@ private void tryRangeQuery(Type type) throws JSONException { runQueryCheckResultsAndExplainPlan(OTHER_TEST_SOUP, QuerySpec.buildRangeQuerySpec(OTHER_TEST_SOUP, new String[]{"key"}, "key", "ka2", "ka3", "key", Order.descending, 10), 0, type != Type.json1, "SEARCH", new JSONArray("['ka3']"), new JSONArray("['ka2']")); - } /** * Query test looking using like (with ascending or descending ordering) and a string index * @throws JSONException */ + @Test public void testLikeQueryWithStringIndex() throws JSONException { tryLikeQuery(Type.string); } @@ -835,24 +816,23 @@ public void testLikeQueryWithStringIndex() throws JSONException { * Query test looking using like (with ascending or descending ordering) and a json1 index * @throws JSONException */ + @Test public void testLikeQueryWithJSON1Index() throws JSONException { tryLikeQuery(Type.json1); } private void tryLikeQuery(Type type) throws JSONException { - assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); + Assert.assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); store.registerSoup(OTHER_TEST_SOUP, new IndexSpec[] {new IndexSpec("key", type)}); - assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); - + Assert.assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); JSONObject soupElt1 = new JSONObject("{'key':'abcd', 'value':'va1', 'otherValue':'ova1'}"); JSONObject soupElt2 = new JSONObject("{'key':'bbcd', 'value':'va2', 'otherValue':'ova2'}"); JSONObject soupElt3 = new JSONObject("{'key':'abcc', 'value':'va3', 'otherValue':'ova3'}"); JSONObject soupElt4 = new JSONObject("{'key':'defg', 'value':'va4', 'otherValue':'ova3'}"); - JSONObject soupElt1Created = store.create(OTHER_TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(OTHER_TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(OTHER_TEST_SOUP, soupElt3); - /*JSONObject soupElt4Created = */ store.create(OTHER_TEST_SOUP, soupElt4); + store.create(OTHER_TEST_SOUP, soupElt4); // Like query (starts with) runQueryCheckResultsAndExplainPlan(OTHER_TEST_SOUP, QuerySpec.buildLikeQuerySpec(OTHER_TEST_SOUP, "key", "abc%", "key", Order.ascending, 10), 0, false, "SCAN", soupElt3Created, soupElt1Created); @@ -876,31 +856,34 @@ private void tryLikeQuery(Type type) throws JSONException { runQueryCheckResultsAndExplainPlan(OTHER_TEST_SOUP, QuerySpec.buildLikeQuerySpec(OTHER_TEST_SOUP, new String[] {"key"}, "key", "%bc%", "key", Order.descending, 10), 0, type != Type.json1, "SCAN", new JSONArray("['bbcd']"), new JSONArray("['abcd']"), new JSONArray("['abcc']")); - } protected void runQueryCheckResultsAndExplainPlan(String soupName, QuerySpec querySpec, int page, boolean covering, String expectedDbOperation, JSONObject... expectedResults) throws JSONException { + // Run query JSONArray result = store.query(querySpec, page); // Check results - assertEquals("Wrong number of results", expectedResults.length, result.length()); + Assert.assertEquals("Wrong number of results", expectedResults.length, result.length()); for (int i=0; i initialSize); + Assert.assertTrue("Database should be larger now", store.getDatabaseSize() > initialSize); } /** * Test registerSoup with json1 indexes * Register soup with multiple json1 indexes and a string index, check the underlying table and indexes in the database */ + @Test public void testRegisterSoupWithJSON1() throws JSONException { - assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); + Assert.assertFalse("Soup other_test_soup should not exist", store.hasSoup(OTHER_TEST_SOUP)); store.registerSoup(OTHER_TEST_SOUP, new IndexSpec[] {new IndexSpec("lastName", Type.json1), new IndexSpec("address.city", Type.json1), new IndexSpec("address.zipcode", Type.string)}); - assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); + Assert.assertTrue("Register soup call failed", store.hasSoup(OTHER_TEST_SOUP)); // Check columns of soup table String soupTableName = getSoupTableName(OTHER_TEST_SOUP); @@ -1240,15 +1230,15 @@ public void testRegisterSoupWithJSON1() throws JSONException { // Check soup indexes final IndexSpec[] indexSpecs = store.getSoupIndexSpecs(OTHER_TEST_SOUP); - assertEquals("Wrong path", "lastName", indexSpecs[0].path); - assertEquals("Wrong type", Type.json1, indexSpecs[0].type); - assertEquals("Wrong column name", "json_extract(soup, '$.lastName')", indexSpecs[0].columnName); - assertEquals("Wrong path", "address.city", indexSpecs[1].path); - assertEquals("Wrong type", Type.json1, indexSpecs[1].type); - assertEquals("Wrong column name", "json_extract(soup, '$.address.city')", indexSpecs[1].columnName); - assertEquals("Wrong path", "address.zipcode", indexSpecs[2].path); - assertEquals("Wrong type", Type.string, indexSpecs[2].type); - assertEquals("Wrong column name", soupTableName + "_2", indexSpecs[2].columnName); + Assert.assertEquals("Wrong path", "lastName", indexSpecs[0].path); + Assert.assertEquals("Wrong type", Type.json1, indexSpecs[0].type); + Assert.assertEquals("Wrong column name", "json_extract(soup, '$.lastName')", indexSpecs[0].columnName); + Assert.assertEquals("Wrong path", "address.city", indexSpecs[1].path); + Assert.assertEquals("Wrong type", Type.json1, indexSpecs[1].type); + Assert.assertEquals("Wrong column name", "json_extract(soup, '$.address.city')", indexSpecs[1].columnName); + Assert.assertEquals("Wrong path", "address.zipcode", indexSpecs[2].path); + Assert.assertEquals("Wrong type", Type.string, indexSpecs[2].type); + Assert.assertEquals("Wrong column name", soupTableName + "_2", indexSpecs[2].columnName); // Check db indexes checkDatabaseIndexes(soupTableName, Arrays.asList(new String[] { @@ -1264,13 +1254,14 @@ public void testRegisterSoupWithJSON1() throws JSONException { * Testing Delete: create multiple soup elements and alter the soup, after that delete a entry, then check them all * @throws JSONException */ + @Test public void testDeleteAgainstChangedSoup() throws JSONException { + //create a new soup with multiple entries JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); JSONObject soupElt4 = new JSONObject("{'key':'ka4', 'value':'va4'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); @@ -1294,6 +1285,7 @@ public void testDeleteAgainstChangedSoup() throws JSONException { protected void tryAllQueryOnChangedSoupWithUpdate(String soupName, JSONObject deletedEntry, String orderPath, IndexSpec[] newIndexSpecs, JSONObject... expectedResults) throws JSONException { + //alert the soup store.alterSoup(soupName, newIndexSpecs, true); @@ -1310,24 +1302,26 @@ protected void tryAllQueryOnChangedSoupWithUpdate(String soupName, JSONObject de * Testing Upsert: create multiple soup elements and alter the soup, after that upsert a entry, then check them all * @throws JSONException */ + @Test public void testUpsertAgainstChangedSoup() throws JSONException { + //create a new soup with multiple entries JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka2', 'value':'va2'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka3', 'value':'va3'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); - JSONObject soupElt1ForUpsert = new JSONObject("{'key':'ka1u', 'value':'va1u'}"); JSONObject soupElt2ForUpsert = new JSONObject("{'key':'ka2u', 'value':'va2u'}"); JSONObject soupElt3ForUpsert = new JSONObject("{'key':'ka3u', 'value':'va3u'}"); //CASE 1: index spec from key to value store.alterSoup(TEST_SOUP, new IndexSpec[]{new IndexSpec("value", Type.string)}, true); + //upsert an entry JSONObject soupElt1Upserted = store.upsert(TEST_SOUP, soupElt1ForUpsert); + // Query all - small page runQueryCheckResultsAndExplainPlan(TEST_SOUP, QuerySpec.buildAllQuerySpec(TEST_SOUP, "value", Order.ascending, 10), @@ -1335,8 +1329,10 @@ public void testUpsertAgainstChangedSoup() throws JSONException { //CASE 2: index spec from string to json1 store.alterSoup(TEST_SOUP, new IndexSpec[]{new IndexSpec("key", Type.json1)}, true); + //upsert an entry JSONObject soupElt2Upserted = store.upsert(TEST_SOUP, soupElt2ForUpsert); + // Query all - small page runQueryCheckResultsAndExplainPlan(TEST_SOUP, QuerySpec.buildAllQuerySpec(TEST_SOUP, "key", Order.ascending, 10), @@ -1344,8 +1340,10 @@ public void testUpsertAgainstChangedSoup() throws JSONException { //CASE 3: add a index spec field store.alterSoup(TEST_SOUP, new IndexSpec[]{new IndexSpec("key", Type.json1), new IndexSpec("value", Type.string)}, true); + //upsert an entry JSONObject soupElt3Upserted = store.upsert(TEST_SOUP, soupElt3ForUpsert); + // Query all - small page runQueryCheckResultsAndExplainPlan(TEST_SOUP, QuerySpec.buildAllQuerySpec(TEST_SOUP, "key", Order.ascending, 10), @@ -1356,12 +1354,13 @@ public void testUpsertAgainstChangedSoup() throws JSONException { * Testing Delete: create multiple soup elements and alter the soup, after that delete a entry, then check them all * @throws JSONException */ + @Test public void testExactQueryAgainstChangedSoup() throws JSONException { + //create a new soup with multiple entries JSONObject soupElt1 = new JSONObject("{'key':'ka1', 'value':'va1'}"); JSONObject soupElt2 = new JSONObject("{'key':'ka1-', 'value':'va1*'}"); JSONObject soupElt3 = new JSONObject("{'key':'ka1 ', 'value':'va1%'}"); - JSONObject soupElt1Created = store.create(TEST_SOUP, soupElt1); JSONObject soupElt2Created = store.create(TEST_SOUP, soupElt2); JSONObject soupElt3Created = store.create(TEST_SOUP, soupElt3); @@ -1384,7 +1383,8 @@ public void testExactQueryAgainstChangedSoup() throws JSONException { protected void tryExactQueryOnChangedSoup(String soupName, String orderPath, String value, IndexSpec[] newIndexSpecs, JSONObject expectedResult) throws JSONException { - //alert the soup + + // Alter the soup store.alterSoup(soupName, newIndexSpecs, true); // Exact Query @@ -1396,7 +1396,9 @@ protected void tryExactQueryOnChangedSoup(String soupName, String orderPath, Str /** * Test updateSoupNamesToAttrs */ + @Test public void testUpdateTableNameAndAddColumns() { + // Setup db and test values final SQLiteDatabase db = dbOpenHelper.getWritableDatabase(getEncryptionKey()); final String TEST_TABLE = "test_table"; @@ -1406,7 +1408,7 @@ public void testUpdateTableNameAndAddColumns() { // Ensure old table doesn't already exist Cursor cursor = db.query("sqlite_master", new String[] { "sql" }, "name = ?", new String[] { NEW_TEST_TABLE }, null, null, null); - assertEquals("New table should not already be in db.", 0, cursor.getCount()); + Assert.assertEquals("New table should not already be in db.", 0, cursor.getCount()); cursor.close(); // Test table renamed and column added @@ -1417,8 +1419,8 @@ public void testUpdateTableNameAndAddColumns() { cursor.moveToFirst(); String schema = cursor.getString(0); cursor.close(); - assertTrue("New table not found", schema.contains(NEW_TEST_TABLE)); - assertTrue("New column not found", schema.contains(NEW_COLUMN)); + Assert.assertTrue("New table not found", schema.contains(NEW_TEST_TABLE)); + Assert.assertTrue("New column not found", schema.contains(NEW_COLUMN)); // Clean up db.execSQL("DROP TABLE " + NEW_TEST_TABLE); @@ -1427,6 +1429,7 @@ public void testUpdateTableNameAndAddColumns() { /** * Ensure correct soup spec is returned from getSoupSpec */ + @Test public void testGetSoupSpec() throws JSONException { final String SOUP_SPEC_TEST = "soup_spec_test"; IndexSpec[] indexSpecs = new IndexSpec[] {new IndexSpec("index", Type.string)}; @@ -1437,11 +1440,11 @@ public void testGetSoupSpec() throws JSONException { SoupSpec result = store.getSoupSpec(TEST_SPEC.getSoupName()); // Verify the result - assertEquals("Soup name in soup spec is incorrect", SOUP_SPEC_TEST, result.getSoupName()); - assertEquals("Feature set in soup spec is incorrect", SoupSpec.FEATURE_EXTERNAL_STORAGE, result.getFeatures().get(0)); + Assert.assertEquals("Soup name in soup spec is incorrect", SOUP_SPEC_TEST, result.getSoupName()); + Assert.assertEquals("Feature set in soup spec is incorrect", SoupSpec.FEATURE_EXTERNAL_STORAGE, result.getFeatures().get(0)); // Verify JSON form - assertEquals("Soup name in json of soup spec is incorrect", SOUP_SPEC_TEST, result.toJSON().getString("name")); - assertEquals("Feature set in json of soup spec is incorrect", SoupSpec.FEATURE_EXTERNAL_STORAGE, result.toJSON().getJSONArray("features").get(0)); + Assert.assertEquals("Soup name in json of soup spec is incorrect", SOUP_SPEC_TEST, result.toJSON().getString("name")); + Assert.assertEquals("Feature set in json of soup spec is incorrect", SoupSpec.FEATURE_EXTERNAL_STORAGE, result.toJSON().getJSONArray("features").get(0)); } } diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreTestCase.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreTestCase.java index 2c538174d5..17d94409a1 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreTestCase.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SmartStoreTestCase.java @@ -26,13 +26,9 @@ */ package com.salesforce.androidsdk.store; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; +import android.content.Context; +import android.database.Cursor; +import android.support.test.InstrumentationRegistry; import com.salesforce.androidsdk.analytics.EventBuilderHelper; import com.salesforce.androidsdk.smartstore.store.DBHelper; @@ -41,29 +37,32 @@ import com.salesforce.androidsdk.smartstore.store.SmartStore; import com.salesforce.androidsdk.util.test.JSONTestHelper; +import junit.framework.Assert; + import net.sqlcipher.database.SQLiteDatabase; import net.sqlcipher.database.SQLiteOpenHelper; -import android.content.Context; -import android.database.Cursor; -import android.test.InstrumentationTestCase; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; /** * Abstract super class for smart store tests - * */ -public abstract class SmartStoreTestCase extends InstrumentationTestCase { +public abstract class SmartStoreTestCase { protected Context targetContext; protected SQLiteOpenHelper dbOpenHelper; protected SmartStore store; protected DBHelper dbHelper; - @Override - public void setUp() throws Exception { - super.setUp(); + protected void setUp() throws Exception { EventBuilderHelper.enableDisable(false); - targetContext = getInstrumentation().getTargetContext(); + targetContext = InstrumentationRegistry.getTargetContext(); dbOpenHelper = DBOpenHelper.getOpenHelper(targetContext, null); dbHelper = DBHelper.getInstance(dbOpenHelper.getWritableDatabase(getEncryptionKey())); store = new SmartStore(dbOpenHelper, getEncryptionKey()); @@ -71,13 +70,11 @@ public void setUp() throws Exception { protected abstract String getEncryptionKey(); - @Override protected void tearDown() throws Exception { store.dropAllSoups(); dbOpenHelper.close(); dbHelper.clearMemoryCache(); DBOpenHelper.deleteDatabase(targetContext, null); - super.tearDown(); } /** @@ -114,7 +111,7 @@ protected void checkColumns(String tableName, List expectedColumnNames) JSONTestHelper.assertSameJSONArray("Wrong columns", new JSONArray(expectedColumnNames), new JSONArray(actualColumnNames)); } catch (Exception e) { - fail("Failed with error:" + e.getMessage()); + Assert.fail("Failed with error:" + e.getMessage()); } finally { safeClose(c); @@ -140,13 +137,13 @@ protected void checkCreateTableStatement(String tableName, String subStringExpec try { List actualSqlStatements = new ArrayList<>(); c = db.rawQuery(String.format("SELECT sql FROM sqlite_master WHERE type='table' AND tbl_name='%s' ORDER BY name", tableName), null); - assertEquals("Expected one statement", 1, c.getCount()); + Assert.assertEquals("Expected one statement", 1, c.getCount()); c.moveToFirst(); String actualStatement = c.getString(0); - assertTrue("Wrong statement: " + actualStatement, actualStatement.contains(subStringExpected)); + Assert.assertTrue("Wrong statement: " + actualStatement, actualStatement.contains(subStringExpected)); } catch (Exception e) { - fail("Failed with error:" + e.getMessage()); + Assert.fail("Failed with error:" + e.getMessage()); } finally { safeClose(c); @@ -170,7 +167,7 @@ protected void checkDatabaseIndexes(String tableName, List expectedSqlSt JSONTestHelper.assertSameJSONArray("Wrong indexes", new JSONArray(expectedSqlStatements), new JSONArray(actualSqlStatements)); } catch (Exception e) { - fail("Failed with error:" + e.getMessage()); + Assert.fail("Failed with error:" + e.getMessage()); } finally { safeClose(c); @@ -184,25 +181,24 @@ protected void checkDatabaseIndexes(String tableName, List expectedSqlSt * @param covering * @param dbOperation e.g. SCAN or SEARCH */ - public void checkExplainQueryPlan(String soupName, int index, boolean covering, String dbOperation) throws JSONException { + protected void checkExplainQueryPlan(String soupName, int index, boolean covering, String dbOperation) throws JSONException { JSONObject explainQueryPlan = store.getLastExplainQueryPlan(); String soupTableName = getSoupTableName(soupName); String indexName = soupTableName + "_" + index + "_idx"; String expectedDetailPrefix = String.format("%s TABLE %s USING %sINDEX %s", dbOperation, soupTableName, covering ? "COVERING " : "", indexName); String detail = explainQueryPlan.getJSONArray(DBHelper.EXPLAIN_ROWS).getJSONObject(0).getString("detail"); - - assertTrue("Wrong query plan:" + detail, detail.startsWith(expectedDetailPrefix)); + Assert.assertTrue("Wrong query plan:" + detail, detail.startsWith(expectedDetailPrefix)); } - public void checkFileSystem(String soupName, long[] expectedIds, boolean shouldExist) { + protected void checkFileSystem(String soupName, long[] expectedIds, boolean shouldExist) { String soupTableName = getSoupTableName(soupName); for (long expectedId : expectedIds) { File file = ((DBOpenHelper) dbOpenHelper).getSoupBlobFile(soupTableName, expectedId); if (shouldExist) { - assertTrue("External file for " + expectedId + " should exist", file.exists()); + Assert.assertTrue("External file for " + expectedId + " should exist", file.exists()); } else { - assertFalse("External file for " + expectedId + " should not exist", file.exists()); + Assert.assertFalse("External file for " + expectedId + " should not exist", file.exists()); } } } @@ -241,4 +237,4 @@ public static long idOf(JSONObject soupElt) throws JSONException { protected void registerSoup(SmartStore store, String soupName, IndexSpec[] indexSpecs) { store.registerSoup(soupName, indexSpecs); } -} \ No newline at end of file +} diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SoupSpecTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SoupSpecTest.java index d5a4e59743..fc496dfa96 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SoupSpecTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/SoupSpecTest.java @@ -26,47 +26,52 @@ */ package com.salesforce.androidsdk.store; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + import com.salesforce.androidsdk.smartstore.store.SoupSpec; -import junit.framework.TestCase; +import junit.framework.Assert; import org.json.JSONException; import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; /** * Tests for SoupSpec */ -public class SoupSpecTest extends TestCase { +@RunWith(AndroidJUnit4.class) +@SmallTest +public class SoupSpecTest { + private static final String TEST_SOUP_NAME = "testSoupName"; private static final String TEST_FEATURE_1 = "testFeature1"; private static final String TEST_FEATURE_2 = "testFeature2"; + @Test public void testSoupSpecNameOnly() { - SoupSpec soupSpec = new SoupSpec(TEST_SOUP_NAME); - - assertEquals("SoupSpec does not have given soup name", TEST_SOUP_NAME, soupSpec.getSoupName()); - assertTrue("SoupSpec must not have any features", soupSpec.getFeatures().isEmpty()); + Assert.assertEquals("SoupSpec does not have given soup name", TEST_SOUP_NAME, soupSpec.getSoupName()); + Assert.assertTrue("SoupSpec must not have any features", soupSpec.getFeatures().isEmpty()); } + @Test public void testSoupSpecFeatures() { SoupSpec soupSpec = new SoupSpec(TEST_SOUP_NAME, TEST_FEATURE_1, TEST_FEATURE_2); - - assertEquals("SoupSpec does not have given soup name", TEST_SOUP_NAME, soupSpec.getSoupName()); - assertTrue("SoupSpec does not have given feature", soupSpec.getFeatures().contains(TEST_FEATURE_1)); - assertTrue("SoupSpec does not have given feature", soupSpec.getFeatures().contains(TEST_FEATURE_2)); - + Assert.assertEquals("SoupSpec does not have given soup name", TEST_SOUP_NAME, soupSpec.getSoupName()); + Assert.assertTrue("SoupSpec does not have given feature", soupSpec.getFeatures().contains(TEST_FEATURE_1)); + Assert.assertTrue("SoupSpec does not have given feature", soupSpec.getFeatures().contains(TEST_FEATURE_2)); soupSpec = new SoupSpec(TEST_SOUP_NAME, (String[]) null); - assertTrue("SoupSpec must not have any features", soupSpec.getFeatures().isEmpty()); + Assert.assertTrue("SoupSpec must not have any features", soupSpec.getFeatures().isEmpty()); } + @Test public void testToJSON() throws JSONException { SoupSpec soupSpec = new SoupSpec(TEST_SOUP_NAME, TEST_FEATURE_1, TEST_FEATURE_2); - JSONObject result = soupSpec.toJSON(); - - assertEquals("Soup name in json representation is incorrect.", TEST_SOUP_NAME, result.getString("name")); - assertEquals("Feature 1 in json representation is incorrect.", TEST_FEATURE_1, result.getJSONArray("features").get(0)); - assertEquals("Feature 1 in json representation is incorrect.", TEST_FEATURE_2, result.getJSONArray("features").get(1)); + Assert.assertEquals("Soup name in json representation is incorrect.", TEST_SOUP_NAME, result.getString("name")); + Assert.assertEquals("Feature 1 in json representation is incorrect.", TEST_FEATURE_1, result.getJSONArray("features").get(0)); + Assert.assertEquals("Feature 1 in json representation is incorrect.", TEST_FEATURE_2, result.getJSONArray("features").get(1)); } } diff --git a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/StoreConfigTest.java b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/StoreConfigTest.java index e8ee99588a..3d2740bd0a 100644 --- a/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/StoreConfigTest.java +++ b/libs/test/SmartStoreTest/src/com/salesforce/androidsdk/store/StoreConfigTest.java @@ -28,6 +28,9 @@ package com.salesforce.androidsdk.store; import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; import com.salesforce.androidsdk.MainActivity; import com.salesforce.androidsdk.smartstore.app.SmartStoreSDKManager; @@ -35,21 +38,28 @@ import com.salesforce.androidsdk.smartstore.store.SmartStore; import com.salesforce.androidsdk.ui.LoginActivity; +import junit.framework.Assert; + import org.json.JSONException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; import java.util.List; +@RunWith(AndroidJUnit4.class) +@SmallTest public class StoreConfigTest extends SmartStoreTestCase { private SmartStoreSDKManager sdkManager; private SmartStore globalStore; private SmartStore userStore; - @Override + @Before public void setUp() throws Exception { super.setUp(); - - SmartStoreSDKTestManager.init(getInstrumentation().getTargetContext(), store); + SmartStoreSDKTestManager.init(InstrumentationRegistry.getTargetContext(), store); sdkManager = SmartStoreSDKTestManager.getInstance(); globalStore = sdkManager.getGlobalSmartStore(); userStore = sdkManager.getSmartStore(); @@ -60,28 +70,27 @@ protected String getEncryptionKey() { return sdkManager.getEncryptionKey(); } - @Override + @After public void tearDown() throws Exception { sdkManager.removeAllGlobalStores(); super.tearDown(); } - + @Test public void testSetupGlobalStoreFromDefaultConfig() throws JSONException { - assertFalse(globalStore.hasSoup("globalSoup1")); - assertFalse(globalStore.hasSoup("globalSoup2")); + Assert.assertFalse(globalStore.hasSoup("globalSoup1")); + Assert.assertFalse(globalStore.hasSoup("globalSoup2")); // Setting up soup sdkManager.setupGlobalStoreFromDefaultConfig(); // Checking smartstore - assertTrue(globalStore.hasSoup("globalSoup1")); - assertTrue(globalStore.hasSoup("globalSoup2")); - + Assert.assertTrue(globalStore.hasSoup("globalSoup1")); + Assert.assertTrue(globalStore.hasSoup("globalSoup2")); List actualSoupNames = globalStore.getAllSoupNames(); - assertEquals("Wrong soups found", 2, actualSoupNames.size()); - assertTrue(actualSoupNames.contains("globalSoup1")); - assertTrue(actualSoupNames.contains("globalSoup2")); + Assert.assertEquals("Wrong soups found", 2, actualSoupNames.size()); + Assert.assertTrue(actualSoupNames.contains("globalSoup1")); + Assert.assertTrue(actualSoupNames.contains("globalSoup2")); // Checking first soup in details checkIndexSpecs("globalSoup1", new IndexSpec[]{ @@ -102,21 +111,21 @@ public void testSetupGlobalStoreFromDefaultConfig() throws JSONException { }); } + @Test public void testSetupUserStoreFromDefaultConfig() throws JSONException { - assertFalse(userStore.hasSoup("userSoup1")); - assertFalse(userStore.hasSoup("userSoup2")); + Assert.assertFalse(userStore.hasSoup("userSoup1")); + Assert.assertFalse(userStore.hasSoup("userSoup2")); // Setting up soup sdkManager.setupUserStoreFromDefaultConfig(); // Checking smartstore - assertTrue(userStore.hasSoup("userSoup1")); - assertTrue(userStore.hasSoup("userSoup2")); - + Assert.assertTrue(userStore.hasSoup("userSoup1")); + Assert.assertTrue(userStore.hasSoup("userSoup2")); List actualSoupNames = userStore.getAllSoupNames(); - assertEquals("Wrong soups found", 2, actualSoupNames.size()); - assertTrue(actualSoupNames.contains("userSoup1")); - assertTrue(actualSoupNames.contains("userSoup2")); + Assert.assertEquals("Wrong soups found", 2, actualSoupNames.size()); + Assert.assertTrue(actualSoupNames.contains("userSoup1")); + Assert.assertTrue(actualSoupNames.contains("userSoup2")); // Checking first soup in details checkIndexSpecs("userSoup1", new IndexSpec[]{ @@ -142,6 +151,7 @@ public void testSetupUserStoreFromDefaultConfig() throws JSONException { * That way we don't actually have to setup a user account */ private static class SmartStoreSDKTestManager extends SmartStoreSDKManager { + // We don't want to be using INSTANCE defined in SmartStoreSDKManager // Otherwise tests in other suites could fail after we call resetInstance(...) private static SmartStoreSDKTestManager TEST_INSTANCE = null; @@ -180,7 +190,7 @@ public static SmartStoreSDKManager getInstance() { if (TEST_INSTANCE != null) { return TEST_INSTANCE; } else { - throw new RuntimeException("Applications need to call SalesforceSDKManager.init() first."); + throw new RuntimeException("Applications need to call SmartStoreSDKManager.init() first."); } } diff --git a/libs/test/SmartSyncTest/AndroidManifest.xml b/libs/test/SmartSyncTest/AndroidManifest.xml index 2103bc1f09..5e1e738512 100644 --- a/libs/test/SmartSyncTest/AndroidManifest.xml +++ b/libs/test/SmartSyncTest/AndroidManifest.xml @@ -1,13 +1,10 @@ + package="com.salesforce.androidsdk.smartsync.tests"> @@ -19,14 +16,8 @@ - - - - diff --git a/native/NativeSampleApps/RestExplorer/build.gradle b/native/NativeSampleApps/RestExplorer/build.gradle index 9d5cac722f..ab823c6976 100644 --- a/native/NativeSampleApps/RestExplorer/build.gradle +++ b/native/NativeSampleApps/RestExplorer/build.gradle @@ -2,6 +2,15 @@ apply plugin: 'com.android.application' dependencies { api project(':libs:SalesforceSDK') + androidTestApi ('com.android.support.test:runner:1.0.1') { + exclude module: 'support-annotations' + } + androidTestApi ('com.android.support.test:rules:1.0.1') { + exclude module: 'support-annotations' + } + androidTestApi ('com.android.support.test.espresso:espresso-core:3.0.1') { + exclude module: 'support-annotations' + } } android { @@ -35,13 +44,14 @@ android { } defaultConfig { testApplicationId "com.salesforce.samples.restexplorer.tests" - testInstrumentationRunner "com.salesforce.androidsdk.analytics.util.test.JUnitReportTestRunner" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } packagingOptions { exclude 'META-INF/LICENSE' exclude 'META-INF/LICENSE.txt' exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/NOTICE' + pickFirst 'protobuf.meta' } lintOptions { diff --git a/native/NativeSampleApps/RestExplorer/src/com/salesforce/samples/restexplorer/ExplorerActivity.java b/native/NativeSampleApps/RestExplorer/src/com/salesforce/samples/restexplorer/ExplorerActivity.java index dcc4aa179e..fa0da65605 100644 --- a/native/NativeSampleApps/RestExplorer/src/com/salesforce/samples/restexplorer/ExplorerActivity.java +++ b/native/NativeSampleApps/RestExplorer/src/com/salesforce/samples/restexplorer/ExplorerActivity.java @@ -48,11 +48,9 @@ import com.salesforce.androidsdk.rest.RestRequest.RestMethod; import com.salesforce.androidsdk.rest.RestResponse; import com.salesforce.androidsdk.rest.files.FileRequests; -import com.salesforce.androidsdk.security.PasscodeManager; import com.salesforce.androidsdk.ui.SalesforceActivity; import com.salesforce.androidsdk.util.EventsObservable; import com.salesforce.androidsdk.util.EventsObservable.EventType; -import com.salesforce.androidsdk.util.UserSwitchReceiver; import org.json.JSONArray; import org.json.JSONObject; @@ -79,7 +77,6 @@ public class ExplorerActivity extends SalesforceActivity { private static final String DOUBLE_LINE = "=============================================================================="; private static final String SINGLE_LINE = "------------------------------------------------------------------------------"; - private PasscodeManager passcodeManager; private String apiVersion; private RestClient client; private TextView resultText; @@ -96,7 +93,6 @@ RestClient getClient() { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - passcodeManager = SalesforceSDKManager.getInstance().getPasscodeManager(); apiVersion = ApiVersionStrings.getVersionNumber(this); setContentView(R.layout.explorer); tabHost = (TabHost) findViewById(android.R.id.tabhost); @@ -136,8 +132,6 @@ public void onResume(RestClient client) { this.client = client; } - - /** * Returns the logout dialog fragment (used mainly by tests). * @@ -811,5 +805,4 @@ private void fixAutoCompleteFields(int... fieldIds) { .toArray(new String[] {}))); } } - } diff --git a/native/NativeSampleApps/test/RestExplorerTest/AndroidManifest.xml b/native/NativeSampleApps/test/RestExplorerTest/AndroidManifest.xml index 1cbae01c6d..7d96e8f8b7 100644 --- a/native/NativeSampleApps/test/RestExplorerTest/AndroidManifest.xml +++ b/native/NativeSampleApps/test/RestExplorerTest/AndroidManifest.xml @@ -1,17 +1,9 @@ + package="com.salesforce.samples.restexplorer.tests"> - - - - - + diff --git a/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/ExplorerActivityTest.java b/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/ExplorerActivityTest.java index b11372840a..00b4f75bdc 100644 --- a/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/ExplorerActivityTest.java +++ b/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/ExplorerActivityTest.java @@ -28,12 +28,11 @@ import android.accounts.AccountManager; import android.app.AlertDialog; import android.content.Context; -import android.test.ActivityInstrumentationTestCase2; -import android.view.View; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; import android.widget.Button; -import android.widget.EditText; -import android.widget.RadioButton; -import android.widget.TabHost; import android.widget.TextView; import com.salesforce.androidsdk.accounts.UserAccount; @@ -45,6 +44,14 @@ import com.salesforce.androidsdk.util.EventsObservable.EventType; import com.salesforce.androidsdk.util.test.EventsListenerQueue; +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.io.IOException; import java.net.HttpURLConnection; @@ -57,15 +64,22 @@ import okhttp3.ResponseBody; import okio.Buffer; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; +import static android.support.test.espresso.action.ViewActions.replaceText; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + /** - * Tests for ExplorerActivity + * Tests for ExplorerActivity. * * NB: we are not actually talking to a live server * instead we inject a mock http accessor in the RestClient * and make sure that the http requests coming through are as expected (method/path/body) */ -public class ExplorerActivityTest extends - ActivityInstrumentationTestCase2 { +@RunWith(AndroidJUnit4.class) +@LargeTest +public class ExplorerActivityTest { private static final String TEST_ORG_ID = "test_org_id"; private static final String TEST_USER_ID = "test_user_id"; @@ -78,75 +92,75 @@ public class ExplorerActivityTest extends private static final String TEST_USERNAME = "test_username"; private static final String TEST_ACCOUNT_NAME = "test_account_name (https://cs1.salesforce.com) (RestExplorerTest)"; - private static final int VERSIONS_TAB = 0; - private static final int RESOURCES_TAB = 1; - private static final int DESCRIBE_GLOBAL_TAB = 2; - private static final int METADATA_TAB = 3; - private static final int DESCRIBE_TAB = 4; - private static final int CREATE_TAB = 5; - private static final int RETRIEVE_TAB = 6; - private static final int UPDATE_TAB = 7; - private static final int UPSERT_TAB = 8; - private static final int DELETE_TAB = 9; - private static final int QUERY_TAB = 10; - private static final int SEARCH_TAB = 11; - private static final int MANUAL_REQUEST_TAB = 12; - private static final int SEARCH_SCOPE_AND_ORDER_TAB = 13; - private static final int SEARCH_RESULT_LAYOUT_TAB = 14; - private static final int OWNED_FILES_LIST_TAB = 15; - private static final int FILES_IN_USERS_GROUPS_TAB = 16; - private static final int FILES_SHARED_WITH_USER_TAB = 17; - private static final int FILE_DETAILS_TAB = 18; - private static final int BATCH_FILE_DETAILS_TAB = 19; - private static final int FILE_SHARES_TAB = 20; - private static final int ADD_FILE_SHARE_TAB = 21; - private static final int DELETE_FILE_SHARE_TAB = 22; - + private static final String VERSIONS_TAB = "versions"; + private static final String RESOURCES_TAB = "resources"; + private static final String DESCRIBE_GLOBAL_TAB = "describe_global"; + private static final String METADATA_TAB = "metadata"; + private static final String DESCRIBE_TAB = "describe"; + private static final String CREATE_TAB = "create"; + private static final String RETRIEVE_TAB = "retrieve"; + private static final String UPDATE_TAB = "update"; + private static final String UPSERT_TAB = "upsert"; + private static final String DELETE_TAB = "delete"; + private static final String QUERY_TAB = "query"; + private static final String SEARCH_TAB = "search"; + private static final String MANUAL_REQUEST_TAB = "manual"; + private static final String SEARCH_SCOPE_AND_ORDER_TAB = "search_scope_and_order"; + private static final String SEARCH_RESULT_LAYOUT_TAB = "search_result_layout"; + private static final String OWNED_FILES_LIST_TAB = "owned_files_list"; + private static final String FILES_IN_USERS_GROUPS_TAB = "files_in_users_groups"; + private static final String FILES_SHARED_WITH_USER_TAB = "files_shared_with_user"; + private static final String FILE_DETAILS_TAB = "file_details"; + private static final String BATCH_FILE_DETAILS_TAB = "batch_file_details"; + private static final String FILE_SHARES_TAB = "files_shares"; + private static final String ADD_FILE_SHARE_TAB = "add_file_share"; + private static final String DELETE_FILE_SHARE_TAB = "delete_file_share"; public static final MediaType MEDIA_TYPE_PLAIN = okhttp3.MediaType.parse("text/plain; charset=utf-8"); - private EventsListenerQueue eq; private Context targetContext; private ClientManager clientManager; public static volatile String RESPONSE = null; - public ExplorerActivityTest() { - super(ExplorerActivity.class); - } - - @Override - public void setUp() throws Exception { - super.setUp(); - setActivityInitialTouchMode(false); - eq = new EventsListenerQueue(); + /** + * Custom activity launch rules to run steps before the activity is launched. + * + * @param Activity. + */ + public class ExplorerActivityRule extends ActivityTestRule { - // Waits for app initialization to complete. - if (!SalesforceSDKManager.hasInstance()) { - eq.waitForEvent(EventType.AppCreateComplete, 5000); + public ExplorerActivityRule(Class activityClass) { + super(activityClass); } - targetContext = getInstrumentation().getTargetContext(); - clientManager = new ClientManager(targetContext, targetContext.getString(R.string.account_type), null, SalesforceSDKManager.getInstance().shouldLogoutWhenTokenRevoked()); - clientManager.createNewAccount(TEST_ACCOUNT_NAME, TEST_USERNAME, TEST_REFRESH_TOKEN, - TEST_ACCESS_TOKEN, TEST_INSTANCE_URL, TEST_LOGIN_URL, TEST_IDENTITY_URL, TEST_CLIENT_ID, - TEST_ORG_ID, TEST_USER_ID, null, null, null, null, null, null, null, null, null); - SalesforceSDKManager.getInstance().getPasscodeManager().setTimeoutMs(0); - final AccountManager accountManager = AccountManager.get(targetContext); - - /* - * Since we are using bogus credentials, we need to explicitly set the auth token value to - * prevent ClientManager from attempting a refresh with the bogus refresh token. - */ - accountManager.setAuthToken(clientManager.getAccount(), AccountManager.KEY_AUTHTOKEN, TEST_ACCESS_TOKEN); - // Plug a modified OkHttpClient that doesn't actually go to the server. - final ExplorerActivity activity = getActivity(); - assertNotNull("Activity should not be null", activity); - final RestClient client = activity.getClient(); - assertNotNull("Rest client should not be null", client); - final OkHttpClient mockOkHttpClient = buildMockOkHttpClient(); - client.setOkHttpClient(mockOkHttpClient); + @Override + protected void beforeActivityLaunched() { + super.beforeActivityLaunched(); + eq = new EventsListenerQueue(); + + // Waits for app initialization to complete. + if (!SalesforceSDKManager.hasInstance()) { + eq.waitForEvent(EventType.AppCreateComplete, 5000); + } + targetContext = InstrumentationRegistry.getTargetContext(); + clientManager = new ClientManager(targetContext, targetContext.getString(R.string.account_type), null, SalesforceSDKManager.getInstance().shouldLogoutWhenTokenRevoked()); + clientManager.createNewAccount(TEST_ACCOUNT_NAME, TEST_USERNAME, TEST_REFRESH_TOKEN, + TEST_ACCESS_TOKEN, TEST_INSTANCE_URL, TEST_LOGIN_URL, TEST_IDENTITY_URL, TEST_CLIENT_ID, + TEST_ORG_ID, TEST_USER_ID, null, null, null, null, null, null, null, null, null); + SalesforceSDKManager.getInstance().getPasscodeManager().setTimeoutMs(0); + final AccountManager accountManager = AccountManager.get(targetContext); + + /* + * Since we are using bogus credentials, we need to explicitly set the auth token value to + * prevent ClientManager from attempting a refresh with the bogus refresh token. + */ + accountManager.setAuthToken(clientManager.getAccount(), AccountManager.KEY_AUTHTOKEN, TEST_ACCESS_TOKEN); + } } + @Rule + public ExplorerActivityRule explorerActivityTestRule = new ExplorerActivityRule<>(ExplorerActivity.class); + private OkHttpClient buildMockOkHttpClient() { OkHttpClient.Builder builder = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @@ -158,11 +172,9 @@ public Response intercept(Chain chain) throws IOException { final Buffer buffer = new Buffer(); request.body().writeTo(buffer); requestBody = " " + buffer.readUtf8(); - } - else { + } else { requestBody = ""; } - RESPONSE = "[" + request.method() + " " + request.url() + requestBody + "]"; Response response = new Response.Builder() .request(request) @@ -176,95 +188,110 @@ public Response intercept(Chain chain) throws IOException { return builder.build(); } - @Override + @Before + public void setUp() throws Exception { + + // Plug a modified OkHttpClient that doesn't actually go to the server. + final ExplorerActivity activity = explorerActivityTestRule.getActivity(); + Assert.assertNotNull("Activity should not be null", activity); + final RestClient client = activity.getClient(); + Assert.assertNotNull("Rest client should not be null", client); + final OkHttpClient mockOkHttpClient = buildMockOkHttpClient(); + client.setOkHttpClient(mockOkHttpClient); + } + + @After public void tearDown() throws Exception { if (eq != null) { eq.tearDown(); eq = null; } RESPONSE = null; - super.tearDown(); } /** * Test clicking clear. */ + @Test public void testClickClear() { - TextView resultText = (TextView) getActivity().findViewById(R.id.result_text); + TextView resultText = explorerActivityTestRule.getActivity().findViewById(R.id.result_text); // Putting some text in the result text area setText(R.id.result_text, "dummy-text"); - assertFalse("Result text area should not be empty", resultText.getText().length() == 0); + Assert.assertFalse("Result text area should not be empty", resultText.getText().length() == 0); // Click on clear - clickView(getActivity().findViewById(R.id.clear_button)); + clickView(R.id.clear_button); // Check that result text has been cleared - assertEquals("Result text area should habe been cleared", 0, resultText.getText().length()); + Assert.assertEquals("Result text area should habe been cleared", 0, resultText.getText().length()); } /** * Test clicking logout and then canceling out. */ + @Test public void testClickLogoutThenCancel() { // Click on logout - clickView(getActivity().findViewById(R.id.logout_button)); - waitSome(); - waitSome(); // wait more to avoid flapping + clickView(R.id.logout_button); + //waitSome(); + //waitSome(); // wait more to avoid flapping // Check that confirmation dialog is shown - final ExplorerActivity activity = getActivity(); - assertNotNull("Activity should not be null", activity); + final ExplorerActivity activity = explorerActivityTestRule.getActivity(); + Assert.assertNotNull("Activity should not be null", activity); final LogoutDialogFragment logoutFrag = activity.getLogoutConfirmationDialog(); - assertNotNull("Logout dialog fragment should not be null", logoutFrag); + Assert.assertNotNull("Logout dialog fragment should not be null", logoutFrag); final AlertDialog dialog = (AlertDialog) logoutFrag.getDialog(); - assertNotNull("Logout dialog should not be null", dialog); - // FLAPPING // assertTrue("Logout confirmation dialog should be showing", dialog.isShowing()); + Assert.assertNotNull("Logout dialog should not be null", dialog); + Assert.assertTrue("Logout confirmation dialog should be showing", dialog.isShowing()); // Click no - clickView(dialog.getButton(AlertDialog.BUTTON_NEGATIVE)); + dialog.getButton(AlertDialog.BUTTON_NEGATIVE).performClick(); // Wait for dialog to go - waitSome(); + //waitSome(); // Check that confirmation dialog is no longer shown - // FLAPPING // assertFalse("Logout confirmation dialog should no longer be showing", dialog.isShowing()); + Assert.assertFalse("Logout confirmation dialog should no longer be showing", dialog.isShowing()); } /** * Test clicking logout and then clicking yes - make sure we end up removing * the account. */ + @Test public void testClickLogoutThenConfirm() { // Click on logout - clickView(getActivity().findViewById(R.id.logout_button)); - waitSome(); + clickView(R.id.logout_button); + //waitSome(); // Check that confirmation dialog is shown - final ExplorerActivity activity = getActivity(); - assertNotNull("Activity should not be null", activity); + final ExplorerActivity activity = explorerActivityTestRule.getActivity(); + Assert.assertNotNull("Activity should not be null", activity); final LogoutDialogFragment logoutFrag = activity.getLogoutConfirmationDialog(); - assertNotNull("Logout dialog fragment should not be null", logoutFrag); + Assert.assertNotNull("Logout dialog fragment should not be null", logoutFrag); final AlertDialog dialog = (AlertDialog) logoutFrag.getDialog(); - assertNotNull("Logout dialog should not be null", dialog); - // FLAPPING // assertTrue("Logout confirmation dialog should be showing", dialog.isShowing()); + Assert.assertNotNull("Logout dialog should not be null", dialog); + Assert.assertTrue("Logout confirmation dialog should be showing", dialog.isShowing()); final UserAccountManager userAccMgr = SalesforceSDKManager.getInstance().getUserAccountManager(); UserAccount curUser = userAccMgr.getCurrentUser(); - assertNotNull("Current user should not be null", curUser); + Assert.assertNotNull("Current user should not be null", curUser); // Click yes - clickView(dialog.getButton(AlertDialog.BUTTON_POSITIVE)); + dialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick(); final EventsListenerQueue eq = new EventsListenerQueue(); eq.waitForEvent(EventType.LogoutComplete, 30000); curUser = userAccMgr.getCurrentUser(); - assertNull("Current user should be null", curUser); + Assert.assertNull("Current user should be null", curUser); } /** * Test going to versions tab - check UI and click "Go". */ + @Test public void testGetVersions() { gotoTabAndRunAction(VERSIONS_TAB, R.id.versions_button, "Go", null, "[GET " + TEST_INSTANCE_URL + "/services/data/]"); } @@ -272,6 +299,7 @@ public void testGetVersions() { /** * Test going to resources tab - check UI and click "Go". */ + @Test public void testGetResources() { gotoTabAndRunAction(RESOURCES_TAB, R.id.resources_button, "Go", null, "[GET " + TEST_INSTANCE_URL + "/services/data/" + ApiVersionStrings.getVersionNumber(targetContext) + "/]"); } @@ -279,6 +307,7 @@ public void testGetResources() { /** * Test going to describe global tab - check UI and click "Go". */ + @Test public void testDescribeGlobal() { gotoTabAndRunAction(DESCRIBE_GLOBAL_TAB, R.id.describe_global_button, "Go", null, "[GET " + TEST_INSTANCE_URL + "/services/data/" + ApiVersionStrings.getVersionNumber(targetContext) + "/sobjects/]"); } @@ -286,6 +315,7 @@ public void testDescribeGlobal() { /** * Test going to metadata tab - check UI and click "Go". */ + @Test public void testGetMetadata() { Runnable extraSetup = new Runnable() { @Override @@ -299,6 +329,7 @@ public void run() { /** * Test going to describe tab - check UI and click "Go". */ + @Test public void testDescribe() { Runnable extraSetup = new Runnable() { @Override @@ -312,6 +343,7 @@ public void run() { /** * Test going to create tab - check UI and click "Go". */ + @Test public void testCreate() { Runnable extraSetup = new Runnable() { @Override @@ -326,6 +358,7 @@ public void run() { /** * Test going to retrieve tab - check UI and click "Go". */ + @Test public void testRetrieve() { Runnable extraSetup = new Runnable() { @Override @@ -342,6 +375,7 @@ public void run() { /** * Test going to update tab - check UI and click "Go". */ + @Test public void testUpdate() { Runnable extraSetup = new Runnable() { @Override @@ -357,6 +391,7 @@ public void run() { /** * Test going to upsert tab - check UI and click "Go". */ + @Test public void testUpsert() { Runnable extraSetup = new Runnable() { @Override @@ -373,6 +408,7 @@ public void run() { /** * Test going to delete tab - check UI and click "Go". */ + @Test public void testDelete() { Runnable extraSetup = new Runnable() { @Override @@ -388,6 +424,7 @@ public void run() { /** * Test going to query tab - check UI and click "Go". */ + @Test public void testQuery() { Runnable extraSetup = new Runnable() { @Override @@ -402,6 +439,7 @@ public void run() { /** * Test going to search tab - check UI and click "Go". */ + @Test public void testSearch() { Runnable extraSetup = new Runnable() { @Override @@ -416,6 +454,7 @@ public void run() { /** * Test going to manual request tab - check UI and click "Go". */ + @Test public void testManualRequest() { Runnable extraSetup = new Runnable() { @Override @@ -431,6 +470,7 @@ public void run() { /** * Test going to search scope and order tab - check UI and click "Go". */ + @Test public void testSearchScopeAndOrderTab() { gotoTabAndRunAction(SEARCH_SCOPE_AND_ORDER_TAB, R.id.search_scope_and_order_button, "Go", null, "[GET " + TEST_INSTANCE_URL + "/services/data/" + ApiVersionStrings.getVersionNumber(targetContext) + "/search/scopeOrder]"); } @@ -438,6 +478,7 @@ public void testSearchScopeAndOrderTab() { /** * Test going to search result layout tab - check UI and click "Go". */ + @Test public void testSearchResultLayout() { Runnable extraSetup = new Runnable() { @Override @@ -451,6 +492,7 @@ public void run() { /** * Test going to owned files list tab - check UI and click "Go". */ + @Test public void testOwnedFilesList() { Runnable extraSetup = new Runnable() { @Override @@ -465,6 +507,7 @@ public void run() { /** * Test going to files in users groups tab - check UI and click "Go". */ + @Test public void testFilesInUsersGroups() { Runnable extraSetup = new Runnable() { @Override @@ -479,6 +522,7 @@ public void run() { /** * Test going to files shared with user tab - check UI and click "Go". */ + @Test public void testFilesSharedWithUser() { Runnable extraSetup = new Runnable() { @Override @@ -493,6 +537,7 @@ public void run() { /** * Test going to file details tab - check UI and click "Go". */ + @Test public void testFileDetails() { Runnable extraSetup = new Runnable() { @Override @@ -507,6 +552,7 @@ public void run() { /** * Test going to batch file details tab - check UI and click "Go". */ + @Test public void testBatchFileDetails() { Runnable extraSetup = new Runnable() { @Override @@ -520,6 +566,7 @@ public void run() { /** * Test going to file shares tab - check UI and click "Go". */ + @Test public void testFileShares() { Runnable extraSetup = new Runnable() { @Override @@ -534,6 +581,7 @@ public void run() { /** * Test going to add file share tab - check UI and click "Go". */ + @Test public void testAddFileShare() { Runnable extraSetup = new Runnable() { @Override @@ -549,6 +597,7 @@ public void run() { /** * Test going to delete file share tab - check UI and click "Go". */ + @Test public void testDeleteFileShare() { Runnable extraSetup = new Runnable() { @Override @@ -559,28 +608,16 @@ public void run() { gotoTabAndRunAction(DELETE_FILE_SHARE_TAB, R.id.delete_file_share_button, "Go", extraSetup, "[DELETE " + TEST_INSTANCE_URL + "/services/data/" + ApiVersionStrings.getVersionNumber(targetContext) + "/sobjects/ContentDocumentLink/shareIdToDelete]"); } - /** - * Go to tab (tabId), check button (goButtonId) label is as expected (goButtonLabel) - * Do any extra setup (extraSetup) - * Click on button and check response is as expected (expectedResponse) - * - * @param tabIndex - * @param goButtonId - * @param goButtonLabel - * @param extraSetup - * @param expectedResponse - */ - private void gotoTabAndRunAction(int tabIndex, int goButtonId, String goButtonLabel, Runnable extraSetup, String expectedResponse) { + private void gotoTabAndRunAction(String tabTag, int goButtonId, String goButtonLabel, Runnable extraSetup, String expectedResponse) { // Go to tab - final ExplorerActivity activity = getActivity(); - assertNotNull("Activity should not be null", activity); - TabHost tabHost = (TabHost) activity.findViewById(android.R.id.tabhost); - clickTab(tabHost, tabIndex); + final ExplorerActivity activity = explorerActivityTestRule.getActivity(); + Assert.assertNotNull("Activity should not be null", activity); + clickTab(R.id.versions_tab); // Check UI - Button runButton = (Button) activity.findViewById(goButtonId); - assertEquals(goButtonLabel + " button has wrong label", goButtonLabel, runButton.getText()); + Button runButton = activity.findViewById(goButtonId); + Assert.assertEquals(goButtonLabel + " button has wrong label", goButtonLabel, runButton.getText()); // Do any extra setup if (extraSetup != null) { @@ -588,7 +625,7 @@ private void gotoTabAndRunAction(int tabIndex, int goButtonId, String goButtonLa } // Click resources button - clickView(runButton); + clickView(goButtonId); // Wait for call to complete long curTime = System.currentTimeMillis(); @@ -598,26 +635,19 @@ private void gotoTabAndRunAction(int tabIndex, int goButtonId, String goButtonLa break; } } - assertEquals("Wrong request executed", expectedResponse, RESPONSE); + Assert.assertEquals("Wrong request executed", expectedResponse, RESPONSE); // Check result area waitForRender(); TextView resultText = (TextView) activity.findViewById(R.id.result_text); - assertTrue("Response not found in text area", resultText.getText().toString().indexOf(expectedResponse) > 0); + Assert.assertTrue("Response not found in text area", resultText.getText().toString().indexOf(expectedResponse) > 0); } private void setText(final int textViewId, final String text) { try { - runTestOnUiThread(new Runnable() { - @Override public void run() { - TextView v = (TextView) getActivity().findViewById(textViewId); - v.setText(text); - if (v instanceof EditText) - ((EditText) v).setSelection(v.getText().length()); - } - }); + onView(withId(textViewId)).perform(replaceText(text), closeSoftKeyboard()); } catch (Throwable t) { - fail("Failed to set text " + text); + Assert.fail("Failed to set text " + text); } } @@ -625,17 +655,11 @@ private void waitForRender() { eq.waitForEvent(EventType.RenditionComplete, 5000); } - private void clickTab(final TabHost tabHost, final int tabIndex) { + private void clickTab(final int tabId) { try { - runTestOnUiThread(new Runnable() { - - @Override - public void run() { - tabHost.setCurrentTab(tabIndex); - } - }); + onView(withId(tabId)).perform(click()); } catch (Throwable t) { - fail("Failed to click tab " + tabIndex); + Assert.fail("Failed to click tab " + tabId); } } @@ -643,36 +667,15 @@ private void waitSome() { try { Thread.sleep(500); } catch (InterruptedException e) { - fail("Test interrupted"); + Assert.fail("Test interrupted"); } } - private void clickView(final View v) { - try { - runTestOnUiThread(new Runnable() { - - @Override - public void run() { - v.performClick(); - } - }); - } catch (Throwable t) { - fail("Failed to click view " + v); - } + private void clickView(final int viewId) { + onView(withId(viewId)).perform(click()); } private void checkRadioButton(final int radioButtonId) { - try { - runTestOnUiThread(new Runnable() { - - @Override - public void run() { - RadioButton v = (RadioButton) getActivity().findViewById(radioButtonId); - v.setChecked(true); - } - }); - } catch (Throwable t) { - fail("Failed to check radio button " + radioButtonId); - } + onView(withId(radioButtonId)).perform(click()); } } diff --git a/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/PasscodeActivityTest.java b/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/PasscodeActivityTest.java new file mode 100644 index 0000000000..f6dc17fd83 --- /dev/null +++ b/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/PasscodeActivityTest.java @@ -0,0 +1,530 @@ +/* + * Copyright (c) 2011-present, salesforce.com, inc. + * All rights reserved. + * Redistribution and use of this software in source and binary forms, with or + * without modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of salesforce.com, inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission of salesforce.com, inc. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package com.salesforce.samples.restexplorer; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; +import android.widget.TextView; + +import com.salesforce.androidsdk.app.SalesforceSDKManager; +import com.salesforce.androidsdk.security.PasscodeManager; +import com.salesforce.androidsdk.ui.PasscodeActivity; +import com.salesforce.androidsdk.ui.PasscodeActivity.PasscodeMode; +import com.salesforce.androidsdk.util.EventsObservable.EventType; +import com.salesforce.androidsdk.util.test.EventsListenerQueue; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; +import static android.support.test.espresso.action.ViewActions.pressImeActionButton; +import static android.support.test.espresso.action.ViewActions.replaceText; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +/** + * Tests for PasscodeActivity. + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class PasscodeActivityTest { + + private EventsListenerQueue eq; + private Context targetContext; + private PasscodeActivity passcodeActivity; + private PasscodeManager passcodeManager; + + /** + * Custom activity launch rules to run steps before the activity is launched. + * + * @param Activity. + */ + public class PasscodeActivityRule extends ActivityTestRule { + + public PasscodeActivityRule(Class activityClass) { + super(activityClass); + } + + @Override + protected void beforeActivityLaunched() { + eq = new EventsListenerQueue(); + + // Waits for app initialization to complete. + if (!SalesforceSDKManager.hasInstance()) { + eq.waitForEvent(EventType.AppCreateComplete, 5000); + } + targetContext = InstrumentationRegistry.getTargetContext(); + passcodeManager = SalesforceSDKManager.getInstance().getPasscodeManager(); + passcodeManager.reset(targetContext); + passcodeManager.setTimeoutMs(600000); + } + } + + @Rule + public PasscodeActivityRule passcodeActivityTestRule = new PasscodeActivityRule<>(PasscodeActivity.class); + + @Before + public void setUp() throws Exception { + Assert.assertTrue("Application should be locked", passcodeManager.isLocked()); + Assert.assertFalse("Application should not have a passcode", passcodeManager.hasStoredPasscode(targetContext)); + } + + @After + public void tearDown() throws Exception { + if (passcodeActivity != null) { + passcodeActivity.finish(); + passcodeActivity = null; + } + if (eq != null) { + eq.tearDown(); + eq = null; + } + } + + /** + * Test passcode creation flow when no mistakes are made by user. + */ + @Test + public void testCreateWithNoMistakes() { + + // Get activity + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); + + // Entering in 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); + Assert.assertTrue("Error message should be empty", TextUtils.isEmpty( + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText())); + + // Re-entering 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertFalse("Application should be unlocked", passcodeManager.isLocked()); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + } + + /** + * Test passcode change flow when no mistakes are made by user. + */ + @Test + public void testChangeWithNoMistakes() { + + // Get activity + final Intent i = new Intent(SalesforceSDKManager.getInstance().getAppContext(), + SalesforceSDKManager.getInstance().getPasscodeActivity()); + i.putExtra(PasscodeManager.CHANGE_PASSCODE_KEY, true); + passcodeActivityTestRule.launchActivity(i); + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in change mode", PasscodeMode.Change, passcodeActivity.getMode()); + + // Entering in 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); + Assert.assertTrue("Error message should be empty", TextUtils.isEmpty( + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText())); + + // Re-entering 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertFalse("Application should be unlocked", passcodeManager.isLocked()); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + } + + /** + * Test passcode creation flow when user try to enter a passcode too short. + */ + @Test + public void testCreateWithPasscodeTooShort() { + + // Get activity + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); + + // Entering nothing and submitting -> expect passcode too short error + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, ""); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in create mode still", PasscodeMode.Create, passcodeActivity.getMode()); + Assert.assertEquals("Error expected", "The passcode must be at least 4 characters long", + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); + + // Entering in 123 and submitting -> expect passcode too short error + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in create mode still", PasscodeMode.Create, passcodeActivity.getMode()); + Assert.assertEquals("Error expected", "The passcode must be at least 4 characters long", + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); + + // Entering in 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in create confirm mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); + + // Re-entering 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertFalse("Application should be unlocked", passcodeManager.isLocked()); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + } + + /** + * Test passcode creation flow when user try to enter a passcode matching the minimum value. + */ + @Test + public void testCreatewithPasscodeMinimumLength() { + + // Get activity + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); + + // Entering nothing and submitting -> expect passcode too short error + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "1234"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in create mode still", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); + Assert.assertTrue("Error Message should be empty", TextUtils.isEmpty( + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText())); + } + + /** + * Test passcode creation flow when user enter a passcode too short during confirmation. + */ + @Test + public void testCreateWithConfirmPasscodeTooShort() { + + // Get activity + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); + + // Entering in 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); + + // Entering in 123 and submitting -> expect passcode too short error + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in create confirm mode still", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); + Assert.assertEquals("Error expected", "The passcode must be at least 4 characters long", + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); + + // Entering 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertFalse("Application should be unlocked", passcodeManager.isLocked()); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + } + + /** + * Test passcode creation flow when user enter a different passcode during confirmation. + */ + @Test + public void testCreateWithWrongConfirmPasscode() { + + // Get activity + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); + + // Entering in 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should be still locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); + + // Entering in 654321 and submitting -> expect passcodes don't match error + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "654321"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should be still locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in create confirm mode still", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); + Assert.assertEquals("Error expected", "Passcodes don't match!", + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); + + // Entering 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertFalse("Application should be unlocked", passcodeManager.isLocked()); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + } + + /** + * Test passcode verification flow when no mistakes are made by user. + */ + @Test + public void testVerificationWithNoMistakes() { + + // Store passcode and set mode to Check + passcodeManager.store(targetContext, "123456"); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + + // Get activity + final Intent i = new Intent(SalesforceSDKManager.getInstance().getAppContext(), + SalesforceSDKManager.getInstance().getPasscodeActivity()); + passcodeActivityTestRule.launchActivity(i); + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); + + // We should still be locked + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + + // Entering 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertFalse("Application should be unlocked", passcodeManager.isLocked()); + } + + /** + * Test passcode verification flow when user enters wrong passcode once. + */ + @Test + public void testVerificationWithWrongPasscodeOnce() { + + // Store passcode and set mode to Check + passcodeManager.store(targetContext, "123456"); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + + // Get activity + final Intent i = new Intent(SalesforceSDKManager.getInstance().getAppContext(), + SalesforceSDKManager.getInstance().getPasscodeActivity()); + passcodeActivityTestRule.launchActivity(i); + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); + + // We should still be locked + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + + // Entering 654321 and submitting -> expect passcode incorrect error + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "654321"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in check mode still", PasscodeMode.Check, passcodeActivity.getMode()); + Assert.assertEquals("Error expected", "The passcode you entered is incorrect. Please try again. You have 9 attempts remaining.", + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); + Assert.assertEquals("Wrong failure count", 1, passcodeManager.getFailedPasscodeAttempts()); + + // Entering 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertFalse("Application should be unlocked", passcodeManager.isLocked()); + } + + /** + * Test passcode verification flow when user enters wrong passcode twice. + */ + @Test + public void testVerificationWithWrongPasscodeTwice() { + + // Store passcode and set mode to Check + passcodeManager.store(targetContext, "123456"); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + + // Get activity + final Intent intent = new Intent(SalesforceSDKManager.getInstance().getAppContext(), + SalesforceSDKManager.getInstance().getPasscodeActivity()); + passcodeActivityTestRule.launchActivity(intent); + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); + + // We should still be locked + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + for (int i = 1; i < 10; i++) { + enterWrongPasscode(i); + } + + // Entering 123456 and submitting + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertFalse("Application should be unlocked", passcodeManager.isLocked()); + } + + /** + * Test passcode verification flow when user enters a passcode too short. + */ + @Test + public void testVerificationWithPasscodeTooShort() { + + // Store passcode and set mode to Check + passcodeManager.store(targetContext, "123456"); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + + // Get activity + final Intent i = new Intent(SalesforceSDKManager.getInstance().getAppContext(), + SalesforceSDKManager.getInstance().getPasscodeActivity()); + passcodeActivityTestRule.launchActivity(i); + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); + + // We should still be locked + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + + // Entering 123 and submitting -> expect passcode too short error, not counted as attempt + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "654321"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in check mode still", PasscodeMode.Check, passcodeActivity.getMode()); + Assert.assertEquals("Error expected", "The passcode you entered is incorrect. Please try again. You have 9 attempts remaining.", + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); + Assert.assertEquals("Wrong failure count", 1, passcodeManager.getFailedPasscodeAttempts()); + } + + /** + * Test passcode verification flow when user enters wrong passcode too many times. + */ + @Test + public void testVerificationWithWrongPasscodeTooManyTimes() { + + // Store passcode and set mode to Check + passcodeManager.store(targetContext, "123456"); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + + // Get activity + final Intent intent = new Intent(SalesforceSDKManager.getInstance().getAppContext(), + SalesforceSDKManager.getInstance().getPasscodeActivity()); + passcodeActivityTestRule.launchActivity(intent); + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); + passcodeActivity.enableLogout(false); // logout is async, it creates havoc when running other tests + + // We should still be locked + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + for (int i = 1; i < 10; i++) { + enterWrongPasscode(i); + } + + // Entering 132645 and submitting -> expect passcode manager to be reset + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "132645"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertFalse("Application should not have a passcode", passcodeManager.hasStoredPasscode(targetContext)); + } + + /** + * Test when user clicks on the 'Forgot Passcode' link. + */ + @Test + public void testForgotPasscodeLink() throws Throwable { + + // Store passcode and set mode to Check. + passcodeManager.store(targetContext, "123456"); + Assert.assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); + + // Get activity + final Intent i = new Intent(SalesforceSDKManager.getInstance().getAppContext(), + SalesforceSDKManager.getInstance().getPasscodeActivity()); + passcodeActivityTestRule.launchActivity(i); + passcodeActivity = passcodeActivityTestRule.getActivity(); + Assert.assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); + passcodeActivity.enableLogout(false); // logout is async, it creates havoc when running other tests + + // We should still be locked. + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + + // Click on 'Forgot Passcode' link. + Assert.assertFalse("Logout dialog should not be showing", passcodeActivityTestRule.getActivity().getIsLogoutDialogShowing()); + clickView(com.salesforce.androidsdk.R.id.sf__passcode_forgot); + waitSome(); + Assert.assertTrue("Logout dialog should be showing", passcodeActivityTestRule.getActivity().getIsLogoutDialogShowing()); + + // Clicking on 'Cancel' should take us back to the passcode screen. + final AlertDialog logoutDialog = passcodeActivityTestRule.getActivity().getLogoutAlertDialog(); + logoutDialog.getButton(AlertDialog.BUTTON_NEGATIVE).performClick(); + waitSome(); + Assert.assertFalse("Logout dialog should not be showing", passcodeActivityTestRule.getActivity().getIsLogoutDialogShowing()); + + // Clicking on 'Ok' should log the user out. + clickView(com.salesforce.androidsdk.R.id.sf__passcode_forgot); + waitSome(); + logoutDialog.getButton(AlertDialog.BUTTON_POSITIVE).performClick(); + waitSome(); + Assert.assertFalse("Application should not have a passcode", passcodeManager.hasStoredPasscode(targetContext)); + } + + private void enterWrongPasscode(int count) { + + // Entering 321654 and submitting -> expect passcode incorrect error + setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "321654"); + doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text); + Assert.assertTrue("Application should still be locked", passcodeManager.isLocked()); + Assert.assertEquals("Activity expected in check mode still", PasscodeMode.Check, passcodeActivity.getMode()); + if (count == 9) { + Assert.assertEquals("Error expected", "Final passcode attempt", + ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); + } + Assert.assertEquals("Wrong failure count", count, passcodeManager.getFailedPasscodeAttempts()); + } + + private void clickView(final int resId) { + try { + onView(withId(resId)).perform(click()); + } catch (Throwable t) { + Assert.fail("Failed to click view " + resId); + } + } + + private void setText(final int textViewId, final String text) { + try { + onView(withId(textViewId)).perform(replaceText(text), closeSoftKeyboard()); + } catch (Throwable t) { + Assert.fail("Failed to set text " + text); + } + } + + private void doEditorAction(final int textViewId) { + try { + onView(withId(textViewId)).perform(pressImeActionButton()); + } catch (Throwable t) { + Assert.fail("Failed to perform editor action"); + } + } + + private void waitSome() { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + Assert.fail("Test interrupted"); + } + } +} diff --git a/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/ServerPickerActivityTest.java b/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/ServerPickerActivityTest.java new file mode 100644 index 0000000000..424d0ac16d --- /dev/null +++ b/native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/ServerPickerActivityTest.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2011-present, salesforce.com, inc. + * All rights reserved. + * Redistribution and use of this software in source and binary forms, with or + * without modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of salesforce.com, inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission of salesforce.com, inc. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package com.salesforce.samples.restexplorer; + +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.support.test.filters.SmallTest; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.view.View; +import android.widget.EditText; + +import com.salesforce.androidsdk.app.SalesforceSDKManager; +import com.salesforce.androidsdk.ui.CustomServerUrlEditor; +import com.salesforce.androidsdk.ui.ServerPickerActivity; +import com.salesforce.androidsdk.util.EventsObservable.EventType; +import com.salesforce.androidsdk.util.test.EventsListenerQueue; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; +import static android.support.test.espresso.action.ViewActions.replaceText; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +/** + * Tests for ServerPickerActivity. + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class ServerPickerActivityTest { + + private EventsListenerQueue eq; + private ServerPickerActivity activity; + + @Rule + public ActivityTestRule serverPickerActivityTestRule = new ActivityTestRule<>(ServerPickerActivity.class); + + @Before + public void setUp() throws Exception { + eq = new EventsListenerQueue(); + + // Waits for app initialization to complete. + if (!SalesforceSDKManager.hasInstance()) { + eq.waitForEvent(EventType.AppCreateComplete, 5000); + } + activity = serverPickerActivityTestRule.getActivity(); + removeFragmentIfRequired(); + Assert.assertNotNull("Activity should not be null", activity); + } + + @After + public void tearDown() throws Exception { + if (eq != null) { + eq.tearDown(); + eq = null; + } + activity.finish(); + activity = null; + } + + /** + * Test that the cancel button can be clicked and the URL not saved. + * + * @throws Throwable + */ + @Test + public void testCancelButton() throws Throwable { + openCustomEditDialog(); + clickView(com.salesforce.androidsdk.R.id.sf__cancel_button); + Assert.assertNull("Custom URL dialog should be closed", + activity.getCustomServerUrlEditor().getDialog()); + } + + /** + * Test a valid URL can be entered and saved. + * + * @throws Throwable + */ + @Test + public void testAddCustomInstance() throws Throwable { + String label = "My Custom URL"; + String url = "https://valid.url.com"; + addCustomUrl(label, url); + clickView(com.salesforce.androidsdk.R.id.sf__apply_button); + openCustomEditDialog(); + final CustomServerUrlEditor dialog = activity.getCustomServerUrlEditor(); + Thread.sleep(3000); + final View rootView = dialog.getRootView(); + final EditText txtLabel = rootView.findViewById(com.salesforce.androidsdk.R.id.sf__picker_custom_label); + final EditText txtUrl = rootView.findViewById(com.salesforce.androidsdk.R.id.sf__picker_custom_url); + Assert.assertTrue("Custom Label does not match Expected: " + label + + " Actual: " + txtLabel.getEditableText().toString(), label + .equalsIgnoreCase(txtLabel.getEditableText().toString())); + Assert.assertTrue("Custom URL does not match Expected: " + url + " Actual: " + + txtUrl.getEditableText().toString(), url + .equalsIgnoreCase(txtUrl.getEditableText().toString())); + } + + /** + * Test that "https" is required. + * + * @throws Throwable + */ + @Test + public void testAddInvalidUrl() throws Throwable { + String label = "My URL"; + String url = "http://invalid.url.com"; + addCustomUrl(label, url); + clickView(com.salesforce.androidsdk.R.id.sf__apply_button); + Assert.assertTrue("Custom URL dialog should still be open", + activity.getCustomServerUrlEditor().getDialog().isShowing()); + url = "https://valid.url.com"; + addCustomUrl(label, url); + clickView(com.salesforce.androidsdk.R.id.sf__apply_button); + Assert.assertNull("Custom URL dialog should be closed", + activity.getCustomServerUrlEditor().getDialog()); + } + + private void openCustomEditDialog() throws Throwable { + clickView(com.salesforce.androidsdk.R.id.sf__show_custom_url_edit); + final CustomServerUrlEditor dialog = activity.getCustomServerUrlEditor(); + Thread.sleep(3000); + final View rootView = dialog.getRootView(); + Assert.assertNotNull("Root view should not be null", rootView); + clickView(com.salesforce.androidsdk.R.id.sf__picker_custom_label); + } + + private void addCustomUrl(String label, String url) throws Throwable { + if (!activity.getCustomServerUrlEditor().isVisible()) { + openCustomEditDialog(); + } + setText(com.salesforce.androidsdk.R.id.sf__picker_custom_label, label); + clickView(com.salesforce.androidsdk.R.id.sf__picker_custom_url); + setText(com.salesforce.androidsdk.R.id.sf__picker_custom_url, url); + } + + private void removeFragmentIfRequired() { + final FragmentManager fm = activity.getFragmentManager(); + final Fragment dialog = activity.getFragmentManager().findFragmentByTag("custom_server_dialog"); + if (dialog != null && dialog.isAdded()) { + final FragmentTransaction ft = fm.beginTransaction(); + ft.remove(dialog); + ft.commit(); + } + } + + private void setText(final int viewId, final String text) { + try { + onView(withId(viewId)).perform(replaceText(text), closeSoftKeyboard()); + } catch (Throwable t) { + Assert.fail("Failed to set text " + text); + } + } + + private void clickView(final int resId) { + try { + onView(withId(resId)).perform(click()); + } catch (Throwable t) { + Assert.fail("Failed to click view " + resId); + } + } +} diff --git a/native/README.md b/native/README.md index db88f02ca8..3c2eb56643 100644 --- a/native/README.md +++ b/native/README.md @@ -17,13 +17,11 @@ For the rest of this document, we assume that you have setup three shell variabl Inside the $NATIVE_DIR, you will find several projects: -1. **TemplateApp**: Template used when creating new native application using SalesforceSDK -2. **test/TemplateAppTest**: Test project for the TemplateApp project -3. **SampleApps/RestExplorer**: An app using SalesforceSDK to explore the REST API calls -4. **SampleApps/test/RestExplorerTest**: Test project for the RestExplorer project -5. **SampleApps/SmartSyncExplorer**: An app using SmartSync to demonstrate synching a list of contacts from and to the server -6. **SampleApps/AppConfigurator**: An app to specify runtime configurations for ConfiguredApp (it allows configuration of login server and oauth consumer key and redirect uri) -7. **SampleApps/ConfiguredApp**: An app that consumes the runtime configurations specified with AppConfigurator +1. **NativeSampleApps/RestExplorer**: An app using SalesforceSDK to explore the REST API calls +2. **NativeSampleApps/test/RestExplorerTest**: Test project for the RestExplorer project +3. **NativeSampleApps/SmartSyncExplorer**: An app using SmartSync to demonstrate synching a list of contacts from and to the server +4. **NativeSampleApps/AppConfigurator**: An app to specify runtime configurations for ConfiguredApp (it allows configuration of login server and oauth consumer key and redirect uri) +5. **NativeSampleApps/ConfiguredApp**: An app that consumes the runtime configurations specified with AppConfigurator # Running sample apps from Android Studio diff --git a/native/test/TemplateAppTest/AndroidManifest.xml b/native/test/TemplateAppTest/AndroidManifest.xml deleted file mode 100644 index 401c4ff34d..0000000000 --- a/native/test/TemplateAppTest/AndroidManifest.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - diff --git a/native/test/TemplateAppTest/proguard.cfg b/native/test/TemplateAppTest/proguard.cfg deleted file mode 100644 index b1cdf17b5b..0000000000 --- a/native/test/TemplateAppTest/proguard.cfg +++ /dev/null @@ -1,40 +0,0 @@ --optimizationpasses 5 --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontpreverify --verbose --optimizations !code/simplification/arithmetic,!field/*,!class/merging/* - --keep public class * extends android.app.Activity --keep public class * extends android.app.Application --keep public class * extends android.app.Service --keep public class * extends android.content.BroadcastReceiver --keep public class * extends android.content.ContentProvider --keep public class * extends android.app.backup.BackupAgentHelper --keep public class * extends android.preference.Preference --keep public class com.android.vending.licensing.ILicensingService - --keepclasseswithmembernames class * { - native ; -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet); -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet, int); -} - --keepclassmembers class * extends android.app.Activity { - public void *(android.view.View); -} - --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} - --keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; -} diff --git a/native/test/TemplateAppTest/res/drawable-hdpi/icon.png b/native/test/TemplateAppTest/res/drawable-hdpi/icon.png deleted file mode 100644 index 8074c4c571..0000000000 Binary files a/native/test/TemplateAppTest/res/drawable-hdpi/icon.png and /dev/null differ diff --git a/native/test/TemplateAppTest/res/drawable-ldpi/icon.png b/native/test/TemplateAppTest/res/drawable-ldpi/icon.png deleted file mode 100644 index 1095584ec2..0000000000 Binary files a/native/test/TemplateAppTest/res/drawable-ldpi/icon.png and /dev/null differ diff --git a/native/test/TemplateAppTest/res/drawable-mdpi/icon.png b/native/test/TemplateAppTest/res/drawable-mdpi/icon.png deleted file mode 100644 index a07c69fa5a..0000000000 Binary files a/native/test/TemplateAppTest/res/drawable-mdpi/icon.png and /dev/null differ diff --git a/native/test/TemplateAppTest/res/layout/main.xml b/native/test/TemplateAppTest/res/layout/main.xml deleted file mode 100644 index c5deb6be39..0000000000 --- a/native/test/TemplateAppTest/res/layout/main.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/native/test/TemplateAppTest/res/values/strings.xml b/native/test/TemplateAppTest/res/values/strings.xml deleted file mode 100644 index 7195f715b9..0000000000 --- a/native/test/TemplateAppTest/res/values/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Hello World! - TemplateAppTest - com.salesforce.samples.templateapp.tests - diff --git a/native/test/TemplateAppTest/src/com/salesforce/samples/templateapp/PasscodeActivityTest.java b/native/test/TemplateAppTest/src/com/salesforce/samples/templateapp/PasscodeActivityTest.java deleted file mode 100644 index fcf3dd77c2..0000000000 --- a/native/test/TemplateAppTest/src/com/salesforce/samples/templateapp/PasscodeActivityTest.java +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright (c) 2011-present, salesforce.com, inc. - * All rights reserved. - * Redistribution and use of this software in source and binary forms, with or - * without modification, are permitted provided that the following conditions - * are met: - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of salesforce.com, inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission of salesforce.com, inc. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -package com.salesforce.samples.templateapp; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.test.ActivityInstrumentationTestCase2; -import android.text.TextUtils; -import android.view.KeyEvent; -import android.view.View; -import android.view.inputmethod.EditorInfo; -import android.widget.EditText; -import android.widget.TextView; - -import com.salesforce.androidsdk.app.SalesforceSDKManager; -import com.salesforce.androidsdk.security.PasscodeManager; -import com.salesforce.androidsdk.ui.PasscodeActivity; -import com.salesforce.androidsdk.ui.PasscodeActivity.PasscodeMode; -import com.salesforce.androidsdk.util.EventsObservable.EventType; -import com.salesforce.androidsdk.util.test.EventsListenerQueue; - -/** - * Tests for PasscodeActivity - */ -public class PasscodeActivityTest extends - ActivityInstrumentationTestCase2 { - - private EventsListenerQueue eq; - private Context targetContext; - private PasscodeActivity passcodeActivity; - private PasscodeManager passcodeManager; - - public PasscodeActivityTest() { - super(PasscodeActivity.class); - } - - @Override - public void setUp() throws Exception { - super.setUp(); - setActivityInitialTouchMode(false); - eq = new EventsListenerQueue(); - - // Waits for app initialization to complete. - if (!SalesforceSDKManager.hasInstance()) { - eq.waitForEvent(EventType.AppCreateComplete, 5000); - } - targetContext = getInstrumentation().getTargetContext(); - passcodeManager = SalesforceSDKManager.getInstance().getPasscodeManager(); - passcodeManager.reset(targetContext); - passcodeManager.setTimeoutMs(600000); - assertTrue("Application should be locked", passcodeManager.isLocked()); - assertFalse("Application should not have a passcode", passcodeManager.hasStoredPasscode(targetContext)); - } - - @Override - public void tearDown() throws Exception { - if (passcodeActivity != null) { - passcodeActivity.finish(); - passcodeActivity = null; - } - if (eq != null) { - eq.tearDown(); - eq = null; - } - super.tearDown(); - } - - /** - * Test passcode creation flow when no mistakes are made by user - */ - public void testCreateWithNoMistakes() { - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); - - // Entering in 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in check mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); - assertTrue("Error message should be empty", TextUtils.isEmpty( - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText())); - - // Re-entering 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertFalse("Application should be unlocked", passcodeManager.isLocked()); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - } - - /** - * Test passcode change flow when no mistakes are made by user - */ - public void testChangeWithNoMistakes() { - // Get activity - final Intent i = new Intent(SalesforceSDKManager.getInstance().getAppContext(), - SalesforceSDKManager.getInstance().getPasscodeActivity()); - i.putExtra(PasscodeManager.CHANGE_PASSCODE_KEY, true); - setActivityIntent(i); - passcodeActivity = getActivity(); - assertEquals("Activity expected in change mode", PasscodeMode.Change, passcodeActivity.getMode()); - - // Entering in 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in check mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); - assertTrue("Error message should be empty", TextUtils.isEmpty( - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText())); - - // Re-entering 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertFalse("Application should be unlocked", passcodeManager.isLocked()); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - } - - /** - * Test passcode creation flow when user try to enter a passcode too short - */ - public void testCreateWithPasscodeTooShort() { - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); - - // Entering nothing and submitting -> expect passcode too short error - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, ""); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in create mode still", PasscodeMode.Create, passcodeActivity.getMode()); - assertEquals("Error expected", "The passcode must be at least 4 characters long", - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); - - // Entering in 123 and submitting -> expect passcode too short error - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in create mode still", PasscodeMode.Create, passcodeActivity.getMode()); - assertEquals("Error expected", "The passcode must be at least 4 characters long", - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); - - // Entering in 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in create confirm mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); - - // Re-entering 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertFalse("Application should be unlocked", passcodeManager.isLocked()); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - } - - /** - * Test passcode creation flow when user try to enter a passcode matching the minimum value - */ - public void testCreatewithPasscodeMinimumLength() { - - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); - - // Entering nothing and submitting -> expect passcode too short error - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "1234"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in create mode still", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); - assertTrue("Error Message should be empty", TextUtils.isEmpty( - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText())); - } - - /** - * Test passcode creation flow when user enter a passcode too short during confirmation - */ - public void testCreateWithConfirmPasscodeTooShort() { - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); - - // Entering in 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in check mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); - - // Entering in 123 and submitting -> expect passcode too short error - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in create confirm mode still", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); - assertEquals("Error expected", "The passcode must be at least 4 characters long", - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); - - // Entering 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertFalse("Application should be unlocked", passcodeManager.isLocked()); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - } - - /** - * Test passcode creation flow when user enter a different passcode during confirmation - */ - public void testCreateWithWrongConfirmPasscode() { - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in create mode", PasscodeMode.Create, passcodeActivity.getMode()); - - // Entering in 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should be still locked", passcodeManager.isLocked()); - assertEquals("Activity expected in check mode", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); - - // Entering in 654321 and submitting -> expect passcodes don't match error - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "654321"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should be still locked", passcodeManager.isLocked()); - assertEquals("Activity expected in create confirm mode still", PasscodeMode.CreateConfirm, passcodeActivity.getMode()); - assertEquals("Error expected", "Passcodes don't match!", - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); - - // Entering 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertFalse("Application should be unlocked", passcodeManager.isLocked()); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - } - - /** - * Test passcode verification flow when no mistakes are made by user - */ - public void testVerificationWithNoMistakes() { - // Store passcode and set mode to Check - passcodeManager.store(targetContext, "123456"); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); - - // We should still be locked - assertTrue("Application should still be locked", passcodeManager.isLocked()); - - // Entering 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertFalse("Application should be unlocked", passcodeManager.isLocked()); - } - - /** - * Test passcode verification flow when user enters wrong passcode once - */ - public void testVerificationWithWrongPasscodeOnce() { - // Store passcode and set mode to Check - passcodeManager.store(targetContext, "123456"); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); - - // We should still be locked - assertTrue("Application should still be locked", passcodeManager.isLocked()); - - // Entering 654321 and submitting -> expect passcode incorrect error - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "654321"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in check mode still", PasscodeMode.Check, passcodeActivity.getMode()); - assertEquals("Error expected", "The passcode you entered is incorrect. Please try again. You have 9 attempts remaining.", - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); - assertEquals("Wrong failure count", 1, passcodeManager.getFailedPasscodeAttempts()); - - // Entering 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertFalse("Application should be unlocked", passcodeManager.isLocked()); - } - - /** - * Test passcode verification flow when user enters wrong passcode twice - */ - public void testVerificationWithWrongPasscodeTwice() { - // Store passcode and set mode to Check - passcodeManager.store(targetContext, "123456"); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); - - // We should still be locked - assertTrue("Application should still be locked", passcodeManager.isLocked()); - - for (int i = 1; i < 10; i++) { - enterWrongPasscode(i); - } - - // Entering 123456 and submitting - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "123456"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertFalse("Application should be unlocked", passcodeManager.isLocked()); - } - - /** - * Test passcode verification flow when user enters a passcode too short - */ - public void testVerificationWithPasscodeTooShort() { - // Store passcode and set mode to Check - passcodeManager.store(targetContext, "123456"); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); - - // We should still be locked - assertTrue("Application should still be locked", passcodeManager.isLocked()); - - // Entering 123 and submitting -> expect passcode too short error, not counted as attempt - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "654321"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in check mode still", PasscodeMode.Check, passcodeActivity.getMode()); - assertEquals("Error expected", "The passcode you entered is incorrect. Please try again. You have 9 attempts remaining.", - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); - assertEquals("Wrong failure count", 1, passcodeManager.getFailedPasscodeAttempts()); - } - - /** - * Test passcode verification flow when user enters wrong passcode too many times - */ - public void testVerificationWithWrongPasscodeTooManyTimes() { - // Store passcode and set mode to Check - passcodeManager.store(targetContext, "123456"); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); - passcodeActivity.enableLogout(false); // logout is async, it creates havoc when running other tests - - // We should still be locked - assertTrue("Application should still be locked", passcodeManager.isLocked()); - - for (int i = 1; i < 10; i++) { - enterWrongPasscode(i); - } - - // Entering 132645 and submitting -> expect passcode manager to be reset - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "132645"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertFalse("Application should not have a passcode", passcodeManager.hasStoredPasscode(targetContext)); - } - - /** - * Test when user clicks on the 'Forgot Passcode' link. - */ - public void testForgotPasscodeLink() throws Throwable { - // Store passcode and set mode to Check. - passcodeManager.store(targetContext, "123456"); - assertTrue("Stored passcode should match entered passcode", passcodeManager.check(targetContext, "123456")); - - // Get activity - passcodeActivity = getActivity(); - assertEquals("Activity expected in check mode", PasscodeMode.Check, passcodeActivity.getMode()); - passcodeActivity.enableLogout(false); // logout is async, it creates havoc when running other tests - - // We should still be locked. - assertTrue("Application should still be locked", passcodeManager.isLocked()); - - // Click on 'Forgot Passcode' link. - assertFalse("Logout dialog should not be showing", getActivity().getIsLogoutDialogShowing()); - clickView(getActivity().findViewById(com.salesforce.androidsdk.R.id.sf__passcode_forgot)); - waitSome(); - assertTrue("Logout dialog should be showing", getActivity().getIsLogoutDialogShowing()); - - // Clicking on 'Cancel' should take us back to the passcode screen. - final AlertDialog logoutDialog = getActivity().getLogoutAlertDialog(); - clickView(logoutDialog.getButton(AlertDialog.BUTTON_NEGATIVE)); - waitSome(); - assertFalse("Logout dialog should not be showing", getActivity().getIsLogoutDialogShowing()); - - // Clicking on 'Ok' should log the user out. - clickView(getActivity().findViewById(com.salesforce.androidsdk.R.id.sf__passcode_forgot)); - waitSome(); - clickView(logoutDialog.getButton(AlertDialog.BUTTON_POSITIVE)); - waitSome(); - assertFalse("Application should not have a passcode", passcodeManager.hasStoredPasscode(targetContext)); - } - - private void enterWrongPasscode(int count) { - - // Entering 321654 and submitting -> expect passcode incorrect error - setText(com.salesforce.androidsdk.R.id.sf__passcode_text, "321654"); - doEditorAction(com.salesforce.androidsdk.R.id.sf__passcode_text, EditorInfo.IME_ACTION_GO); - assertTrue("Application should still be locked", passcodeManager.isLocked()); - assertEquals("Activity expected in check mode still", PasscodeMode.Check, passcodeActivity.getMode()); - if (count == 9) { - assertEquals("Error expected", "Final passcode attempt", - ((TextView) passcodeActivity.findViewById(com.salesforce.androidsdk.R.id.sf__passcode_error)).getText()); - } - assertEquals("Wrong failure count", count, passcodeManager.getFailedPasscodeAttempts()); - } - - private void clickView(final View v) { - try { - runTestOnUiThread(new Runnable() { - @Override - public void run() { - v.performClick(); - } - }); - } catch (Throwable t) { - fail("Failed to click view " + v); - } - } - - private void setText(final int textViewId, final String text) { - try { - runTestOnUiThread(new Runnable() { - @Override public void run() { - TextView v = (TextView) getActivity().findViewById(textViewId); - v.setText(text); - if (v instanceof EditText) - ((EditText) v).setSelection(v.getText().length()); - } - }); - } catch (Throwable t) { - fail("Failed to set text " + text); - } - } - - private void doEditorAction(final int textViewId, final int actionCode) { - try { - runTestOnUiThread(new Runnable() { - @Override public void run() { - TextView v = (TextView) getActivity().findViewById(textViewId); - v.onEditorAction(actionCode); - } - }); - } catch (Throwable t) { - fail("Failed do editor action " + actionCode); - } - } - - private void waitSome() { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - fail("Test interrupted"); - } - } -} diff --git a/native/test/TemplateAppTest/src/com/salesforce/samples/templateapp/ServerPickerActivityTest.java b/native/test/TemplateAppTest/src/com/salesforce/samples/templateapp/ServerPickerActivityTest.java deleted file mode 100644 index df4570899d..0000000000 --- a/native/test/TemplateAppTest/src/com/salesforce/samples/templateapp/ServerPickerActivityTest.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2011-present, salesforce.com, inc. - * All rights reserved. - * Redistribution and use of this software in source and binary forms, with or - * without modification, are permitted provided that the following conditions - * are met: - * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - Neither the name of salesforce.com, inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission of salesforce.com, inc. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -package com.salesforce.samples.templateapp; - -import android.app.Fragment; -import android.app.FragmentManager; -import android.app.FragmentTransaction; -import android.test.ActivityInstrumentationTestCase2; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.TextView; - -import com.salesforce.androidsdk.app.SalesforceSDKManager; -import com.salesforce.androidsdk.ui.CustomServerUrlEditor; -import com.salesforce.androidsdk.ui.ServerPickerActivity; -import com.salesforce.androidsdk.util.EventsObservable.EventType; -import com.salesforce.androidsdk.util.test.EventsListenerQueue; - -/** - * Tests for ServerPickerActivity - */ -public class ServerPickerActivityTest extends - ActivityInstrumentationTestCase2 { - - private EventsListenerQueue eq; - private Button btnCustomEdit; - private Button btnCancel; - private Button btnApply; - private EditText txtLabel; - private EditText txtUrl; - private ServerPickerActivity activity; - - public ServerPickerActivityTest() { - super(ServerPickerActivity.class); - } - - @Override - public void setUp() throws Exception { - super.setUp(); - setActivityInitialTouchMode(false); - eq = new EventsListenerQueue(); - - // Waits for app initialization to complete. - if (!SalesforceSDKManager.hasInstance()) { - eq.waitForEvent(EventType.AppCreateComplete, 5000); - } - activity = getActivity(); - removeFragmentIfRequired(); - assertNotNull("Activity should not be null", activity); - } - - @Override - public void tearDown() throws Exception { - if (eq != null) { - eq.tearDown(); - eq = null; - } - activity.finish(); - activity = null; - super.tearDown(); - } - - /** - * Test that the cancel button can be clicked and the URL not saved - * - * @throws Throwable - */ - public void testCancelButton() throws Throwable { - openCustomEditDialog(); - clickView(btnCancel); - assertNull("Custom URL dialog should be closed", - activity.getCustomServerUrlEditor().getDialog()); - } - - /** - * Test a valid URL can be entered and saved - * - * @throws Throwable - */ - public void testAddCustomInstance() throws Throwable { - String label = "My Custom URL"; - String url = "https://valid.url.com"; - addCustomUrl(label, url); - clickView(btnApply); - openCustomEditDialog(); - assertTrue("Custom Label does not match Expected: " + label - + " Actual: " + txtLabel.getEditableText().toString(), label - .equalsIgnoreCase(txtLabel.getEditableText().toString())); - assertTrue("Custom URL does not match Expected: " + url + " Actual: " - + txtUrl.getEditableText().toString(), url - .equalsIgnoreCase(txtUrl.getEditableText().toString())); - } - - /** - * Test that "https" is required - * - * @throws Throwable - */ - public void testAddInvalidUrl() throws Throwable { - String label = "My URL"; - String url = "http://invalid.url.com"; - addCustomUrl(label, url); - clickView(btnApply); - assertTrue("Custom URL dialog should still be open", - activity.getCustomServerUrlEditor().getDialog().isShowing()); - assertTrue("URL field should still have focus", txtUrl.hasFocus()); - url = "https://valid.url.com"; - addCustomUrl(label, url); - clickView(btnApply); - assertNull("Custom URL dialog should be closed", - activity.getCustomServerUrlEditor().getDialog()); - } - - private void openCustomEditDialog() throws Throwable { - btnCustomEdit = (Button) activity.findViewById( - com.salesforce.androidsdk.R.id.sf__show_custom_url_edit); - assertNotNull("Custom URL Edit dialog does not exist", btnCustomEdit); - clickView(btnCustomEdit); - final CustomServerUrlEditor dialog = activity.getCustomServerUrlEditor(); - Thread.sleep(3000); - final View rootView = dialog.getRootView(); - assertNotNull("Root view should not be null", rootView); - if (btnApply == null || btnCancel == null || txtLabel == null - || txtUrl == null) { - btnApply = (Button) rootView.findViewById(com.salesforce.androidsdk.R.id.sf__apply_button); - btnCancel = (Button) rootView.findViewById(com.salesforce.androidsdk.R.id.sf__cancel_button); - txtLabel = (EditText) rootView.findViewById(com.salesforce.androidsdk.R.id.sf__picker_custom_label); - txtUrl = (EditText) rootView.findViewById(com.salesforce.androidsdk.R.id.sf__picker_custom_url); - } - setFocus(txtLabel); - } - - private void addCustomUrl(String label, String url) throws Throwable { - if (!activity.getCustomServerUrlEditor().isVisible()) { - openCustomEditDialog(); - } - setText(txtLabel, label); - setFocus(txtUrl); - setText(txtUrl, url); - } - - private void removeFragmentIfRequired() { - final FragmentManager fm = activity.getFragmentManager(); - final Fragment dialog = activity.getFragmentManager().findFragmentByTag("custom_server_dialog"); - if (dialog != null && dialog.isAdded()) { - final FragmentTransaction ft = fm.beginTransaction(); - ft.remove(dialog); - ft.commit(); - } - } - - private void setText(final TextView v, final String text) { - try { - runTestOnUiThread(new Runnable() { - - @Override - public void run() { - v.setText(text); - if (v instanceof EditText) - ((EditText) v).setSelection(v.getText().length()); - } - }); - } catch (Throwable t) { - fail("Failed to set text " + text); - } - } - - private void setFocus(View v) throws Throwable { - runTestOnUiThread(new Focuser(v)); - } - - /** - * A runnable that requests focus for the specified view. - */ - private static class Focuser implements Runnable { - - Focuser(View v) { - this.view = v; - } - - private final View view; - - @Override - public void run() { - view.requestFocus(); - } - } - - private void clickView(final View v) { - try { - runTestOnUiThread(new Runnable() { - - @Override - public void run() { - v.performClick(); - } - }); - } catch (Throwable t) { - fail("Failed to click view " + v); - } - } -} diff --git a/tools/sdk.sh b/tools/sdk.sh index 40bcc49031..8742da11ef 100755 --- a/tools/sdk.sh +++ b/tools/sdk.sh @@ -58,8 +58,6 @@ usage () echo " NoteSync" echo " SmartSyncExplorerHybrid" echo " SmartSyncExplorer" - echo " TemplateApp" - echo " ReactNativeTemplateApp" echo " SalesforceHybridTest" echo " can be " echo " all" @@ -68,7 +66,6 @@ usage () echo " SalesforceSDKTest" echo " SmartStoreTest" echo " SmartSyncTest" - echo " TemplateAppTest" echo " SalesforceHybridTest" } @@ -171,7 +168,6 @@ else build_project_if_requested "SmartSync" :libs:SmartSync build_project_if_requested "SalesforceHybrid" :libs:SalesforceHybrid build_project_if_requested "SalesforceReact" :libs:SalesforceReact - build_project_if_requested "TemplateApp" :native:TemplateApp build_project_if_requested "RestExplorer" :native:NativeSampleApps:RestExplorer build_project_if_requested "AppConfigurator" :native:NativeSampleApps:AppConfigurator build_project_if_requested "ConfiguredApp" :native:NativeSampleApps:ConfiguredApp @@ -179,7 +175,6 @@ else build_project_if_requested "AccountEditor" :hybrid:HybridSampleApps:AccountEditor build_project_if_requested "NoteSync" :hybrid:HybridSampleApps:NoteSync build_project_if_requested "SmartSyncExplorerHybrid" :hybrid:HybridSampleApps:SmartSyncExplorerHybrid - build_project_if_requested "ReactNativeTemplateApp" :reactnative:ReactNativeTemplateApp fi if ( should_do "test{all}" ) @@ -192,7 +187,6 @@ else run_test_project_if_requested "SmartStoreTest" :libs:SmartStore run_test_project_if_requested "SmartSyncTest" :libs:SmartSync run_test_project_if_requested "SalesforceHybridTest" :libs:SalesforceHybrid - run_test_project_if_requested "TemplateAppTest" :native:TemplateApp run_test_project_if_requested "RestExplorerTest" :native:NativeSampleApps:RestExplorer fi fi