/*
 * Copyright (C) 2017 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;

import static org.junit.Assert.assertTrue;

import android.content.Context;
import android.database.sqlite.SQLiteCursor;
import android.database.sqlite.SQLiteDatabase;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class CursorWindowPerfTest {
    @Rule
    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();

    private static Context getContext() {
        return InstrumentationRegistry.getTargetContext();
    }

    private static final String DB_NAME = CursorWindowPerfTest.class.toString();

    private static SQLiteDatabase sDatabase;

    @BeforeClass
    public static void setup() {
        getContext().deleteDatabase(DB_NAME);
        sDatabase = getContext().openOrCreateDatabase(DB_NAME, Context.MODE_PRIVATE, null);

        for (TableHelper helper : TableHelper.TABLE_HELPERS) {
            sDatabase.execSQL(helper.createSql());
            final String insert = helper.insertSql();

            // this test only needs 1 row
            sDatabase.execSQL(insert, helper.createItem(0));
        }

    }

    @AfterClass
    public static void teardown() {
        getContext().deleteDatabase(DB_NAME);
    }

    @Test
    public void loadInt() {
        loadRowFromCursorWindow(TableHelper.INT_1, false);
    }

    @Test
    public void loadInt_doubleRef() {
        loadRowFromCursorWindow(TableHelper.INT_1, true);
    }

    @Test
    public void load10Ints() {
        loadRowFromCursorWindow(TableHelper.INT_10, false);
    }

    @Test
    public void loadUser() {
        loadRowFromCursorWindow(TableHelper.USER, false);
    }

    private void loadRowFromCursorWindow(TableHelper helper, boolean doubleRef) {
        try (Cursor cursor = sDatabase.rawQuery(helper.readSql(), new String[0])) {
            TableHelper.CursorReader reader = helper.createReader(cursor);

            SQLiteCursor sqLiteCursor = (SQLiteCursor) cursor;

            sqLiteCursor.getCount(); // load one window
            CursorWindow window = sqLiteCursor.getWindow();
            assertTrue("must have enough rows", window.getNumRows() >= 1);
            int start = window.getStartPosition();

            BenchmarkState state = mPerfStatusReporter.getBenchmarkState();

            if (!doubleRef) {
                // normal access
                while (state.keepRunning()) {
                    cursor.moveToPosition(start);
                    reader.read();
                }
            } else {
                // add an extra window acquire/release to measure overhead
                while (state.keepRunning()) {
                    cursor.moveToPosition(start);
                    try {
                        window.acquireReference();
                        reader.read();
                    } finally {
                        window.releaseReference();
                    }
                }
            }
        }
    }
}
