Convert BaseAndroidTest

pull/716/head
Quentin Hibon 5 years ago
parent df755d30ee
commit 21fa636e0c

@ -1,289 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits;
import android.appwidget.*;
import android.content.*;
import android.content.res.*;
import android.os.*;
import android.util.*;
import androidx.annotation.*;
import androidx.test.filters.*;
import androidx.test.platform.app.*;
import androidx.test.uiautomator.*;
import junit.framework.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.tasks.*;
import org.isoron.uhabits.core.utils.*;
import org.isoron.uhabits.inject.*;
import org.isoron.uhabits.utils.*;
import org.junit.*;
import java.io.*;
import java.time.*;
import java.util.*;
import java.util.concurrent.*;
import static androidx.test.platform.app.InstrumentationRegistry.*;
import static androidx.test.uiautomator.UiDevice.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
@MediumTest
public class BaseAndroidTest extends TestCase
{
// 8:00am, January 25th, 2015 (UTC)
public static final long FIXED_LOCAL_TIME = 1422172800000L;
protected Context testContext;
protected Context targetContext;
protected Preferences prefs;
protected HabitList habitList;
protected TaskRunner taskRunner;
protected HabitFixtures fixtures;
protected CountDownLatch latch;
protected HabitsApplicationTestComponent appComponent;
protected ModelFactory modelFactory;
protected HabitsActivityTestComponent component;
private boolean isDone = false;
private UiDevice device;
@Override
@Before
public void setUp()
{
if (Looper.myLooper() == null) Looper.prepare();
device = getInstance(getInstrumentation());
targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
testContext = InstrumentationRegistry.getInstrumentation().getContext();
DateUtils.setFixedLocalTime(FIXED_LOCAL_TIME);
DateUtils.setStartDayOffset(0, 0);
setResolution(2.0f);
setTheme(R.style.AppBaseTheme);
setLocale("en", "US");
latch = new CountDownLatch(1);
Context context = targetContext.getApplicationContext();
File dbFile = DatabaseUtils.getDatabaseFile(context);
appComponent = DaggerHabitsApplicationTestComponent
.builder()
.appContextModule(new AppContextModule(context))
.habitsModule(new HabitsModule(dbFile))
.build();
HabitsApplication.Companion.setComponent(appComponent);
prefs = appComponent.getPreferences();
habitList = appComponent.getHabitList();
taskRunner = appComponent.getTaskRunner();
modelFactory = appComponent.getModelFactory();
prefs.clear();
fixtures = new HabitFixtures(modelFactory, habitList);
fixtures.purgeHabits(appComponent.getHabitList());
Habit habit = fixtures.createEmptyHabit();
component = DaggerHabitsActivityTestComponent
.builder()
.activityContextModule(new ActivityContextModule(targetContext))
.habitsApplicationComponent(appComponent)
.build();
}
protected void assertWidgetProviderIsInstalled(Class componentClass)
{
ComponentName provider =
new ComponentName(targetContext, componentClass);
AppWidgetManager manager = AppWidgetManager.getInstance(targetContext);
List<ComponentName> installedProviders = new LinkedList<>();
for (AppWidgetProviderInfo info : manager.getInstalledProviders())
installedProviders.add(info.provider);
assertThat(installedProviders, hasItems(provider));
}
protected void awaitLatch() throws InterruptedException
{
assertTrue(latch.await(1, TimeUnit.SECONDS));
}
protected void setLocale(@NonNull String language, @NonNull String country)
{
Locale locale = new Locale(language, country);
Locale.setDefault(locale);
Resources res = targetContext.getResources();
Configuration config = res.getConfiguration();
config.setLocale(locale);
}
protected void setResolution(float r)
{
DisplayMetrics dm = targetContext.getResources().getDisplayMetrics();
dm.density = r;
dm.scaledDensity = r;
InterfaceUtils.setFixedResolution(r);
}
protected void runConcurrently(Runnable... runnableList) throws Exception
{
isDone = false;
ExecutorService executor = Executors.newFixedThreadPool(100);
List<Future> futures = new LinkedList<>();
for (Runnable r : runnableList)
futures.add(executor.submit(() ->
{
while (!isDone) r.run();
return null;
}));
Thread.sleep(3000);
isDone = true;
executor.shutdown();
for(Future f : futures) f.get();
while (!executor.isTerminated()) Thread.sleep(50);
}
protected void setTheme(@StyleRes int themeId)
{
targetContext.setTheme(themeId);
StyledResources.setFixedTheme(themeId);
}
protected void sleep(int time)
{
try
{
Thread.sleep(time);
}
catch (InterruptedException e)
{
fail();
}
}
public long timestamp(int year, int month, int day)
{
GregorianCalendar cal = DateUtils.getStartOfTodayCalendar();
cal.set(year, month, day);
return cal.getTimeInMillis();
}
protected void startTracing()
{
File dir = new AndroidDirFinder(targetContext).getFilesDir("Profile");
assertNotNull(dir);
String tracePath = dir.getAbsolutePath() + "/performance.trace";
Log.d("PerformanceTest", String.format("Saving trace file to %s", tracePath));
Debug.startMethodTracingSampling(tracePath, 0, 1000);
}
protected void stopTracing()
{
Debug.stopMethodTracing();
}
protected Timestamp day(int offset)
{
return DateUtils.getToday().minus(offset);
}
public void setSystemTime(String tz,
int year,
int javaMonth,
int day,
int hourOfDay,
int minute) throws Exception
{
GregorianCalendar cal = new GregorianCalendar();
cal.set(Calendar.SECOND, 0);
cal.set(year, javaMonth, day, hourOfDay, minute);
cal.setTimeZone(TimeZone.getTimeZone(tz));
setSystemTime(cal);
}
private void setSystemTime(GregorianCalendar cal) throws Exception
{
ZoneId tz = cal.getTimeZone().toZoneId();
// Set time zone (temporary)
String command = String.format("service call alarm 3 s16 %s", tz);
device.executeShellCommand(command);
// Set time zone (permanent)
command = String.format("setprop persist.sys.timezone %s", tz);
device.executeShellCommand(command);
// Set time
String date = String.format("%02d%02d%02d%02d%02d.%02d",
cal.get(Calendar.MONTH) + 1,
cal.get(Calendar.DAY_OF_MONTH),
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
cal.get(Calendar.YEAR),
cal.get(Calendar.SECOND));
// Set time (method 1)
// Run twice to override daylight saving time
device.executeShellCommand("date " + date);
device.executeShellCommand("date " + date);
// Set time (method 2)
// Run in addition to the method above because one of these mail fail, depending
// on the Android API version.
command = String.format("date -u @%d", cal.getTimeInMillis() / 1000);
device.executeShellCommand(command);
// Wait for system events to settle
Thread.sleep(1000);
}
private GregorianCalendar savedCalendar = null;
public void saveSystemTime()
{
savedCalendar = new GregorianCalendar();
}
public void restoreSystemTime() throws Exception
{
if (savedCalendar == null) throw new NullPointerException();
setSystemTime(savedCalendar);
}
}

