// Copyright 2015 The Project Buendia Authors
//
// 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 distrib-
// uted 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
// specific language governing permissions and limitations under the License.
package org.projectbuendia.client.ui.sync;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.preference.PreferenceManager;
import android.support.test.espresso.Espresso;
import net.sqlcipher.database.SQLiteException;
import org.projectbuendia.client.App;
import org.projectbuendia.client.events.sync.SyncFailedEvent;
import org.projectbuendia.client.sync.Database;
import org.projectbuendia.client.ui.FunctionalTestCase;
import org.projectbuendia.client.utils.Logger;
import java.sql.SQLException;
import java.util.UUID;
/**
* A {@link FunctionalTestCase} that clears the application database as part of set up, allowing for
* sync behavior to be tested more easily. This class does NOT currently clear ODK forms, which are
* stored separately as flat files.
* <p/>
* <p>WARNING: Syncing may require the transfer of large quantities of data, so {@link SyncTestCase}
* tests will almost always be very large tests.
*/
public class SyncTestCase extends FunctionalTestCase {
private static final Logger LOG = Logger.create();
// The database may still be holding a lock after a test, so clearing the database may not
// be successful right away.
private static final int MAX_DATABASE_CLEAR_RETRIES = 10;
@Override public void setUp() throws Exception {
// Clearing the database can be flaky if previous tests are temporarily holding a DB lock,
// so try a few times before failing.
boolean cleared = false;
int retriesRemaining = MAX_DATABASE_CLEAR_RETRIES;
while (!cleared && retriesRemaining > 0) {
try {
clearDatabase();
clearPreferences();
cleared = true;
} catch (SQLiteException e) {
Thread.sleep(500);
retriesRemaining--;
}
}
super.setUp();
}
/** Clears all contents of the database (note: this does not include ODK forms or instances). */
public void clearDatabase() throws SQLException {
Database db = new Database(App.getInstance().getApplicationContext());
db.onUpgrade(db.getWritableDatabase(), 0, 1);
db.close();
}
/** Clears all shared preferences of the application. */
public void clearPreferences() {
PreferenceManager.getDefaultSharedPreferences(App.getInstance()).edit().clear().commit();
}
/** Cleans up post-test wifi state. Won't work during tearDown(). */
public void cleanupWifi() {
setWifiEnabled(true);
// Wait until wifi connection has been re-established.
Espresso.registerIdlingResources(new WifiStateIdlingResource());
}
/** Turns wifi on or off. */
protected void setWifiEnabled(boolean enabled) {
LOG.i("Setting wifi state: %b", enabled);
WifiManager wifiManager =
(WifiManager) App.getInstance().getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(enabled);
}
/** Delays all ViewActions until sync has failed once. */
protected void waitForSyncFailure() {
EventBusIdlingResource<SyncFailedEvent> syncFailedEventIdlingResource =
new EventBusIdlingResource<>(UUID.randomUUID().toString(), mEventBus);
Espresso.registerIdlingResources(syncFailedEventIdlingResource);
}
class WifiDisabler implements AutoCloseable {
public WifiDisabler() {
setWifiEnabled(false);
}
public void close() {
cleanupWifi();
}
}
}