Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4219e5c2 authored by Lee Shombert's avatar Lee Shombert Committed by Android (Google) Code Review
Browse files

Merge "Improve error reporting for open-database failures" into main

parents f86103c4 1611e110
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -239,8 +239,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
                    NoPreloadHolder.DEBUG_SQL_STATEMENTS, NoPreloadHolder.DEBUG_SQL_TIME,
                    mConfiguration.lookasideSlotSize, mConfiguration.lookasideSlotCount);
        } catch (SQLiteCantOpenDatabaseException e) {
            final StringBuilder message = new StringBuilder("Cannot open database '")
                    .append(file).append('\'')
            final StringBuilder message = new StringBuilder(e.getMessage())
                    .append(" '").append(file).append("'")
                    .append(" with flags 0x")
                    .append(Integer.toHexString(mConfiguration.openFlags));

@@ -265,12 +265,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
                    message.append(": File ").append(path).append(" is not readable");
                } else if (Files.isDirectory(path)) {
                    message.append(": Path ").append(path).append(" is a directory");
                } else {
                    message.append(": Unable to deduct failure reason");
                }
            } catch (Throwable th) {
                message.append(": Unable to deduct failure reason"
                        + " because filesystem couldn't be examined: ").append(th.getMessage());
                // Ignore any exceptions generated whilst attempting to create extended diagnostic
                // messages.
            }
            throw new SQLiteCantOpenDatabaseException(message.toString(), e);
        } finally {
+6 −1
Original line number Diff line number Diff line
@@ -134,10 +134,15 @@ static jlong nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFla
    String8 label(labelChars);
    env->ReleaseStringUTFChars(labelStr, labelChars);

    errno = 0;
    sqlite3* db;
    int err = sqlite3_open_v2(path.c_str(), &db, sqliteFlags, NULL);
    if (err != SQLITE_OK) {
        throw_sqlite3_exception_errcode(env, err, "Could not open database");
        if (errno == 0) {
            throw_sqlite3_exception(env, db, "could not open database");
        } else {
            throw_sqlite3_exception(env, db, strerror(errno));
        }
        return 0;
    }

+99 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * 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 android.database.sqlite;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.content.Context;
import android.database.sqlite.SQLiteCantOpenDatabaseException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.OpenParams;
import android.util.Log;

import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class SQLiteCantOpenDatabaseExceptionTest {
    private static final String TAG = "SQLiteCantOpenDatabaseExceptionTest";

    private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();

    private File getDatabaseFile(String name) {
        mContext.deleteDatabase(name);

        // getDatabasePath() doesn't like a filename with a / in it, so we can't use it directly.
        return new File(mContext.getDatabasePath("a").getParentFile(), name);
    }

    private void callWithExpectedMessage(File file, String expectedMessagePattern) {
        try {
            SQLiteDatabase.openDatabase(file, new OpenParams.Builder().build());
            fail("SQLiteCantOpenDatabaseException was not thrown");
        } catch (SQLiteCantOpenDatabaseException e) {
            Log.i(TAG, "Caught expected exception: " + e.getMessage());
            assertTrue(e.getMessage().matches(expectedMessagePattern));
        }
    }

    /** DB's directory doesn't exist. */
    @Test
    public void testDirectoryDoesNotExist() {
        final File file = getDatabaseFile("nonexisitentdir/mydb.db");

        callWithExpectedMessage(file, ".*: Directory .* doesn't exist");
    }

    /** File doesn't exist */
    @Test
    public void testFileDoesNotExist() {
        final File file = getDatabaseFile("mydb.db");

        callWithExpectedMessage(file, ".*: File .* doesn't exist");
    }

    /** File exists, but not readable. */
    @Test
    public void testFileNotReadable() {
        final File file = getDatabaseFile("mydb.db");

        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(file, null);
        db.close();

        file.setReadable(false);

        callWithExpectedMessage(file, ".*: File .* not readable");
    }

    /** Directory with the given name exists already. */
    @Test
    public void testPathIsADirectory() {
        final File file = getDatabaseFile("mydb.db");

        file.mkdirs();

        callWithExpectedMessage(file, ".*: Path .* is a directory");
    }
}
+0 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.util.Log;

import androidx.test.filters.SmallTest;