@ -0,0 +1,219 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.os.Looper
import androidx.annotation.StyleRes
import androidx.test.filters.MediumTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import junit.framework.TestCase
import org.hamcrest.CoreMatchers
import org.hamcrest.MatcherAssert
import org.isoron.uhabits.core.models.HabitList
import org.isoron.uhabits.core.models.ModelFactory
import org.isoron.uhabits.core.models.Timestamp
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.tasks.TaskRunner
import org.isoron.uhabits.core.utils.DateUtils.Companion.getToday
import org.isoron.uhabits.core.utils.DateUtils.Companion.setFixedLocalTime
import org.isoron.uhabits.core.utils.DateUtils.Companion.setStartDayOffset
import org.isoron.uhabits.inject.ActivityContextModule
import org.isoron.uhabits.inject.AppContextModule
import org.isoron.uhabits.inject.HabitsModule
import org.isoron.uhabits.utils.DatabaseUtils.getDatabaseFile
import org.isoron.uhabits.utils.InterfaceUtils.setFixedResolution
import org.isoron.uhabits.utils.StyledResources.Companion.setFixedTheme
import org.isoron.uhabits.widgets.BaseWidgetProvider
import org.junit.Before
import java.util.Calendar
import java.util.GregorianCalendar
import java.util.LinkedList
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.CountDownLatch
@MediumTest
abstract class BaseAndroidTest : TestCase() {
@JvmField
protected var testContext: Context = InstrumentationRegistry.getInstrumentation().context
@JvmField
protected var targetContext: Context =
InstrumentationRegistry.getInstrumentation().targetContext
protected lateinit var prefs: Preferences
protected lateinit var habitList: HabitList
protected lateinit var taskRunner: TaskRunner
protected lateinit var fixtures: HabitFixtures
protected lateinit var latch: CountDownLatch
protected lateinit var appComponent: HabitsApplicationTestComponent
protected lateinit var modelFactory: ModelFactory
protected lateinit var component: HabitsActivityTestComponent
private lateinit var device: UiDevice
@Before
public override fun setUp() {
if (Looper.myLooper() == null) Looper.prepare()
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
setFixedLocalTime(FIXED_LOCAL_TIME)
setStartDayOffset(0, 0)
setResolution(2.0f)
setTheme(R.style.AppBaseTheme)
setLocale("en", "US")
latch = CountDownLatch(1)
val context = targetContext.applicationContext
val dbFile = getDatabaseFile(context)
appComponent = DaggerHabitsApplicationTestComponent
.builder()
.appContextModule(AppContextModule(context))
.habitsModule(HabitsModule(dbFile))
.build()
HabitsApplication.component = appComponent
prefs = appComponent.preferences
habitList = appComponent.habitList
taskRunner = appComponent.taskRunner
modelFactory = appComponent.modelFactory
prefs.clear()
fixtures = HabitFixtures(modelFactory, habitList)
fixtures.purgeHabits(appComponent.habitList)
fixtures.createEmptyHabit()
component = DaggerHabitsActivityTestComponent
.builder()
.activityContextModule(ActivityContextModule(targetContext))
.habitsApplicationComponent(appComponent)
.build()
}
protected fun assertWidgetProviderIsInstalled(componentClass: Class<out BaseWidgetProvider?>?) {
val provider = ComponentName(targetContext, componentClass!!)
val manager = AppWidgetManager.getInstance(targetContext)
val installedProviders: MutableList<ComponentName> = LinkedList()
for (info in manager.installedProviders) installedProviders.add(info.provider)
MatcherAssert.assertThat<List<ComponentName>>(
installedProviders,
CoreMatchers.hasItems(provider)
)
}
protected fun setLocale(language: String, country: String) {
val locale = Locale(language, country)
Locale.setDefault(locale)
val res = targetContext.resources
val config = res.configuration
config.setLocale(locale)
}
protected fun setResolution(r: Float) {
val dm = targetContext.resources.displayMetrics
dm.density = r
dm.scaledDensity = r
setFixedResolution(r)
}
protected fun setTheme(@StyleRes themeId: Int) {
targetContext.setTheme(themeId)
setFixedTheme(themeId)
}
protected fun sleep(time: Int) {
try {
Thread.sleep(time.toLong())
} catch (e: InterruptedException) {
fail()
}
}
protected fun day(offset: Int): Timestamp {
return getToday().minus(offset)
}
@Throws(Exception::class)
fun setSystemTime(
tz: String?,
year: Int,
javaMonth: Int,
day: Int,
hourOfDay: Int,
minute: Int
) {
val cal = GregorianCalendar()
cal[Calendar.SECOND] = 0
cal[year, javaMonth, day, hourOfDay] = minute
cal.timeZone = TimeZone.getTimeZone(tz)
setSystemTime(cal)
}
@Throws(Exception::class)
private fun setSystemTime(cal: GregorianCalendar) {
val tz = cal.timeZone.toZoneId()
// Set time zone (temporary)
var command = String.format("service call alarm 3 s16 %s", tz)
device.executeShellCommand(command)
// Set time zone (permanent)
command = String.format("setprop persist.sys.timezone %s", tz)
device.executeShellCommand(command)
// Set time
val date = String.format(
"%02d%02d%02d%02d%02d.%02d",
cal[Calendar.MONTH] + 1,
cal[Calendar.DAY_OF_MONTH],
cal[Calendar.HOUR_OF_DAY],
cal[Calendar.MINUTE],
cal[Calendar.YEAR],
cal[Calendar.SECOND]
)
// Set time (method 1)
// Run twice to override daylight saving time
device.executeShellCommand("date $date")
device.executeShellCommand("date $date")
// Set time (method 2)
// Run in addition to the method above because one of these mail fail, depending
// on the Android API version.
command = String.format("date -u @%d", cal.timeInMillis / 1000)
device.executeShellCommand(command)
// Wait for system events to settle
Thread.sleep(1000)
}
private var savedCalendar: GregorianCalendar? = null
fun saveSystemTime() {
savedCalendar = GregorianCalendar()
}
@Throws(Exception::class)
fun restoreSystemTime() {
if (savedCalendar == null) throw NullPointerException()
setSystemTime(savedCalendar!!)
}
companion object {
// 8:00am, January 25th, 2015 (UTC)
const val FIXED_LOCAL_TIME = 1422172800000L
}
}
Loading…
Cancel
Save