diff --git a/.travis.yml b/.travis.yml index 80ae7d4..d1b789a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,12 +6,6 @@ env: matrix: - ANDROID_TARGET=android-22 -sudo: false -addons: - apt: - packages: - - oracle-java8-installer - android: components: # following added as quick fix to get support for 23.0.3 build tools @@ -31,4 +25,4 @@ android: before_script: script: - - ./gradlew assembleFullRelease + - ./gradlew testFullDebugUnitTest assembleFullRelease diff --git a/app/build.gradle b/app/build.gradle index 3553c33..eb5168a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,6 +38,19 @@ android { } } + sourceSets { + fullDebug { + assets.srcDirs = ['src/testUtils/assets'] + } + test { + java.srcDirs = ['src/test/java', 'src/testUtils/java'] + } + instrumentationTest { + java.srcDirs = ['src/testUtils/java'] + assets.srcDirs = ['src/testUtils/assets'] + } + } + productFlavors { full { } @@ -45,6 +58,7 @@ android { instrumentationTest { applicationId "org.xbmc.kore.instrumentationtest" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + proguardFiles 'proguardTest-rules.pro' } } @@ -110,6 +124,10 @@ dependencies { androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' androidTestCompile 'com.android.support.test.espresso:espresso-idling-resource:2.2.2' androidTestCompile 'com.android.support:support-v13:23.4.0' + instrumentationTestCompile 'junit:junit:4.12' + + testCompile 'org.robolectric:robolectric:3.1.1' + testCompile 'junit:junit:4.12' compile fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/app/proguardTest-rules.pro b/app/proguardTest-rules.pro new file mode 100644 index 0000000..2d97617 --- /dev/null +++ b/app/proguardTest-rules.pro @@ -0,0 +1,8 @@ +-keep class org.junit.** { *; } +-dontwarn org.junit.** + +-keep class junit.** { *; } +-dontwarn junit.** + +-keep class sun.misc.** { *; } +-dontwarn sun.misc.** \ No newline at end of file diff --git a/app/src/androidTest/README.md b/app/src/androidTest/README.md new file mode 100644 index 0000000..9382fdf --- /dev/null +++ b/app/src/androidTest/README.md @@ -0,0 +1,19 @@ +Integration tests that need to be executed on an Android device. + +## Run tests + +You can run the tests as follows: + +### Android Studio + +1. Select build variant "instrumentationTestDebug" +2. Set the (Project view)[https://developer.android.com/studio/projects/index.html] to Android +3. Right-click on the directory "androidTest" and select "Run tests" + +### Commandline + +Run the following command from the top of the project: + + ./gradlew connectedInstrumentationTestDebugAndroidTest + +This will run the tests on all connected devices in parallel \ No newline at end of file diff --git a/app/src/androidTest/java/org/xbmc/kore/testhelpers/Utils.java b/app/src/androidTest/java/org/xbmc/kore/testhelpers/Utils.java index aa8b259..ad52edc 100644 --- a/app/src/androidTest/java/org/xbmc/kore/testhelpers/Utils.java +++ b/app/src/androidTest/java/org/xbmc/kore/testhelpers/Utils.java @@ -18,7 +18,6 @@ package org.xbmc.kore.testhelpers; import android.content.Context; import android.content.pm.PackageManager; -import android.database.Cursor; import android.os.IBinder; import android.support.test.rule.ActivityTestRule; import android.support.v4.widget.DrawerLayout; @@ -27,10 +26,10 @@ import android.util.Log; import org.xbmc.kore.R; import org.xbmc.kore.host.HostInfo; import org.xbmc.kore.host.HostManager; +import org.xbmc.kore.provider.MediaProvider; +import org.xbmc.kore.testutils.Database; import org.xbmc.kore.utils.LogUtils; -import java.io.IOException; -import java.io.InputStream; import java.lang.reflect.Method; public class Utils { @@ -45,20 +44,6 @@ public class Utils { private static HostInfo hostInfo; private static Context context; - public static String readFile(Context context, String filename) throws IOException { - InputStream is = context.getAssets().open(filename); - - int size = is.available(); - - byte[] buffer = new byte[size]; - - is.read(buffer); - - is.close(); - - return new String(buffer, "UTF-8"); - } - public static void closeDrawer(final ActivityTestRule activityTestRule) throws Throwable { activityTestRule.runOnUiThread(new Runnable() { @Override @@ -77,7 +62,11 @@ public class Utils { disableAnimations(); - hostInfo = Database.fill(context); + MediaProvider mediaProvider = new MediaProvider(); + mediaProvider.setContext(context); + mediaProvider.onCreate(); + + hostInfo = Database.fill(context, context.getContentResolver()); HostManager.getInstance(context).switchHost(hostInfo); Utils.closeDrawer(activityTestRule); @@ -86,22 +75,13 @@ public class Utils { } public static void cleanup() { - Database.flush(context, hostInfo); + Database.flush(context.getContentResolver(), hostInfo); enableAnimations(); isInitialized = false; } - public static String cursorToString(Cursor cursor) { - StringBuffer stringBuffer = new StringBuffer(); - for (String name : cursor.getColumnNames()) { - int index = cursor.getColumnIndex(name); - stringBuffer.append(name + "=" + cursor.getString(index) + "\n"); - } - return stringBuffer.toString(); - } - private static void disableAnimations() { int permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION); if (permStatus == PackageManager.PERMISSION_GRANTED) { @@ -137,16 +117,4 @@ public class Utils { Log.e("SystemAnimations", "Could not change animation scale to " + animationScale + " :'("); } } - - public static boolean moveCursorTo(Cursor cursor, int index, int item) { - if (( cursor == null ) || ( ! cursor.moveToFirst() )) - return false; - - do { - if ( cursor.getInt(index) == item ) - return true; - } while (cursor.moveToNext()); - - return false; - } } diff --git a/app/src/instrumentationTest/README.md b/app/src/instrumentationTest/README.md new file mode 100644 index 0000000..e98b7f8 --- /dev/null +++ b/app/src/instrumentationTest/README.md @@ -0,0 +1,5 @@ +Resources required for the instrumentation tests in [androidTest](../androidTest) + +**Note**: do not put any tests here! Put local tests +that DO NOT need to be executed on an android device in [test](../test). +Put tests that DO need to run on an android device in [androidTest](../androidTest). diff --git a/app/src/test/README.md b/app/src/test/README.md new file mode 100644 index 0000000..6900238 --- /dev/null +++ b/app/src/test/README.md @@ -0,0 +1,17 @@ +Local tests that do NOT need to be executed on an Android device + +## Run tests + +You can run the tests as follows: + +### Android Studio + +1. Select build variant "instrumentationTestDebug" +2. Set the (Project view)[https://developer.android.com/studio/projects/index.html] to Android +3. Right-click on the directory "test" and select "Run tests" + +### Commandline + +Run the following command from the top of the project: + + ./gradlew testInstrumentationTestDebugUnitTest \ No newline at end of file diff --git a/app/src/test/java/org/xbmc/kore/provider/mediaprovider/AbstractTestClass.java b/app/src/test/java/org/xbmc/kore/provider/mediaprovider/AbstractTestClass.java new file mode 100644 index 0000000..ad22058 --- /dev/null +++ b/app/src/test/java/org/xbmc/kore/provider/mediaprovider/AbstractTestClass.java @@ -0,0 +1,53 @@ +/* + * Copyright 2016 Martijn Brekhof. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.xbmc.kore.provider.mediaprovider; + + +import android.content.ContentResolver; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.Shadows; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowContentResolver; +import org.xbmc.kore.BuildConfig; +import org.xbmc.kore.host.HostInfo; +import org.xbmc.kore.provider.MediaProvider; +import org.xbmc.kore.testutils.Database; + +@RunWith(RobolectricTestRunner.class) +@Config(constants = BuildConfig.class) +@Ignore +public class AbstractTestClass { + protected static HostInfo hostInfo; + protected static ShadowContentResolver shadowContentResolver; + + @Before + public void setUp() throws Exception { + MediaProvider provider = new MediaProvider(); + ContentResolver contentResolver = RuntimeEnvironment.application.getContentResolver(); + provider.onCreate(); + shadowContentResolver = Shadows.shadowOf(contentResolver); + ShadowContentResolver.registerProvider("org.xbmc.kore.provider", provider); + provider.onCreate(); + + hostInfo = Database.fill(RuntimeEnvironment.application, contentResolver); + } +} diff --git a/app/src/androidTest/java/org/xbmc/kore/tests/mediaprovider/MediaProviderMusicTest.java b/app/src/test/java/org/xbmc/kore/provider/mediaprovider/MediaProviderMusicTest.java similarity index 72% rename from app/src/androidTest/java/org/xbmc/kore/tests/mediaprovider/MediaProviderMusicTest.java rename to app/src/test/java/org/xbmc/kore/provider/mediaprovider/MediaProviderMusicTest.java index d5d20ce..838f151 100644 --- a/app/src/androidTest/java/org/xbmc/kore/tests/mediaprovider/MediaProviderMusicTest.java +++ b/app/src/test/java/org/xbmc/kore/provider/mediaprovider/MediaProviderMusicTest.java @@ -14,72 +14,27 @@ * limitations under the License. */ -package org.xbmc.kore.tests.mediaprovider; +package org.xbmc.kore.provider.mediaprovider; -import android.content.ContentResolver; -import android.content.Context; import android.database.Cursor; import android.net.Uri; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.runner.RunWith; -import org.xbmc.kore.host.HostInfo; import org.xbmc.kore.provider.MediaContract; -import org.xbmc.kore.provider.MediaProvider; -import org.xbmc.kore.testhelpers.Database; -import org.xbmc.kore.testhelpers.TestUtils; -import org.xbmc.kore.testhelpers.Utils; -import org.xbmc.kore.ui.MoviesActivity; -import org.xbmc.kore.utils.LogUtils; +import org.xbmc.kore.testutils.CursorUtils; +import org.xbmc.kore.testutils.TestUtils; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; -@RunWith(AndroidJUnit4.class) -public class MediaProviderMusicTest { - private static HostInfo hostInfo; - private static Context context; - private ContentResolver contentResolver; - - /** - * Note that the activity MoviesActivity is only needed for context and is not tested - */ - @Rule - public ActivityTestRule mActivityRule = new ActivityTestRule<>( - MoviesActivity.class); - - @Before - public void setUp() throws Exception { - context = mActivityRule.getActivity(); - - if (hostInfo == null) // We only need to fill the database the first time - hostInfo = Database.fill(context); - - contentResolver = mActivityRule.getActivity().getContentResolver(); - } - - @After - public void tearDown() throws Exception { - - } - - @AfterClass - public static void cleanup() { - Database.flush(context, hostInfo); - } +public class MediaProviderMusicTest extends AbstractTestClass { @Test public void queryAllArtistsTest() { Uri uri = MediaContract.Artists.buildArtistsListUri(hostInfo.getId()); - Cursor cursor = contentResolver.query(uri, TestValues.Artist.PROJECTION, null, null, null); + Cursor cursor = shadowContentResolver.query(uri, TestValues.Artist.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 227, cursor.getCount()); @@ -94,7 +49,7 @@ public class MediaProviderMusicTest { public void queryArtistTest() { Uri uri = MediaContract.Artists.buildArtistUri(hostInfo.getId(), TestValues.Artist.artistId); - Cursor cursor = contentResolver.query(uri, TestValues.Artist.PROJECTION, null, null, null); + Cursor cursor = shadowContentResolver.query(uri, TestValues.Artist.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 1, cursor.getCount()); @@ -106,7 +61,7 @@ public class MediaProviderMusicTest { public void queryAllAlbumsTest() { Uri uri = MediaContract.Albums.buildAlbumsListUri(hostInfo.getId()); - Cursor cursor = contentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null); + Cursor cursor = shadowContentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 232, cursor.getCount()); @@ -120,7 +75,7 @@ public class MediaProviderMusicTest { public void queryAlbumTest() { Uri uri = MediaContract.Albums.buildAlbumUri(hostInfo.getId(), TestValues.Album.albumId); - Cursor cursor = contentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null); + Cursor cursor = shadowContentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 1, cursor.getCount()); @@ -133,7 +88,7 @@ public class MediaProviderMusicTest { Uri uri = MediaContract.AlbumArtists.buildAlbumsForArtistListUri(hostInfo.getId(), TestValues.Artist.artistId); - Cursor cursor = contentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null); + Cursor cursor = shadowContentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 1, cursor.getCount()); @@ -146,7 +101,7 @@ public class MediaProviderMusicTest { int genreId = 13; Uri uri = MediaContract.AlbumGenres.buildAlbumsForGenreListUri(hostInfo.getId(), genreId); - Cursor cursor = contentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null); + Cursor cursor = shadowContentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 31, cursor.getCount()); @@ -162,7 +117,7 @@ public class MediaProviderMusicTest { public void queryAlbumSongsTest() { Uri uri = MediaContract.Songs.buildAlbumSongsListUri(hostInfo.getId(), TestValues.Album.albumId); - Cursor cursor = contentResolver.query(uri, new String[] {MediaProvider.Qualified.SONGS_SONGID}, null, null, null); + Cursor cursor = shadowContentResolver.query(uri, new String[] {MediaContract.Songs.SONGID}, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 17, cursor.getCount()); @@ -175,7 +130,7 @@ public class MediaProviderMusicTest { Uri uri = MediaContract.Albums.buildAlbumUri(hostInfo.getId(), TestValues.AlbumWithoutArtist.albumId); - Cursor cursor = contentResolver.query(uri, TestValues.AlbumWithoutArtist.PROJECTION, null, null, null); + Cursor cursor = shadowContentResolver.query(uri, TestValues.AlbumWithoutArtist.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 1, cursor.getCount()); @@ -188,7 +143,7 @@ public class MediaProviderMusicTest { Uri uri = MediaContract.Albums.buildAlbumUri(hostInfo.getId(), TestValues.AlbumWithMultipleArtists.albumId); - Cursor cursor = contentResolver.query(uri, TestValues.AlbumWithMultipleArtists.PROJECTION, + Cursor cursor = shadowContentResolver.query(uri, TestValues.AlbumWithMultipleArtists.PROJECTION, null, null, null); assertNotNull(cursor); @@ -201,13 +156,13 @@ public class MediaProviderMusicTest { public void queryArtistSongsTest() { Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(), TestValues.ArtistSong.artistId); - Cursor cursor = contentResolver.query(uri, TestValues.ArtistSong.PROJECTION, null, null, null); + Cursor cursor = shadowContentResolver.query(uri, TestValues.ArtistSong.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 17, cursor.getCount()); TestUtils.testCursorContainsRange(cursor, cursor.getColumnIndex(MediaContract.SongsColumns.SONGID), 96, 112); - assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), + assertTrue(CursorUtils.moveCursorToFirstOccurrence(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), TestValues.ArtistSong.songId)); } @@ -216,13 +171,12 @@ public class MediaProviderMusicTest { Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(), TestValues.SongWithArtistWithoutAlbum.artistId); - Cursor cursor = contentResolver.query(uri, TestValues.SongWithArtistWithoutAlbum.PROJECTION, + Cursor cursor = shadowContentResolver.query(uri, TestValues.SongWithArtistWithoutAlbum.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 1, cursor.getCount()); assertTrue(cursor.moveToFirst()); - Utils.cursorToString(cursor); TestValues.SongWithArtistWithoutAlbum.test(cursor); } @@ -231,7 +185,7 @@ public class MediaProviderMusicTest { Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(), TestValues.SongWithMultipleArtists.firstArtistId); - Cursor cursor = contentResolver.query(uri, TestValues.SongWithMultipleArtists.PROJECTION, + Cursor cursor = shadowContentResolver.query(uri, TestValues.SongWithMultipleArtists.PROJECTION, null, null, null); assertNotNull(cursor); @@ -245,7 +199,7 @@ public class MediaProviderMusicTest { Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(), TestValues.SongWithMultipleArtists.secondArtistId); - Cursor cursor = contentResolver.query(uri, TestValues.SongWithMultipleArtists.PROJECTION, + Cursor cursor = shadowContentResolver.query(uri, TestValues.SongWithMultipleArtists.PROJECTION, null, null, null); assertNotNull(cursor); @@ -259,7 +213,7 @@ public class MediaProviderMusicTest { Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(), TestValues.SongWithMultipleArtists.thirdArtistId); - Cursor cursor = contentResolver.query(uri, + Cursor cursor = shadowContentResolver.query(uri, TestValues.SongWithMultipleArtists.PROJECTION, null, null, null); @@ -273,7 +227,7 @@ public class MediaProviderMusicTest { public void queryAllSongsTest() { Uri uri = MediaContract.Songs.buildSongsListUri(hostInfo.getId()); - Cursor cursor = contentResolver.query(uri, + Cursor cursor = shadowContentResolver.query(uri, TestValues.ArtistSong.PROJECTION, null, null, null); @@ -283,22 +237,22 @@ public class MediaProviderMusicTest { 1, 1804); //Test if list also contains a song WITH an album AND an artist - assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), - TestValues.SongWithAlbumAndArtist.songId)); + assertTrue(CursorUtils.moveCursorToFirstOccurrence(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), + TestValues.SongWithAlbumAndArtist.songId)); TestValues.SongWithAlbumAndArtist.test(cursor); //Test if list also contains a song WITHOUT an album but WITH an artist - assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), + assertTrue(CursorUtils.moveCursorToFirstOccurrence(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), TestValues.SongWithArtistWithoutAlbum.songId)); TestValues.SongWithArtistWithoutAlbum.test(cursor); //Test if list also contains a song WITH an album but WITHOUT an artist - assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), + assertTrue(CursorUtils.moveCursorToFirstOccurrence(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), TestValues.SongWithAlbumWithoutArtist.songId)); TestValues.SongWithAlbumWithoutArtist.test(cursor); //Test if list contains a song WITH MULTIPLE artists - assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), + assertTrue(CursorUtils.moveCursorToFirstOccurrence(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID), TestValues.SongWithMultipleArtists.songId)); TestValues.SongWithMultipleArtists.test(cursor); } @@ -308,14 +262,13 @@ public class MediaProviderMusicTest { Uri uri = MediaContract.Albums.buildAlbumUri(hostInfo.getId(), TestValues.AlbumWithMultipleArtists.albumId); - Cursor cursor = contentResolver.query(uri, + Cursor cursor = shadowContentResolver.query(uri, TestValues.AlbumWithMultipleArtists.PROJECTION, null, null, null); assertNotNull(cursor); assertEquals("cursor size ", 1, cursor.getCount()); assertTrue(cursor.moveToFirst()); - LogUtils.LOGD("MediaProviderMusicTest", Utils.cursorToString(cursor)); TestValues.AlbumWithMultipleArtists.test(cursor); } @@ -323,7 +276,7 @@ public class MediaProviderMusicTest { public void queryAllGenresTest() { Uri uri = MediaContract.AudioGenres.buildAudioGenresListUri(hostInfo.getId()); - Cursor cursor = contentResolver.query(uri, + Cursor cursor = shadowContentResolver.query(uri, new String[] {MediaContract.AudioGenresColumns.GENREID}, null, null, null); diff --git a/app/src/androidTest/java/org/xbmc/kore/tests/mediaprovider/TestValues.java b/app/src/test/java/org/xbmc/kore/provider/mediaprovider/TestValues.java similarity index 99% rename from app/src/androidTest/java/org/xbmc/kore/tests/mediaprovider/TestValues.java rename to app/src/test/java/org/xbmc/kore/provider/mediaprovider/TestValues.java index 76bc71d..f240567 100644 --- a/app/src/androidTest/java/org/xbmc/kore/tests/mediaprovider/TestValues.java +++ b/app/src/test/java/org/xbmc/kore/provider/mediaprovider/TestValues.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.xbmc.kore.tests.mediaprovider; +package org.xbmc.kore.provider.mediaprovider; import android.database.Cursor; diff --git a/app/src/testUtils/README.md b/app/src/testUtils/README.md new file mode 100644 index 0000000..deae291 --- /dev/null +++ b/app/src/testUtils/README.md @@ -0,0 +1,5 @@ +Resources required for both the local and instrumentation tests. + +**Note**: do not put any tests here! Put local tests +that DO NOT need to be executed on an android device in [test](../test). +Put tests that DO need to run on an android device in [androidTest](../androidTest). diff --git a/app/src/instrumentationTest/assets/AudioLibrary.GetAlbums.json b/app/src/testUtils/assets/AudioLibrary.GetAlbums.json similarity index 100% rename from app/src/instrumentationTest/assets/AudioLibrary.GetAlbums.json rename to app/src/testUtils/assets/AudioLibrary.GetAlbums.json diff --git a/app/src/instrumentationTest/assets/AudioLibrary.GetArtists.json b/app/src/testUtils/assets/AudioLibrary.GetArtists.json similarity index 100% rename from app/src/instrumentationTest/assets/AudioLibrary.GetArtists.json rename to app/src/testUtils/assets/AudioLibrary.GetArtists.json diff --git a/app/src/instrumentationTest/assets/AudioLibrary.GetGenres.json b/app/src/testUtils/assets/AudioLibrary.GetGenres.json similarity index 100% rename from app/src/instrumentationTest/assets/AudioLibrary.GetGenres.json rename to app/src/testUtils/assets/AudioLibrary.GetGenres.json diff --git a/app/src/instrumentationTest/assets/AudioLibrary.GetSongs.json b/app/src/testUtils/assets/AudioLibrary.GetSongs.json similarity index 100% rename from app/src/instrumentationTest/assets/AudioLibrary.GetSongs.json rename to app/src/testUtils/assets/AudioLibrary.GetSongs.json diff --git a/app/src/instrumentationTest/assets/Video.Details.Movie.json b/app/src/testUtils/assets/Video.Details.Movie.json similarity index 100% rename from app/src/instrumentationTest/assets/Video.Details.Movie.json rename to app/src/testUtils/assets/Video.Details.Movie.json diff --git a/app/src/testUtils/java/org/xbmc/kore/testutils/CursorUtils.java b/app/src/testUtils/java/org/xbmc/kore/testutils/CursorUtils.java new file mode 100644 index 0000000..b5a41e8 --- /dev/null +++ b/app/src/testUtils/java/org/xbmc/kore/testutils/CursorUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright 2016 Martijn Brekhof. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.xbmc.kore.testutils; + +import android.database.Cursor; + +public class CursorUtils { + /** + * Converts the current row in cursor to a string with each line + * containing a column name and value pair. + * @param cursor + * @return + */ + public static String cursorToString(Cursor cursor) { + StringBuffer stringBuffer = new StringBuffer(); + for (String name : cursor.getColumnNames()) { + int index = cursor.getColumnIndex(name); + stringBuffer.append(name + "=" + cursor.getString(index) + "\n"); + } + return stringBuffer.toString(); + } + + /** + * Moves cursor to first position item is found at column index + * @param cursor + * @param columnIndex + * @param item integer to search for at given column index + * @return true if item found, false otherwise + */ + public static boolean moveCursorToFirstOccurrence(Cursor cursor, int columnIndex, int item) { + if (( cursor == null ) || ( ! cursor.moveToFirst() )) + return false; + + do { + if ( cursor.getInt(columnIndex) == item ) + return true; + } while (cursor.moveToNext()); + + return false; + } + + /** + * Counts the occurences item is found at given column index + * @param cursor + * @param columnIndex + * @param item integer to search for at given column index + * @return amount of occurences, -1 if an error occured + */ + public static int countOccurences(Cursor cursor, int columnIndex, int item) { + if (( cursor == null ) || ( ! cursor.moveToFirst() )) + return -1; + + int count = 0; + do { + if ( cursor.getInt(columnIndex) == item ) + count++; + } while (cursor.moveToNext()); + + return count; + } +} diff --git a/app/src/androidTest/java/org/xbmc/kore/testhelpers/Database.java b/app/src/testUtils/java/org/xbmc/kore/testutils/Database.java similarity index 57% rename from app/src/androidTest/java/org/xbmc/kore/testhelpers/Database.java rename to app/src/testUtils/java/org/xbmc/kore/testutils/Database.java index bd3188c..576335d 100644 --- a/app/src/androidTest/java/org/xbmc/kore/testhelpers/Database.java +++ b/app/src/testUtils/java/org/xbmc/kore/testutils/Database.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.xbmc.kore.testhelpers; +package org.xbmc.kore.testutils; import android.content.ContentResolver; import android.content.ContentValues; @@ -30,7 +30,6 @@ import org.xbmc.kore.jsonrpc.type.AudioType; import org.xbmc.kore.jsonrpc.type.LibraryType; import org.xbmc.kore.jsonrpc.type.VideoType; import org.xbmc.kore.provider.MediaContract; -import org.xbmc.kore.provider.MediaProvider; import org.xbmc.kore.service.library.SyncMusic; import org.xbmc.kore.service.library.SyncUtils; import org.xbmc.kore.utils.LogUtils; @@ -41,34 +40,33 @@ import java.util.ArrayList; public class Database { public static final String TAG = LogUtils.makeLogTag(Database.class); - public static HostInfo fill(Context context) throws ApiException, IOException { - MediaProvider mediaProvider = new MediaProvider(); - mediaProvider.setContext(context); - mediaProvider.onCreate(); - + public static HostInfo fill(Context context, ContentResolver contentResolver) throws ApiException, IOException { HostInfo hostInfo = addHost(context); + SyncMusic syncMusic = new SyncMusic(hostInfo.getId(), null); - insertMovies(context, hostInfo.getId()); - insertArtists(context, syncMusic); - insertGenres(context, syncMusic); - insertAlbums(context, syncMusic); - insertSongs(context, syncMusic); + + insertMovies(context, contentResolver, hostInfo.getId()); + insertArtists(context, contentResolver, syncMusic); + insertGenres(context, contentResolver, syncMusic); + insertAlbums(context, contentResolver, syncMusic); + insertSongs(context, contentResolver, syncMusic); return hostInfo; } - public static void flush(Context context, HostInfo hostInfo) { - context.getContentResolver() - .delete(MediaContract.Hosts.buildHostUri(hostInfo.getId()), null, null); + public static void flush(ContentResolver contentResolver, HostInfo hostInfo) { + contentResolver.delete(MediaContract.Hosts.buildHostUri(hostInfo.getId()), null, null); } private static HostInfo addHost(Context context) { - return HostManager.getInstance(context).addHost("TestHost", "127.0.0.1", 1, 80, 9090, null, null, "52:54:00:12:35:02", 9, false, 9777); + return HostManager.getInstance(context).addHost("TestHost", "127.0.0.1", 1, 80, 9090, null, + null, "52:54:00:12:35:02", 9, false, 9777); } - private static void insertMovies(Context context, int hostId) throws ApiException, IOException { + public static void insertMovies(Context context, ContentResolver contentResolver, int hostId) + throws ApiException, IOException { VideoLibrary.GetMovies getMovies = new VideoLibrary.GetMovies(); - String result = Utils.readFile(context, "Video.Details.Movie.json"); + String result = FileUtils.readFile(context, "Video.Details.Movie.json"); ApiList movieList = getMovies.resultFromJson(result); @@ -82,7 +80,7 @@ public class Database { castCount += movie.cast.size(); } - context.getContentResolver().bulkInsert(MediaContract.Movies.CONTENT_URI, movieValuesBatch); + contentResolver.bulkInsert(MediaContract.Movies.CONTENT_URI, movieValuesBatch); ContentValues movieCastValuesBatch[] = new ContentValues[castCount]; int count = 0; @@ -95,37 +93,39 @@ public class Database { } } - context.getContentResolver().bulkInsert(MediaContract.MovieCast.CONTENT_URI, movieCastValuesBatch); + contentResolver.bulkInsert(MediaContract.MovieCast.CONTENT_URI, movieCastValuesBatch); } - private static void insertArtists(Context context, SyncMusic syncMusic) throws ApiException, IOException { + private static void insertArtists(Context context, ContentResolver contentResolver, SyncMusic syncMusic) throws ApiException, IOException { AudioLibrary.GetArtists getArtists = new AudioLibrary.GetArtists(false); - String result = Utils.readFile(context, "AudioLibrary.GetArtists.json"); + String result = FileUtils.readFile(context, "AudioLibrary.GetArtists.json"); ArrayList artistList = (ArrayList) getArtists.resultFromJson(result).items; - syncMusic.insertArtists(artistList, context.getContentResolver()); + syncMusic.insertArtists(artistList, contentResolver); } - private static void insertGenres(Context context, SyncMusic syncMusic) throws ApiException, IOException { + private static void insertGenres(Context context, ContentResolver contentResolver, SyncMusic syncMusic) throws ApiException, IOException { AudioLibrary.GetGenres getGenres = new AudioLibrary.GetGenres(); - ArrayList genreList = (ArrayList) getGenres.resultFromJson(Utils.readFile(context, "AudioLibrary.GetGenres.json")); + ArrayList genreList = + (ArrayList) getGenres.resultFromJson(FileUtils.readFile(context, + "AudioLibrary.GetGenres.json")); - syncMusic.insertGenresItems(genreList, context.getContentResolver()); + syncMusic.insertGenresItems(genreList, contentResolver); } - private static void insertAlbums(Context context, SyncMusic syncMusic) throws ApiException, IOException { + private static void insertAlbums(Context context, ContentResolver contentResolver, SyncMusic syncMusic) throws ApiException, IOException { AudioLibrary.GetAlbums getAlbums = new AudioLibrary.GetAlbums(); - String result = Utils.readFile(context, "AudioLibrary.GetAlbums.json"); + String result = FileUtils.readFile(context, "AudioLibrary.GetAlbums.json"); ArrayList albumList = (ArrayList) getAlbums.resultFromJson(result).items; - syncMusic.insertAlbumsItems(albumList, context.getContentResolver()); + syncMusic.insertAlbumsItems(albumList, contentResolver); } - private static void insertSongs(Context context, SyncMusic syncMusic) throws ApiException, IOException { + private static void insertSongs(Context context, ContentResolver contentResolver, SyncMusic syncMusic) throws ApiException, IOException { AudioLibrary.GetSongs getSongs = new AudioLibrary.GetSongs(); ArrayList songList = (ArrayList) - getSongs.resultFromJson(Utils.readFile(context, "AudioLibrary.GetSongs.json")).items; + getSongs.resultFromJson(FileUtils.readFile(context, "AudioLibrary.GetSongs.json")).items; - syncMusic.insertSongsItems(songList, context.getContentResolver()); + syncMusic.insertSongsItems(songList, contentResolver); } } diff --git a/app/src/testUtils/java/org/xbmc/kore/testutils/FileUtils.java b/app/src/testUtils/java/org/xbmc/kore/testutils/FileUtils.java new file mode 100644 index 0000000..8e8b498 --- /dev/null +++ b/app/src/testUtils/java/org/xbmc/kore/testutils/FileUtils.java @@ -0,0 +1,38 @@ +/* + * Copyright 2016 Martijn Brekhof. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.xbmc.kore.testutils; + +import android.content.Context; + +import java.io.IOException; +import java.io.InputStream; + +public class FileUtils { + public static String readFile(Context context, String filename) throws IOException { + InputStream is = context.getAssets().open(filename); + + int size = is.available(); + + byte[] buffer = new byte[size]; + + is.read(buffer); + + is.close(); + + return new String(buffer, "UTF-8"); + } +} diff --git a/app/src/androidTest/java/org/xbmc/kore/testhelpers/TestUtils.java b/app/src/testUtils/java/org/xbmc/kore/testutils/TestUtils.java similarity index 98% rename from app/src/androidTest/java/org/xbmc/kore/testhelpers/TestUtils.java rename to app/src/testUtils/java/org/xbmc/kore/testutils/TestUtils.java index 4b24c06..1ff80e5 100644 --- a/app/src/androidTest/java/org/xbmc/kore/testhelpers/TestUtils.java +++ b/app/src/testUtils/java/org/xbmc/kore/testutils/TestUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.xbmc.kore.testhelpers; +package org.xbmc.kore.testutils; import android.database.Cursor;