From b6503464bb8364766e9525a40cd9a71c6718d827 Mon Sep 17 00:00:00 2001 From: hritikRitss <113812066+hritikRitss@users.noreply.github.com> Date: Thu, 2 Oct 2025 22:58:43 +0530 Subject: [PATCH] Refactor(DB): Replace rawQuery with query builder and use try-with-resources --- .../java/protect/card_locker/DBHelper.java | 212 +++++++++++------ .../protect/card_locker/MainActivity.java | 2 - .../protect/card_locker/DatabaseTest.java | 57 +++-- .../protect/card_locker/ImportExportTest.java | 220 +++++++++--------- .../java/protect/card_locker/TestHelpers.java | 33 +-- 5 files changed, 288 insertions(+), 236 deletions(-) diff --git a/app/src/main/java/protect/card_locker/DBHelper.java b/app/src/main/java/protect/card_locker/DBHelper.java index 88ad9167bb..1b9378f3d5 100644 --- a/app/src/main/java/protect/card_locker/DBHelper.java +++ b/app/src/main/java/protect/card_locker/DBHelper.java @@ -284,37 +284,38 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { LoyaltyCardDbFTS.STORE + ", " + LoyaltyCardDbFTS.NOTE + ", " + "tokenize=unicode61);"); - Cursor cursor = db.rawQuery("SELECT * FROM " + LoyaltyCardDbIds.TABLE + ";", null, null); + try (Cursor cursor = db.query( + LoyaltyCardDbIds.TABLE, + new String[]{LoyaltyCardDbIds.ID, LoyaltyCardDbIds.STORE, LoyaltyCardDbIds.NOTE}, + null, null, null, null, null, null) + ) { + cursor.moveToFirst(); - cursor.moveToFirst(); - - while (cursor.moveToNext()) { - int id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID)); - String store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)); - String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)); - insertFTS(db, id, store, note); + while (cursor.moveToNext()) { + int id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID)); + String store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)); + String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)); + insertFTS(db, id, store, note); + } } } if (oldVersion < 13 && newVersion >= 13) { db.execSQL("DELETE FROM " + LoyaltyCardDbFTS.TABLE + ";"); - Cursor cursor = db.rawQuery("SELECT * FROM " + LoyaltyCardDbIds.TABLE + ";", null, null); - - if (cursor.moveToFirst()) { - int id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID)); - String store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)); - String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)); - insertFTS(db, id, store, note); - + try(Cursor cursor = db.query( + LoyaltyCardDbIds.TABLE, + new String[]{LoyaltyCardDbIds.ID, LoyaltyCardDbIds.STORE, LoyaltyCardDbIds.NOTE}, + null, null, null, null, null + )){ + // This single loop handles all cases, including an empty cursor. while (cursor.moveToNext()) { - id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID)); - store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)); - note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)); + int id = cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ID)); + String store = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE)); + String note = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE)); insertFTS(db, id, store, note); } } - cursor.close(); } if (oldVersion < 14 && newVersion >= 14) { @@ -562,26 +563,36 @@ public static LoyaltyCard getLoyaltyCard(Context context, SQLiteDatabase databas } public static List getLoyaltyCardGroups(SQLiteDatabase database, final int id) { - Cursor data = database.rawQuery("select * from " + LoyaltyCardDbGroups.TABLE + " g " + - " LEFT JOIN " + LoyaltyCardDbIdsGroups.TABLE + " ig ON ig." + LoyaltyCardDbIdsGroups.groupID + " = g." + LoyaltyCardDbGroups.ID + - " where " + LoyaltyCardDbIdsGroups.cardID + "=?" + - " ORDER BY " + LoyaltyCardDbIdsGroups.groupID, withArgs(id)); - + // A list to hold the resulting Group objects. List groups = new ArrayList<>(); - if (!data.moveToFirst()) { - data.close(); - return groups; - } - - groups.add(Group.toGroup(data)); - - while (data.moveToNext()) { - groups.add(Group.toGroup(data)); + // Define the table join for the query. + String table = LoyaltyCardDbGroups.TABLE + " g LEFT JOIN " + + LoyaltyCardDbIdsGroups.TABLE + " ig ON ig." + + LoyaltyCardDbIdsGroups.groupID + " = g." + LoyaltyCardDbGroups.ID; + + // Define the WHERE clause and its arguments. + String selection = LoyaltyCardDbIdsGroups.cardID + " = ?"; + String[] selectionArgs = { String.valueOf(id) }; + + // Define the ORDER BY clause. + String orderBy = LoyaltyCardDbIdsGroups.groupID; + + try(Cursor cursor = database.query( + table, + null, // Using null for columns selects all ('*'). + selection, + selectionArgs, + null, + null, + orderBy + )){ + // A single while loop is cleaner for iterating through the cursor. + while (cursor.moveToNext()) { + groups.add(Group.toGroup(cursor)); + } } - data.close(); - return groups; } @@ -633,20 +644,29 @@ public static int getArchivedCardsCount(SQLiteDatabase database) { whereAttrs(LoyaltyCardDbIds.ARCHIVE_STATUS), withArgs(1)); } + /** + * Calculates the number of archived loyalty cards within a specific group. + *

+ * This method performs a query with a LEFT JOIN on the card and group-linking tables + * to find cards that are both marked as archived and associated with the specified group name. + * For optimal performance, it uses {@link DatabaseUtils#longForQuery(SQLiteDatabase, String, String[])} + * to execute a COUNT(*) query, which is significantly more efficient than retrieving all + * matching rows into a Cursor just to get the count. + * + * @param database The readable SQLiteDatabase instance to query against. + * @param groupName The name of the group for which to count archived cards. + * @return The total number of archived cards found in the specified group. + */ public static int getArchivedCardsCount(SQLiteDatabase database, final String groupName) { - Cursor data = database.rawQuery( - "select * from " + LoyaltyCardDbIds.TABLE + " c " + - " LEFT JOIN " + LoyaltyCardDbIdsGroups.TABLE + " cg " + - " ON c." + LoyaltyCardDbIds.ID + " = cg." + LoyaltyCardDbIdsGroups.cardID + - " where " + LoyaltyCardDbIds.ARCHIVE_STATUS + " = 1" + - " AND " + LoyaltyCardDbIdsGroups.groupID + "= ?", - withArgs(groupName) - ); + String query = "SELECT COUNT(*) FROM " + LoyaltyCardDbIds.TABLE + " c " + + "LEFT JOIN " + LoyaltyCardDbIdsGroups.TABLE + " cg " + + "ON c." + LoyaltyCardDbIds.ID + " = cg." + LoyaltyCardDbIdsGroups.cardID + + " WHERE " + LoyaltyCardDbIds.ARCHIVE_STATUS + " = 1" + + " AND " + LoyaltyCardDbIdsGroups.groupID + " = ?"; - int count = data.getCount(); + long count = DatabaseUtils.longForQuery(database, query, new String[]{groupName}); - data.close(); - return count; + return (int) count; } public static Cursor getLoyaltyCardCursor(SQLiteDatabase database) { @@ -689,47 +709,79 @@ public static Cursor getLoyaltyCardCursor(SQLiteDatabase database, final String * @return Cursor */ public static Cursor getLoyaltyCardCursor(SQLiteDatabase database, String filter, Group group, LoyaltyCardOrder order, LoyaltyCardOrderDirection direction, LoyaltyCardArchiveFilter archiveFilter) { - StringBuilder groupFilter = new StringBuilder(); - String limitString = ""; + // Use lists to dynamically and safely build the WHERE clause and its arguments. + List conditions = new ArrayList<>(); + List selectionArgs = new ArrayList<>(); - if (group != null) { - List allowedIds = getGroupCardIds(database, group._id); + // 1. Full-Text Search (FTS) Filter + String trimmedFilter = filter.trim(); + if (!trimmedFilter.isEmpty()) { + Log.d("MyQueryDebug", "Filter is NOT empty. Adding MATCH clause."); + conditions.add(LoyaltyCardDbFTS.TABLE + " MATCH ?"); + // Prepare the filter argument for FTS (e.g., "word1 word2" -> "word1* word2*") + selectionArgs.add(TextUtils.join("* ", trimmedFilter.split(" ")) + '*'); + } - // Empty group - if (!allowedIds.isEmpty()) { - groupFilter.append("AND ("); + // 2. Archive Status Filter + if (archiveFilter != LoyaltyCardArchiveFilter.All) { + conditions.add(LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ARCHIVE_STATUS + " = ?"); + selectionArgs.add(archiveFilter.equals(LoyaltyCardArchiveFilter.Unarchived) ? "0" : "1"); + } + // 3. Group Filter + if (group != null) { + List allowedIds = getGroupCardIds(database, group._id); + if (allowedIds.isEmpty()) { + // If the group has no cards, add a condition that is always false. + // This is a safe and clean replacement for the original "LIMIT 0" hack. + conditions.add("LIMIT=0"); + } else { + // Build a "?,?,?" string for the IN clause based on the number of IDs. + StringBuilder inClausePlaceholders = new StringBuilder(); for (int i = 0; i < allowedIds.size(); i++) { - groupFilter.append(LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ID + " = ").append(allowedIds.get(i)); - if (i != allowedIds.size() - 1) { - groupFilter.append(" OR "); + inClausePlaceholders.append("?"); + if (i < allowedIds.size() - 1) { + inClausePlaceholders.append(","); } } - groupFilter.append(") "); - } else { - limitString = "LIMIT 0"; + conditions.add(LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ID + " IN (" + inClausePlaceholders + ")"); + + // Add all the group card IDs to the selection arguments. + for (Integer id : allowedIds) { + selectionArgs.add(String.valueOf(id)); + } } } - String archiveFilterString = ""; - if (archiveFilter != LoyaltyCardArchiveFilter.All) { - archiveFilterString = " AND " + LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ARCHIVE_STATUS + " = " + (archiveFilter.equals(LoyaltyCardArchiveFilter.Unarchived) ? 0 : 1); - } + // Define the tables to join. + String table = LoyaltyCardDbIds.TABLE + + " JOIN " + LoyaltyCardDbFTS.TABLE + + " ON " + LoyaltyCardDbFTS.TABLE + "." + LoyaltyCardDbFTS.ID + " = " + LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ID; - String orderField = getFieldForOrder(order); + // Combine all conditions with " AND ". + String selection = TextUtils.join(" AND ", conditions); - return database.rawQuery("SELECT " + LoyaltyCardDbIds.TABLE + ".* FROM " + LoyaltyCardDbIds.TABLE + - " JOIN " + LoyaltyCardDbFTS.TABLE + - " ON " + LoyaltyCardDbFTS.TABLE + "." + LoyaltyCardDbFTS.ID + " = " + LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ID + - (filter.trim().isEmpty() ? " " : " AND " + LoyaltyCardDbFTS.TABLE + " MATCH ? ") + - groupFilter.toString() + - archiveFilterString + - " ORDER BY " + LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ARCHIVE_STATUS + " ASC, " + + // Build the complex ORDER BY clause. This is safe as it contains no user data. + String orderField = getFieldForOrder(order); + String orderBy = LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.ARCHIVE_STATUS + " ASC, " + LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.STAR_STATUS + " DESC, " + " (CASE WHEN " + LoyaltyCardDbIds.TABLE + "." + orderField + " IS NULL THEN 1 ELSE 0 END), " + - LoyaltyCardDbIds.TABLE + "." + orderField + " COLLATE NOCASE " + getDbDirection(order, direction) + ", " + - LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC " + - limitString, filter.trim().isEmpty() ? null : new String[]{TextUtils.join("* ", filter.split(" ")) + '*'}, null); + LoyaltyCardDbIds.TABLE + "." + orderField + " COLLATE NOCASE " + getDbDirection(order, direction); + + if(order != LoyaltyCardOrder.Alpha) { + orderBy += ", " + LoyaltyCardDbIds.TABLE + "." + LoyaltyCardDbIds.STORE + " COLLATE NOCASE ASC"; + } + + // Execute the query using the safe builder method. + return database.query( + table, + new String[]{LoyaltyCardDbIds.TABLE + ".*"}, // Using null for columns selects all ('*'). + selection, + selectionArgs.toArray(new String[0]), + null, // groupBy + null, // having + orderBy + ); } /** @@ -747,8 +799,14 @@ public static int getLoyaltyCardCount(SQLiteDatabase database) { * @return Cursor */ public static Cursor getGroupCursor(SQLiteDatabase database) { - return database.rawQuery("select * from " + LoyaltyCardDbGroups.TABLE + - " ORDER BY " + LoyaltyCardDbGroups.ORDER + " ASC," + LoyaltyCardDbGroups.ID + " COLLATE NOCASE ASC", null, null); + String table = LoyaltyCardDbGroups.TABLE; + String orderBy = LoyaltyCardDbGroups.ORDER + " ASC," + LoyaltyCardDbGroups.ID + " COLLATE NOCASE ASC"; + + return database.query( + table, + null, // Using null for columns selects all ('*'). + null, null, null, null, orderBy + ); } public static List getGroups(SQLiteDatabase database) { diff --git a/app/src/main/java/protect/card_locker/MainActivity.java b/app/src/main/java/protect/card_locker/MainActivity.java index 777c319d2d..8bfe827d1c 100644 --- a/app/src/main/java/protect/card_locker/MainActivity.java +++ b/app/src/main/java/protect/card_locker/MainActivity.java @@ -2,8 +2,6 @@ import android.app.Activity; import android.app.SearchManager; -import android.appwidget.AppWidgetManager; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; diff --git a/app/src/test/java/protect/card_locker/DatabaseTest.java b/app/src/test/java/protect/card_locker/DatabaseTest.java index 5c89dc82e9..739007be7e 100644 --- a/app/src/test/java/protect/card_locker/DatabaseTest.java +++ b/app/src/test/java/protect/card_locker/DatabaseTest.java @@ -41,7 +41,7 @@ public void setUp() { @Test public void addRemoveOneGiftCard() { assertEquals(0, DBHelper.getLoyaltyCardCount(mDatabase)); - long id = DBHelper.insertLoyaltyCard(mDatabase, "store", "note", null, null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null,0); + long id = DBHelper.insertLoyaltyCard(mDatabase, "store", "note", null, null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null, 0); boolean result = (id != -1); assertTrue(result); assertEquals(1, DBHelper.getLoyaltyCardCount(mDatabase)); @@ -69,7 +69,7 @@ public void addRemoveOneGiftCard() { @Test public void updateGiftCard() { - long id = DBHelper.insertLoyaltyCard(mDatabase, "store", "note", null, null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null,0); + long id = DBHelper.insertLoyaltyCard(mDatabase, "store", "note", null, null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null, 0); boolean result = (id != -1); assertTrue(result); assertEquals(1, DBHelper.getLoyaltyCardCount(mDatabase)); @@ -96,7 +96,7 @@ public void updateGiftCard() { @Test public void updateGiftCardOnlyStar() { - long id = DBHelper.insertLoyaltyCard(mDatabase, "store", "note", null, null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null,0); + long id = DBHelper.insertLoyaltyCard(mDatabase, "store", "note", null, null, new BigDecimal("0"), null, "cardId", null, CatimaBarcode.fromBarcode(BarcodeFormat.UPC_A), DEFAULT_HEADER_COLOR, 0, null, 0); boolean result = (id != -1); assertTrue(result); assertEquals(1, DBHelper.getLoyaltyCardCount(mDatabase)); @@ -133,7 +133,7 @@ public void updateMissingGiftCard() { @Test public void emptyGiftCardValues() { - long id = DBHelper.insertLoyaltyCard(mDatabase, "", "", null, null, new BigDecimal("0"), null, "", null, null, null, 0, null,0); + long id = DBHelper.insertLoyaltyCard(mDatabase, "", "", null, null, new BigDecimal("0"), null, "", null, null, null, 0, null, 0); boolean result = (id != -1); assertTrue(result); assertEquals(1, DBHelper.getLoyaltyCardCount(mDatabase)); @@ -168,34 +168,31 @@ public void giftCardsViaCursor() { } assertEquals(CARDS_TO_ADD, DBHelper.getLoyaltyCardCount(mDatabase)); + try (Cursor cursor = DBHelper.getLoyaltyCardCursor(mDatabase)) { + assertNotNull(cursor); + assertEquals(CARDS_TO_ADD, cursor.getCount()); + + cursor.moveToFirst(); + + for (int index = 0; index < CARDS_TO_ADD; index++) { + assertEquals("store" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE))); + assertEquals("note" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE))); + assertEquals(0, cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.VALID_FROM))); + assertEquals(0, cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY))); + assertEquals("0", cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE))); + assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE))); + assertEquals("cardId" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID))); + assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID))); + assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE))); + assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR))); + assertEquals(0, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STAR_STATUS))); + assertEquals(0, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ARCHIVE_STATUS))); + + cursor.moveToNext(); + } - Cursor cursor = DBHelper.getLoyaltyCardCursor(mDatabase); - assertNotNull(cursor); - - assertEquals(CARDS_TO_ADD, cursor.getCount()); - - cursor.moveToFirst(); - - for (int index = 0; index < CARDS_TO_ADD; index++) { - assertEquals("store" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STORE))); - assertEquals("note" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.NOTE))); - assertEquals(0, cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.VALID_FROM))); - assertEquals(0, cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.EXPIRY))); - assertEquals("0", cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE))); - assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BALANCE_TYPE))); - assertEquals("cardId" + index, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.CARD_ID))); - assertEquals(null, cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_ID))); - assertEquals(BarcodeFormat.UPC_A.toString(), cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.BARCODE_TYPE))); - assertEquals(index, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.HEADER_COLOR))); - assertEquals(0, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.STAR_STATUS))); - assertEquals(0, cursor.getInt(cursor.getColumnIndexOrThrow(DBHelper.LoyaltyCardDbIds.ARCHIVE_STATUS))); - - cursor.moveToNext(); + assertTrue(cursor.isAfterLast()); } - - assertTrue(cursor.isAfterLast()); - - cursor.close(); } @Test diff --git a/app/src/test/java/protect/card_locker/ImportExportTest.java b/app/src/test/java/protect/card_locker/ImportExportTest.java index 370af487f8..6cee4a7ee9 100644 --- a/app/src/test/java/protect/card_locker/ImportExportTest.java +++ b/app/src/test/java/protect/card_locker/ImportExportTest.java @@ -73,7 +73,7 @@ private void addLoyaltyCardsFiveStarred() { for (int index = cardsToAdd; index > 4; index--) { String storeName = String.format("store, \"%4d", index); String note = String.format("note, \"%4d", index); - long id = DBHelper.insertLoyaltyCard(mDatabase, storeName, note, null, null, new BigDecimal(String.valueOf(index)), null, BARCODE_DATA, null, BARCODE_TYPE, index, 1, null,0); + long id = DBHelper.insertLoyaltyCard(mDatabase, storeName, note, null, null, new BigDecimal(String.valueOf(index)), null, BARCODE_DATA, null, BARCODE_TYPE, index, 1, null, 0); boolean result = (id != -1); assertTrue(result); } @@ -81,7 +81,7 @@ private void addLoyaltyCardsFiveStarred() { String storeName = String.format("store, \"%4d", index); String note = String.format("note, \"%4d", index); //if index is even - long id = DBHelper.insertLoyaltyCard(mDatabase, storeName, note, null, null, new BigDecimal(String.valueOf(index)), null, BARCODE_DATA, null, BARCODE_TYPE, index, 0, null,0); + long id = DBHelper.insertLoyaltyCard(mDatabase, storeName, note, null, null, new BigDecimal(String.valueOf(index)), null, BARCODE_DATA, null, BARCODE_TYPE, index, 0, null, 0); boolean result = (id != -1); assertTrue(result); } @@ -90,7 +90,7 @@ private void addLoyaltyCardsFiveStarred() { @Test public void addLoyaltyCardsWithExpiryNeverPastTodayFuture() { - long id = DBHelper.insertLoyaltyCard(mDatabase, "No Expiry", "", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, 0, 0, null,0); + long id = DBHelper.insertLoyaltyCard(mDatabase, "No Expiry", "", null, null, new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, 0, 0, null, 0); boolean result = (id != -1); assertTrue(result); @@ -107,7 +107,7 @@ public void addLoyaltyCardsWithExpiryNeverPastTodayFuture() { assertEquals(Integer.valueOf(0), card.headerColor); assertEquals(0, card.starStatus); - id = DBHelper.insertLoyaltyCard(mDatabase, "Past", "", null, new Date((long) 1), new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, 0, 0, null,0); + id = DBHelper.insertLoyaltyCard(mDatabase, "Past", "", null, new Date((long) 1), new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, 0, 0, null, 0); result = (id != -1); assertTrue(result); @@ -124,7 +124,7 @@ public void addLoyaltyCardsWithExpiryNeverPastTodayFuture() { assertEquals(Integer.valueOf(0), card.headerColor); assertEquals(0, card.starStatus); - id = DBHelper.insertLoyaltyCard(mDatabase, "Today", "", null, new Date(), new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, 0, 0, null,0); + id = DBHelper.insertLoyaltyCard(mDatabase, "Today", "", null, new Date(), new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, 0, 0, null, 0); result = (id != -1); assertTrue(result); @@ -144,7 +144,7 @@ public void addLoyaltyCardsWithExpiryNeverPastTodayFuture() { // This will break after 19 January 2038 // If someone is still maintaining this code base by then: I love you - id = DBHelper.insertLoyaltyCard(mDatabase, "Future", "", null, new Date(2147483648000L), new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, 0, 0, null,0); + id = DBHelper.insertLoyaltyCard(mDatabase, "Future", "", null, new Date(2147483648000L), new BigDecimal("0"), null, BARCODE_DATA, null, BARCODE_TYPE, 0, 0, null, 0); result = (id != -1); assertTrue(result); @@ -170,59 +170,58 @@ public void addLoyaltyCardsWithExpiryNeverPastTodayFuture() { * where the smallest card's index is 1 */ private void checkLoyaltyCards() { - Cursor cursor = DBHelper.getLoyaltyCardCursor(mDatabase); - int index = 1; - - while (cursor.moveToNext()) { - LoyaltyCard card = LoyaltyCard.fromCursor(activity.getApplicationContext(), cursor); - - String expectedStore = String.format("store, \"%4d", index); - String expectedNote = String.format("note, \"%4d", index); - - assertEquals(expectedStore, card.store); - assertEquals(expectedNote, card.note); - assertEquals(null, card.validFrom); - assertEquals(null, card.expiry); - assertEquals(new BigDecimal(String.valueOf(index)), card.balance); - assertEquals(null, card.balanceType); - assertEquals(BARCODE_DATA, card.cardId); - assertEquals(null, card.barcodeId); - assertEquals(BARCODE_TYPE.format(), card.barcodeType.format()); - assertEquals(Integer.valueOf(index), card.headerColor); - assertEquals(0, card.starStatus); - - index++; + try (Cursor cursor = DBHelper.getLoyaltyCardCursor(mDatabase)) { + int index = 1; + + while (cursor.moveToNext()) { + LoyaltyCard card = LoyaltyCard.fromCursor(activity.getApplicationContext(), cursor); + + String expectedStore = String.format("store, \"%4d", index); + String expectedNote = String.format("note, \"%4d", index); + + assertEquals(expectedStore, card.store); + assertEquals(expectedNote, card.note); + assertEquals(null, card.validFrom); + assertEquals(null, card.expiry); + assertEquals(new BigDecimal(String.valueOf(index)), card.balance); + assertEquals(null, card.balanceType); + assertEquals(BARCODE_DATA, card.cardId); + assertEquals(null, card.barcodeId); + assertEquals(BARCODE_TYPE.format(), card.barcodeType.format()); + assertEquals(Integer.valueOf(index), card.headerColor); + assertEquals(0, card.starStatus); + + index++; + } } - cursor.close(); } private void checkLoyaltyCardsAndDuplicates(int numCards) { - Cursor cursor = DBHelper.getLoyaltyCardCursor(mDatabase); - - while (cursor.moveToNext()) { - LoyaltyCard card = LoyaltyCard.fromCursor(activity.getApplicationContext(), cursor); - - // ID goes up for duplicates (b/c the cursor orders by store), down for originals - int index = card.id > numCards ? card.id - numCards : numCards - card.id + 1; - // balance is doubled for modified originals - int balance = card.id > numCards ? index : index * 2; - - String expectedStore = String.format("store, \"%4d", index); - String expectedNote = String.format("note, \"%4d", index); - - assertEquals(expectedStore, card.store); - assertEquals(expectedNote, card.note); - assertEquals(null, card.validFrom); - assertEquals(null, card.expiry); - assertEquals(new BigDecimal(String.valueOf(balance)), card.balance); - assertEquals(null, card.balanceType); - assertEquals(BARCODE_DATA, card.cardId); - assertEquals(null, card.barcodeId); - assertEquals(BARCODE_TYPE.format(), card.barcodeType.format()); - assertEquals(Integer.valueOf(index), card.headerColor); - assertEquals(0, card.starStatus); + try (Cursor cursor = DBHelper.getLoyaltyCardCursor(mDatabase)) { + while (cursor.moveToNext()) { + LoyaltyCard card = LoyaltyCard.fromCursor(activity.getApplicationContext(), cursor); + + // ID goes up for duplicates (b/c the cursor orders by store), down for originals + int index = card.id > numCards ? card.id - numCards : numCards - card.id + 1; + // balance is doubled for modified originals + int balance = card.id > numCards ? index : index * 2; + + String expectedStore = String.format("store, \"%4d", index); + String expectedNote = String.format("note, \"%4d", index); + + assertEquals(expectedStore, card.store); + assertEquals(expectedNote, card.note); + assertEquals(null, card.validFrom); + assertEquals(null, card.expiry); + assertEquals(new BigDecimal(String.valueOf(balance)), card.balance); + assertEquals(null, card.balanceType); + assertEquals(BARCODE_DATA, card.cardId); + assertEquals(null, card.barcodeId); + assertEquals(BARCODE_TYPE.format(), card.barcodeType.format()); + assertEquals(Integer.valueOf(index), card.headerColor); + assertEquals(0, card.starStatus); + } } - cursor.close(); } /** @@ -231,54 +230,53 @@ private void checkLoyaltyCardsAndDuplicates(int numCards) { * with starred ones first */ private void checkLoyaltyCardsFiveStarred() { - Cursor cursor = DBHelper.getLoyaltyCardCursor(mDatabase); - int index = 5; - - while (index < 10) { - cursor.moveToNext(); - LoyaltyCard card = LoyaltyCard.fromCursor(activity.getApplicationContext(), cursor); - - String expectedStore = String.format("store, \"%4d", index); - String expectedNote = String.format("note, \"%4d", index); - - assertEquals(expectedStore, card.store); - assertEquals(expectedNote, card.note); - assertEquals(null, card.validFrom); - assertEquals(null, card.expiry); - assertEquals(new BigDecimal(String.valueOf(index)), card.balance); - assertEquals(null, card.balanceType); - assertEquals(BARCODE_DATA, card.cardId); - assertEquals(null, card.barcodeId); - assertEquals(BARCODE_TYPE.format(), card.barcodeType.format()); - assertEquals(Integer.valueOf(index), card.headerColor); - assertEquals(1, card.starStatus); - - index++; - } + try (Cursor cursor = DBHelper.getLoyaltyCardCursor(mDatabase)) { + int index = 5; + + while (index < 10) { + cursor.moveToNext(); + LoyaltyCard card = LoyaltyCard.fromCursor(activity.getApplicationContext(), cursor); + + String expectedStore = String.format("store, \"%4d", index); + String expectedNote = String.format("note, \"%4d", index); + + assertEquals(expectedStore, card.store); + assertEquals(expectedNote, card.note); + assertEquals(null, card.validFrom); + assertEquals(null, card.expiry); + assertEquals(new BigDecimal(String.valueOf(index)), card.balance); + assertEquals(null, card.balanceType); + assertEquals(BARCODE_DATA, card.cardId); + assertEquals(null, card.barcodeId); + assertEquals(BARCODE_TYPE.format(), card.barcodeType.format()); + assertEquals(Integer.valueOf(index), card.headerColor); + assertEquals(1, card.starStatus); + + index++; + } - index = 1; - while (cursor.moveToNext() && index < 5) { - LoyaltyCard card = LoyaltyCard.fromCursor(activity.getApplicationContext(), cursor); - - String expectedStore = String.format("store, \"%4d", index); - String expectedNote = String.format("note, \"%4d", index); - - assertEquals(expectedStore, card.store); - assertEquals(expectedNote, card.note); - assertEquals(null, card.validFrom); - assertEquals(null, card.expiry); - assertEquals(new BigDecimal(String.valueOf(index)), card.balance); - assertEquals(null, card.balanceType); - assertEquals(BARCODE_DATA, card.cardId); - assertEquals(null, card.barcodeId); - assertEquals(BARCODE_TYPE.format(), card.barcodeType.format()); - assertEquals(Integer.valueOf(index), card.headerColor); - assertEquals(0, card.starStatus); - - index++; + index = 1; + while (cursor.moveToNext() && index < 5) { + LoyaltyCard card = LoyaltyCard.fromCursor(activity.getApplicationContext(), cursor); + + String expectedStore = String.format("store, \"%4d", index); + String expectedNote = String.format("note, \"%4d", index); + + assertEquals(expectedStore, card.store); + assertEquals(expectedNote, card.note); + assertEquals(null, card.validFrom); + assertEquals(null, card.expiry); + assertEquals(new BigDecimal(String.valueOf(index)), card.balance); + assertEquals(null, card.balanceType); + assertEquals(BARCODE_DATA, card.cardId); + assertEquals(null, card.barcodeId); + assertEquals(BARCODE_TYPE.format(), card.barcodeType.format()); + assertEquals(Integer.valueOf(index), card.headerColor); + assertEquals(0, card.starStatus); + + index++; + } } - - cursor.close(); } /** @@ -287,19 +285,19 @@ private void checkLoyaltyCardsFiveStarred() { * where the smallest group's index is 1 */ private void checkGroups() { - Cursor cursor = DBHelper.getGroupCursor(mDatabase); - int index = DBHelper.getGroupCount(mDatabase); + try (Cursor cursor = DBHelper.getGroupCursor(mDatabase)) { + int index = DBHelper.getGroupCount(mDatabase); - while (cursor.moveToNext()) { - Group group = Group.toGroup(cursor); + while (cursor.moveToNext()) { + Group group = Group.toGroup(cursor); - String expectedGroupName = String.format("group, \"%4d", index); + String expectedGroupName = String.format("group, \"%4d", index); - assertEquals(expectedGroupName, group._id); + assertEquals(expectedGroupName, group._id); - index--; + index--; + } } - cursor.close(); } @Test @@ -432,7 +430,7 @@ public void multipleCardsExportImportWithGroups() throws IOException { groupsForFour.add(DBHelper.getGroup(mDatabase, "group, \" 3")); List groupsForFive = new ArrayList<>(); - groupsForFive.add(DBHelper.getGroup(mDatabase,"group, \" 1")); + groupsForFive.add(DBHelper.getGroup(mDatabase, "group, \" 1")); groupsForFive.add(DBHelper.getGroup(mDatabase, "group, \" 3")); DBHelper.setLoyaltyCardGroups(mDatabase, 1, groupsForOne); @@ -830,7 +828,7 @@ public void exportImportV2Zip() throws FileNotFoundException { HashMap loyaltyCardIconImages = new HashMap<>(); // Create card 1 - int loyaltyCardId = (int) DBHelper.insertLoyaltyCard(mDatabase, "Card 1", "Note 1", new Date(1601510400), new Date(1618053234), new BigDecimal("100"), Currency.getInstance("USD"), "1234", "5432", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE), 1, 0, null,0); + int loyaltyCardId = (int) DBHelper.insertLoyaltyCard(mDatabase, "Card 1", "Note 1", new Date(1601510400), new Date(1618053234), new BigDecimal("100"), Currency.getInstance("USD"), "1234", "5432", CatimaBarcode.fromBarcode(BarcodeFormat.QR_CODE), 1, 0, null, 0); loyaltyCardHashMap.put(loyaltyCardId, DBHelper.getLoyaltyCard(activity.getApplicationContext(), mDatabase, loyaltyCardId)); DBHelper.insertGroup(mDatabase, "One"); List groups = Arrays.asList(DBHelper.getGroup(mDatabase, "One")); @@ -844,7 +842,7 @@ public void exportImportV2Zip() throws FileNotFoundException { loyaltyCardIconImages.put(loyaltyCardId, bitmap1); // Create card 2 - loyaltyCardId = (int) DBHelper.insertLoyaltyCard(mDatabase, "Card 2", "", null, null, new BigDecimal(0), null, "123456", null, null, 2, 1, null,0); + loyaltyCardId = (int) DBHelper.insertLoyaltyCard(mDatabase, "Card 2", "", null, null, new BigDecimal(0), null, "123456", null, null, 2, 1, null, 0); loyaltyCardHashMap.put(loyaltyCardId, DBHelper.getLoyaltyCard(activity.getApplicationContext(), mDatabase, loyaltyCardId)); // Export everything diff --git a/app/src/test/java/protect/card_locker/TestHelpers.java b/app/src/test/java/protect/card_locker/TestHelpers.java index 1704902a27..50eb53b812 100644 --- a/app/src/test/java/protect/card_locker/TestHelpers.java +++ b/app/src/test/java/protect/card_locker/TestHelpers.java @@ -21,27 +21,28 @@ public static DBHelper getEmptyDb(Context context) { SQLiteDatabase database = db.getWritableDatabase(); // Make sure no files remain - Cursor cursor = DBHelper.getLoyaltyCardCursor(database); - cursor.moveToFirst(); - while (!cursor.isAfterLast()) { - int cardID = cursor.getColumnIndex(DBHelper.LoyaltyCardDbIds.ID); + try(Cursor cursor = DBHelper.getLoyaltyCardCursor(database)){ + cursor.moveToFirst(); + while (!cursor.isAfterLast()) { + int cardID = cursor.getColumnIndex(DBHelper.LoyaltyCardDbIds.ID); - for (ImageLocationType imageLocationType : ImageLocationType.values()) { - try { - Utils.saveCardImage(context.getApplicationContext(), null, cardID, imageLocationType); - } catch (FileNotFoundException ignored) { + for (ImageLocationType imageLocationType : ImageLocationType.values()) { + try { + Utils.saveCardImage(context.getApplicationContext(), null, cardID, imageLocationType); + } catch (FileNotFoundException ignored) { + } } - } - cursor.moveToNext(); - } + cursor.moveToNext(); + } - // Make sure DB is empty - database.execSQL("delete from " + DBHelper.LoyaltyCardDbIds.TABLE); - database.execSQL("delete from " + DBHelper.LoyaltyCardDbGroups.TABLE); - database.execSQL("delete from " + DBHelper.LoyaltyCardDbIdsGroups.TABLE); + // Make sure DB is empty + database.execSQL("delete from " + DBHelper.LoyaltyCardDbIds.TABLE); + database.execSQL("delete from " + DBHelper.LoyaltyCardDbGroups.TABLE); + database.execSQL("delete from " + DBHelper.LoyaltyCardDbIdsGroups.TABLE); - return db; + return db; + } } /**