package org.fdroid.fdroid.data;
import android.app.Application;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import org.fdroid.fdroid.BuildConfig;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.data.Schema.AppMetadataTable.Cols;
import org.fdroid.fdroid.mock.MockRepo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowContentResolver;
import java.util.List;
import static org.fdroid.fdroid.Assert.assertContainsOnly;
import static org.junit.Assert.assertEquals;
// TODO: Use sdk=24 when Robolectric supports this
@Config(constants = BuildConfig.class, application = Application.class, sdk = 23)
@RunWith(RobolectricGradleTestRunner.class)
public class CategoryProviderTest extends FDroidProviderTest {
@Before
public void setup() {
ShadowContentResolver.registerProvider(AppProvider.getAuthority(), new AppProvider());
}
// ========================================================================
// "Categories"
// (at this point) not an additional table, but we treat them sort of
// like they are. That means that if we change the implementation to
// use a separate table in the future, these should still pass.
// ========================================================================
@Test
public void queryAppsInCategories() {
insertAppWithCategory("com.dog", "Dog", "Animal");
insertAppWithCategory("com.cat", "Cat", "Animal");
insertAppWithCategory("com.crow", "Crow", "Animal,Bird");
insertAppWithCategory("com.chicken", "Chicken", "Animal,Bird,Food");
insertAppWithCategory("com.bird-statue", "Bird Statue", "Bird,Mineral");
insertAppWithCategory("com.rock", "Rock", "Mineral");
insertAppWithCategory("com.banana", "Banana", "Food");
assertPackagesInCategory("Animal", new String[] {
"com.dog",
"com.cat",
"com.crow",
"com.chicken",
});
assertPackagesInCategory("Bird", new String[]{
"com.crow",
"com.chicken",
"com.bird-statue",
});
assertPackagesInCategory("Food", new String[] {
"com.chicken",
"com.banana",
});
assertPackagesInCategory("Mineral", new String[] {
"com.rock",
"com.bird-statue",
});
assertNoPackagesInUri(AppProvider.getCategoryUri("Not a category"));
}
private void assertNoPackagesInUri(Uri uri) {
Cursor noApps = contentResolver.query(uri, Cols.ALL, null, null, null);
assertEquals(noApps.getCount(), 0);
}
private void assertPackagesInCategory(String category, String[] expectedPackages) {
assertPackagesInUri(AppProvider.getCategoryUri(category), expectedPackages);
}
private void assertPackagesInUri(Uri uri, String[] expectedPackages) {
List<App> apps = AppProvider.Helper.cursorToList(contentResolver.query(uri, Cols.ALL, null, null, null));
AppProviderTest.assertContainsOnlyIds(apps, expectedPackages);
}
@Test
public void testCategoriesSingle() {
insertAppWithCategory("com.dog", "Dog", "Animal");
insertAppWithCategory("com.rock", "Rock", "Mineral");
insertAppWithCategory("com.banana", "Banana", "Vegetable");
List<String> categories = CategoryProvider.Helper.categories(context);
String[] expected = new String[] {
context.getResources().getString(R.string.category_Whats_New),
context.getResources().getString(R.string.category_Recently_Updated),
context.getResources().getString(R.string.category_All),
"Animal",
"Mineral",
"Vegetable",
};
assertContainsOnly(categories, expected);
}
@Test
public void testCategoriesMultiple() {
long mainRepo = 1;
insertAppWithCategory("com.rock.dog", "Rock-Dog", "Mineral,Animal", mainRepo);
insertAppWithCategory("com.dog.rock.apple", "Dog-Rock-Apple", "Animal,Mineral,Vegetable", mainRepo);
insertAppWithCategory("com.banana.apple", "Banana", "Vegetable,Vegetable", mainRepo);
List<String> categories = CategoryProvider.Helper.categories(context);
String[] expected = new String[] {
context.getResources().getString(R.string.category_Whats_New),
context.getResources().getString(R.string.category_Recently_Updated),
context.getResources().getString(R.string.category_All),
"Animal",
"Mineral",
"Vegetable",
};
assertContainsOnly(categories, expected);
int additionalRepo = 2;
insertAppWithCategory("com.example.game", "Game",
"Running,Shooting,Jumping,Bleh,Sneh,Pleh,Blah,Test category," +
"The quick brown fox jumps over the lazy dog,With apostrophe's", additionalRepo);
List<String> categoriesLonger = CategoryProvider.Helper.categories(context);
String[] expectedLonger = new String[] {
context.getResources().getString(R.string.category_Whats_New),
context.getResources().getString(R.string.category_Recently_Updated),
context.getResources().getString(R.string.category_All),
"Animal",
"Mineral",
"Vegetable",
"Running",
"Shooting",
"Jumping",
"Bleh",
"Sneh",
"Pleh",
"Blah",
"Test category",
"The quick brown fox jumps over the lazy dog",
"With apostrophe's",
};
assertContainsOnly(categoriesLonger, expectedLonger);
RepoProvider.Helper.purgeApps(context, new MockRepo(additionalRepo));
List<String> categoriesAfterPurge = CategoryProvider.Helper.categories(context);
assertContainsOnly(categoriesAfterPurge, expected);
}
private void insertAppWithCategory(String id, String name, String categories) {
insertAppWithCategory(id, name, categories, 1);
}
private void insertAppWithCategory(String id, String name, String categories, long repoId) {
ContentValues values = new ContentValues(1);
values.put(Cols.ForWriting.Categories.CATEGORIES, categories);
AppProviderTest.insertApp(contentResolver, context, id, name, values, repoId);
}
}