From 6734bfeaa4791d69cb97b30de06806e338f59944 Mon Sep 17 00:00:00 2001 From: serso Date: Wed, 13 Jan 2016 23:09:07 +0100 Subject: [PATCH] History tests --- .../org/solovyev/android/calculator/App.java | 12 -- .../android/calculator/AppComponent.java | 5 +- .../android/calculator/AppModule.java | 20 +- .../calculator/CalculatorEventType.java | 13 -- .../history/BaseHistoryFragment.java | 85 +++----- .../android/calculator/history/History.java | 186 ++++++++---------- .../history/RecentHistoryFragment.java | 8 +- .../history/SavedHistoryFragment.java | 8 +- .../android/CalculatorTestRunner.java | 5 +- .../calculator/AbstractCalculatorTest.java | 5 +- .../calculator/CalculatorTestUtils.java | 25 +-- .../android/calculator/EditorTest.java | 4 +- .../calculator/history/HistoryTest.java | 177 +++++++++++++---- .../calculator/history/HistoryUtilsTest.java | 79 -------- 14 files changed, 295 insertions(+), 337 deletions(-) diff --git a/app/src/main/java/org/solovyev/android/calculator/App.java b/app/src/main/java/org/solovyev/android/calculator/App.java index 2bf2ad1d..99b2a7fd 100644 --- a/app/src/main/java/org/solovyev/android/calculator/App.java +++ b/app/src/main/java/org/solovyev/android/calculator/App.java @@ -95,7 +95,6 @@ public final class App { private static volatile Application application; @Nonnull private static Executor uiThreadExecutor; - private static volatile boolean initialized; @Nonnull private static SharedPreferences preferences; @Nonnull @@ -132,9 +131,6 @@ public final class App { public static void init(@Nonnull CalculatorApplication application, @Nonnull Languages languages) { - if (initialized) { - throw new IllegalStateException("Already initialized!"); - } App.application = application; App.preferences = PreferenceManager.getDefaultSharedPreferences(application); App.uiThreadExecutor = application.uiThread; @@ -163,14 +159,6 @@ public final class App { App.editor = application.editor; App.display = application.display; App.bus = application.bus; - - App.initialized = true; - } - - private static void checkInit() { - if (!initialized) { - throw new IllegalStateException("App should be initialized!"); - } } /** diff --git a/app/src/main/java/org/solovyev/android/calculator/AppComponent.java b/app/src/main/java/org/solovyev/android/calculator/AppComponent.java index f461ee54..24a36253 100644 --- a/app/src/main/java/org/solovyev/android/calculator/AppComponent.java +++ b/app/src/main/java/org/solovyev/android/calculator/AppComponent.java @@ -1,11 +1,11 @@ package org.solovyev.android.calculator; +import dagger.Component; +import org.solovyev.android.calculator.history.BaseHistoryFragment; import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService; import javax.inject.Singleton; -import dagger.Component; - @Singleton @Component(modules = AppModule.class) public interface AppComponent { @@ -13,4 +13,5 @@ public interface AppComponent { void inject(CalculatorEditorFragment fragment); void inject(BaseUi ui); void inject(CalculatorOnscreenService service); + void inject(BaseHistoryFragment fragment); } diff --git a/app/src/main/java/org/solovyev/android/calculator/AppModule.java b/app/src/main/java/org/solovyev/android/calculator/AppModule.java index 788ac088..d29704cc 100644 --- a/app/src/main/java/org/solovyev/android/calculator/AppModule.java +++ b/app/src/main/java/org/solovyev/android/calculator/AppModule.java @@ -6,21 +6,17 @@ import android.os.Handler; import android.os.Looper; import android.preference.PreferenceManager; import android.support.annotation.NonNull; - import com.squareup.otto.Bus; - +import dagger.Module; +import dagger.Provides; import org.solovyev.android.UiThreadExecutor; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; - import javax.annotation.Nonnull; import javax.inject.Named; import javax.inject.Singleton; - -import dagger.Module; -import dagger.Provides; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; @Module public class AppModule { @@ -43,6 +39,12 @@ public class AppModule { return new Handler(Looper.getMainLooper()); } + @Provides + @Singleton + Application provideApplication() { + return application; + } + @Provides @Singleton Bus provideBus(Handler handler) { diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java index 0aac8968..048734c0 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java +++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java @@ -80,19 +80,6 @@ public enum CalculatorEventType { engine_preferences_changed, - /* - ********************************************************************** - * - * HISTORY - * - ********************************************************************** - */ - - // @Nonnull CalculatorHistoryState - history_state_added, - - clear_history_requested, - /* ********************************************************************** * diff --git a/app/src/main/java/org/solovyev/android/calculator/history/BaseHistoryFragment.java b/app/src/main/java/org/solovyev/android/calculator/history/BaseHistoryFragment.java index 786e3a78..f11bcdff 100644 --- a/app/src/main/java/org/solovyev/android/calculator/history/BaseHistoryFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/history/BaseHistoryFragment.java @@ -30,43 +30,24 @@ import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.ListFragment; import android.text.ClipboardManager; -import android.view.ContextMenu; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.ListView; -import android.widget.TextView; -import android.widget.Toast; - +import android.view.*; +import android.widget.*; import com.melnykov.fab.FloatingActionButton; - -import org.solovyev.android.calculator.App; -import org.solovyev.android.calculator.CalculatorActivity; -import org.solovyev.android.calculator.CalculatorEventData; -import org.solovyev.android.calculator.CalculatorEventListener; -import org.solovyev.android.calculator.CalculatorEventType; -import org.solovyev.android.calculator.CalculatorFragmentType; -import org.solovyev.android.calculator.FragmentUi; -import org.solovyev.android.calculator.Locator; -import org.solovyev.android.calculator.R; +import com.squareup.otto.Bus; +import com.squareup.otto.Subscribe; +import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.common.text.Strings; -import java.util.ArrayList; -import java.util.List; - import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; import static android.view.Menu.NONE; -import static org.solovyev.android.calculator.CalculatorEventType.clear_history_requested; -public abstract class BaseHistoryFragment extends ListFragment implements CalculatorEventListener { +public abstract class BaseHistoryFragment extends ListFragment { @Nonnull private final DialogInterface.OnClickListener clearDialogListener = new DialogInterface.OnClickListener() { @@ -79,14 +60,16 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul } } }; + @Inject + History history; + @Inject + Bus bus; @Nonnull private HistoryArrayAdapter adapter; @Nonnull private FragmentUi ui; @Nullable private AlertDialog clearDialog; - @Inject - History history; protected BaseHistoryFragment(@Nonnull CalculatorFragmentType fragmentType) { ui = new FragmentUi(fragmentType.getDefaultLayoutId(), fragmentType.getDefaultTitleResId(), false); @@ -114,6 +97,8 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + ((CalculatorApplication) getActivity().getApplication()).getComponent().inject(this); + bus.register(this); ui.onCreate(this); } @@ -139,7 +124,12 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Locator.getInstance().getCalculator().fireCalculatorEvent(clear_history_requested, null); + clearDialog = new AlertDialog.Builder(getActivity()).setTitle(R.string.cpp_clear_history_title) + .setMessage(R.string.cpp_clear_history_message) + .setPositiveButton(R.string.cpp_clear_history, clearDialogListener) + .setNegativeButton(R.string.c_cancel, clearDialogListener) + .create(); + clearDialog.show(); } }); @@ -159,7 +149,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul public void onResume() { super.onResume(); - this.ui.onResume(this); + ui.onResume(this); updateAdapter(); } @@ -285,6 +275,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul @Override public void onDestroy() { + bus.unregister(this); if (clearDialog != null) { clearDialog.dismiss(); clearDialog = null; @@ -323,31 +314,13 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul return adapter; } - @Override - public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { - switch (calculatorEventType) { - case history_state_added: - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - updateAdapter(); - } - }); - break; - case clear_history_requested: - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - clearDialog = new AlertDialog.Builder(getActivity()).setTitle(R.string.cpp_clear_history_title) - .setMessage(R.string.cpp_clear_history_message) - .setPositiveButton(R.string.cpp_clear_history, clearDialogListener) - .setNegativeButton(R.string.c_cancel, clearDialogListener) - .create(); - clearDialog.show(); - } - }); - break; + @Subscribe + void onHistoryChanged(@Nonnull History.ChangedEvent e) { + if (e.recent != isRecentHistory()) { + return; } - + updateAdapter(); } + + protected abstract boolean isRecentHistory(); } diff --git a/app/src/main/java/org/solovyev/android/calculator/history/History.java b/app/src/main/java/org/solovyev/android/calculator/history/History.java index 05250be4..34771bea 100644 --- a/app/src/main/java/org/solovyev/android/calculator/history/History.java +++ b/app/src/main/java/org/solovyev/android/calculator/history/History.java @@ -22,30 +22,24 @@ package org.solovyev.android.calculator.history; +import android.app.Application; import android.content.SharedPreferences; import android.os.Handler; import android.support.annotation.NonNull; -import android.text.TextUtils; - import com.google.common.base.Strings; import com.squareup.otto.Bus; import com.squareup.otto.Subscribe; - import org.json.JSONArray; import org.json.JSONException; import org.solovyev.android.Check; -import org.solovyev.android.calculator.App; -import org.solovyev.android.calculator.AppModule; -import org.solovyev.android.calculator.CalculatorEventType; -import org.solovyev.android.calculator.Display; -import org.solovyev.android.calculator.DisplayState; -import org.solovyev.android.calculator.Editor; -import org.solovyev.android.calculator.EditorState; -import org.solovyev.android.calculator.Locator; -import org.solovyev.android.calculator.model.AndroidCalculatorEngine; +import org.solovyev.android.calculator.*; import org.solovyev.android.io.FileLoader; import org.solovyev.android.io.FileSaver; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Named; import java.io.File; import java.util.ArrayList; import java.util.Collections; @@ -53,16 +47,13 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.Executor; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.inject.Inject; -import javax.inject.Named; - -import static java.lang.Character.isDigit; +import static android.text.TextUtils.isEmpty; public class History { public static final String TAG = App.subTag("History"); + private static final ChangedEvent CHANGED_EVENT_RECENT = new ChangedEvent(true); + private static final ChangedEvent CHANGED_EVENT_SAVED = new ChangedEvent(false); @NonNull private final Runnable writeRecent = new WriteTask(true); @NonNull @@ -71,17 +62,22 @@ public class History { private final RecentHistory recent = new RecentHistory(); @Nonnull private final List saved = new ArrayList<>(); + @Nonnull + private final Bus bus; @Inject Handler handler; @Inject SharedPreferences preferences; - @Nullable - private EditorState lastEditorState; + @Inject + Editor editor; + @Inject + Application application; private boolean initialized; @Inject - public History(Bus bus, @Named(AppModule.THREAD_INIT) Executor initThread) { - bus.register(this); + public History(@NonNull Bus bus, @Nonnull @Named(AppModule.THREAD_INIT) Executor initThread) { + this.bus = bus; + this.bus.register(this); initThread.execute(new Runnable() { @Override public void run() { @@ -90,23 +86,6 @@ public class History { }); } - private void migrateOldHistory() { - try { - final String xml = preferences.getString("org.solovyev.android.calculator.CalculatorModel_history", null); - if (TextUtils.isEmpty(xml)) { - return; - } - final List states = convertOldHistory(xml); - if (states == null) { - return; - } - final JSONArray json = RecentHistory.toJson(states); - FileSaver.save(getSavedHistoryFile(), json.toString()); - } catch (Exception e) { - Locator.getInstance().getLogger().error(TAG, e.getMessage(), e); - } - } - @Nullable static List convertOldHistory(@NonNull String xml) { final OldHistory history = OldHistory.fromXml(xml); @@ -129,13 +108,13 @@ public class History { } @NonNull - private static File getSavedHistoryFile() { - return new File(App.getApplication().getFilesDir(), "history-saved.json"); + private File getSavedHistoryFile() { + return new File(application.getFilesDir(), "history-saved.json"); } @NonNull - private static File getRecentHistoryFile() { - return new File(App.getApplication().getFilesDir(), "history-recent.json"); + private File getRecentHistoryFile() { + return new File(application.getFilesDir(), "history-recent.json"); } @Nonnull @@ -144,7 +123,7 @@ public class History { return Collections.emptyList(); } final CharSequence json = FileLoader.load(file); - if (TextUtils.isEmpty(json)) { + if (isEmpty(json)) { return Collections.emptyList(); } try { @@ -155,6 +134,44 @@ public class History { return Collections.emptyList(); } + private static boolean isIntermediate(@Nonnull String olderText, + @Nonnull String newerText) { + if (isEmpty(olderText)) { + return true; + } + if (isEmpty(newerText)) { + return false; + } + + final int diff = newerText.length() - olderText.length(); + if (diff >= 1) { + return newerText.startsWith(olderText); + } else if (diff <= 1) { + return olderText.startsWith(newerText); + } else if (diff == 0) { + return olderText.equals(newerText); + } + + return false; + } + + private void migrateOldHistory() { + try { + final String xml = preferences.getString("org.solovyev.android.calculator.CalculatorModel_history", null); + if (isEmpty(xml)) { + return; + } + final List states = convertOldHistory(xml); + if (states == null) { + return; + } + final JSONArray json = RecentHistory.toJson(states); + FileSaver.save(getSavedHistoryFile(), json.toString()); + } catch (Exception e) { + Locator.getInstance().getLogger().error(TAG, e.getMessage(), e); + } + } + private void init() { Check.isNotMainThread(); migrateOldHistory(); @@ -175,7 +192,6 @@ public class History { public void addRecent(@Nonnull HistoryState state) { Check.isMainThread(); recent.add(state); - Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, state); onRecentChanged(); } @@ -188,11 +204,13 @@ public class History { private void onRecentChanged() { handler.removeCallbacks(writeRecent); handler.postDelayed(writeRecent, 500); + bus.post(CHANGED_EVENT_RECENT); } private void onSavedChanged() { handler.removeCallbacks(writeSaved); handler.postDelayed(writeSaved, 500); + bus.post(CHANGED_EVENT_SAVED); } @Nonnull @@ -201,8 +219,6 @@ public class History { final List result = new LinkedList<>(); - final String groupingSeparator = AndroidCalculatorEngine.Preferences.groupingSeparator.getPreference(App.getPreferences()); - final List states = recent.asList(); final int statesCount = states.size(); for (int i = 1; i < statesCount; i++) { @@ -210,13 +226,14 @@ public class History { final HistoryState newerState = states.get(i); final String olderText = olderState.editor.getTextString(); final String newerText = newerState.editor.getTextString(); - if (!isIntermediate(olderText, newerText, groupingSeparator)) { + if (!isIntermediate(olderText, newerText)) { result.add(0, olderState); } } if (statesCount > 0) { + // try add last state if not empty final HistoryState state = states.get(statesCount - 1); - if (!TextUtils.isEmpty(state.editor.getTextString())) { + if (!isEmpty(state.editor.getTextString())) { result.add(0, state); } } @@ -229,53 +246,6 @@ public class History { return new ArrayList<>(saved); } - private static boolean isIntermediate(@Nonnull String olderText, - @Nonnull String newerText, - @NonNull String groupingSeparator) { - if (TextUtils.isEmpty(olderText)) { - return true; - } - if (TextUtils.isEmpty(newerText)) { - return false; - } - olderText = trimGroupingSeparators(olderText, groupingSeparator); - newerText = trimGroupingSeparators(newerText, groupingSeparator); - - final int diff = newerText.length() - olderText.length(); - if (diff >= 1) { - return newerText.startsWith(olderText); - } else if (diff <= 1) { - return olderText.startsWith(newerText); - } else if (diff == 0) { - return olderText.equals(newerText); - } - - return false; - } - - @NonNull - private static String trimGroupingSeparators(@NonNull String text, @NonNull String groupingSeparator) { - if (TextUtils.isEmpty(groupingSeparator)) { - return text; - } - Check.isTrue(groupingSeparator.length() == 1); - final StringBuilder sb = new StringBuilder(text.length()); - for (int i = 0; i < text.length(); i++) { - if (i == 0 || i == text.length() - 1) { - // grouping separator can't be the first and the last character - sb.append(text.charAt(i)); - continue; - } - if (isDigit(text.charAt(i - 1)) && text.charAt(i) == groupingSeparator.charAt(0) && isDigit(text.charAt(i + 1))) { - // grouping separator => skip - continue; - } - sb.append(text.charAt(i)); - - } - return sb.toString(); - } - public void clearRecent() { Check.isMainThread(); recent.clear(); @@ -321,27 +291,25 @@ public class History { onRecentChanged(); } - @Subscribe - public void onEditorChanged(@Nonnull Editor.ChangedEvent e) { - if (!initialized) { - return; - } - lastEditorState = e.newState; - } - @Subscribe public void onDisplayChanged(@Nonnull Display.ChangedEvent e) { if (!initialized) { return; } - if (lastEditorState == null) { + final EditorState editorState = editor.getState(); + final DisplayState displayState = e.newState; + if (editorState.sequence != displayState.sequence) { return; } - if (lastEditorState.sequence != e.newState.sequence) { - return; + addRecent(HistoryState.newBuilder(editorState, displayState).build()); + } + + public static class ChangedEvent { + public final boolean recent; + + public ChangedEvent(boolean recent) { + this.recent = recent; } - addRecent(HistoryState.newBuilder(lastEditorState, e.newState).build()); - lastEditorState = null; } private class WriteTask implements Runnable { diff --git a/app/src/main/java/org/solovyev/android/calculator/history/RecentHistoryFragment.java b/app/src/main/java/org/solovyev/android/calculator/history/RecentHistoryFragment.java index 00b76e6a..531599a7 100644 --- a/app/src/main/java/org/solovyev/android/calculator/history/RecentHistoryFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/history/RecentHistoryFragment.java @@ -25,9 +25,8 @@ package org.solovyev.android.calculator.history; import org.solovyev.android.calculator.CalculatorFragmentType; import org.solovyev.android.calculator.R; -import java.util.List; - import javax.annotation.Nonnull; +import java.util.List; public class RecentHistoryFragment extends BaseHistoryFragment { @@ -51,4 +50,9 @@ public class RecentHistoryFragment extends BaseHistoryFragment { history.clearRecent(); getAdapter().clear(); } + + @Override + protected boolean isRecentHistory() { + return true; + } } diff --git a/app/src/main/java/org/solovyev/android/calculator/history/SavedHistoryFragment.java b/app/src/main/java/org/solovyev/android/calculator/history/SavedHistoryFragment.java index 4dd7f540..7b5eb7eb 100644 --- a/app/src/main/java/org/solovyev/android/calculator/history/SavedHistoryFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/history/SavedHistoryFragment.java @@ -25,9 +25,8 @@ package org.solovyev.android.calculator.history; import org.solovyev.android.calculator.CalculatorFragmentType; import org.solovyev.android.calculator.R; -import java.util.List; - import javax.annotation.Nonnull; +import java.util.List; public class SavedHistoryFragment extends BaseHistoryFragment { @@ -51,4 +50,9 @@ public class SavedHistoryFragment extends BaseHistoryFragment { history.clearSaved(); getAdapter().clear(); } + + @Override + protected boolean isRecentHistory() { + return false; + } } diff --git a/app/src/test/java/org/solovyev/android/CalculatorTestRunner.java b/app/src/test/java/org/solovyev/android/CalculatorTestRunner.java index fcf55412..7ccfbfa9 100644 --- a/app/src/test/java/org/solovyev/android/CalculatorTestRunner.java +++ b/app/src/test/java/org/solovyev/android/CalculatorTestRunner.java @@ -1,5 +1,6 @@ package org.solovyev.android; +import android.os.Build; import org.junit.runners.model.InitializationError; import org.robolectric.RobolectricGradleTestRunner; import org.robolectric.annotation.Config; @@ -7,7 +8,7 @@ import org.robolectric.manifest.AndroidManifest; import org.robolectric.res.Fs; public class CalculatorTestRunner extends RobolectricGradleTestRunner { - private static final int MAX_SDK_SUPPORTED_BY_ROBOLECTRIC = 18; + public static final int SUPPORTED_SDK = Build.VERSION_CODES.LOLLIPOP; public CalculatorTestRunner(Class testClass) throws InitializationError { super(testClass); @@ -21,7 +22,7 @@ public class CalculatorTestRunner extends RobolectricGradleTestRunner { return new AndroidManifest(Fs.fileFromPath(manifestFilePath), Fs.fileFromPath(resourcesFilePath), Fs.fileFromPath(assetsFilePath)) { @Override public int getTargetSdkVersion() { - return MAX_SDK_SUPPORTED_BY_ROBOLECTRIC; + return SUPPORTED_SDK; } }; } diff --git a/app/src/test/java/org/solovyev/android/calculator/AbstractCalculatorTest.java b/app/src/test/java/org/solovyev/android/calculator/AbstractCalculatorTest.java index 68e21c62..4f02cae5 100644 --- a/app/src/test/java/org/solovyev/android/calculator/AbstractCalculatorTest.java +++ b/app/src/test/java/org/solovyev/android/calculator/AbstractCalculatorTest.java @@ -22,9 +22,12 @@ package org.solovyev.android.calculator; +import com.squareup.otto.Bus; import org.mockito.Mockito; import org.solovyev.android.calculator.plot.CalculatorPlotter; +import java.util.concurrent.Executor; + /** * User: serso * Date: 10/7/12 @@ -33,7 +36,7 @@ import org.solovyev.android.calculator.plot.CalculatorPlotter; public class AbstractCalculatorTest { protected void setUp() throws Exception { - Locator.getInstance().init(new CalculatorImpl(null, eventExecutor), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class)); + Locator.getInstance().init(new CalculatorImpl(Mockito.mock(Bus.class), Mockito.mock(Executor.class)), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class)); Locator.getInstance().getEngine().init(); } diff --git a/app/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java b/app/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java index bbe7b82e..85e0a4a2 100644 --- a/app/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java +++ b/app/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java @@ -23,32 +23,25 @@ package org.solovyev.android.calculator; import android.content.Context; - +import com.squareup.otto.Bus; +import jscl.JsclMathEngine; import org.junit.Assert; import org.mockito.Mockito; -import org.robolectric.RuntimeEnvironment; import org.robolectric.fakes.RoboSharedPreferences; import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.language.Languages; import org.solovyev.android.calculator.plot.CalculatorPlotter; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.*; import java.text.DecimalFormatSymbols; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import jscl.JsclMathEngine; - /** * User: serso * Date: 10/7/12 @@ -60,8 +53,8 @@ public class CalculatorTestUtils { public static final int TIMEOUT = 3; public static void staticSetUp() throws Exception { - App.init(RuntimeEnvironment.application, new Languages(new RoboSharedPreferences(new HashMap>(), "test", 0))); - Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class)); + App.init(new CalculatorApplication(), new Languages(new RoboSharedPreferences(new HashMap>(), "test", 0))); + Locator.getInstance().init(new CalculatorImpl(Mockito.mock(Bus.class), Mockito.mock(Executor.class)), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class)); Locator.getInstance().getEngine().init(); final DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(); @@ -71,7 +64,7 @@ public class CalculatorTestUtils { } public static void staticSetUp(@Nullable Context context) throws Exception { - Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class)); + Locator.getInstance().init(new CalculatorImpl(Mockito.mock(Bus.class), Mockito.mock(Executor.class)), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class)); Locator.getInstance().getEngine().init(); if (context != null) { diff --git a/app/src/test/java/org/solovyev/android/calculator/EditorTest.java b/app/src/test/java/org/solovyev/android/calculator/EditorTest.java index a2c9c877..fa73437a 100644 --- a/app/src/test/java/org/solovyev/android/calculator/EditorTest.java +++ b/app/src/test/java/org/solovyev/android/calculator/EditorTest.java @@ -22,9 +22,11 @@ package org.solovyev.android.calculator; +import android.preference.PreferenceManager; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.robolectric.RuntimeEnvironment; import javax.annotation.Nonnull; @@ -41,7 +43,7 @@ public class EditorTest extends AbstractCalculatorTest { @Before public void setUp() throws Exception { super.setUp(); - this.editor = new Editor(null); + this.editor = new Editor(PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)); } @Test diff --git a/app/src/test/java/org/solovyev/android/calculator/history/HistoryTest.java b/app/src/test/java/org/solovyev/android/calculator/history/HistoryTest.java index 5e2c8b04..ff962636 100644 --- a/app/src/test/java/org/solovyev/android/calculator/history/HistoryTest.java +++ b/app/src/test/java/org/solovyev/android/calculator/history/HistoryTest.java @@ -22,61 +22,172 @@ package org.solovyev.android.calculator.history; +import android.content.SharedPreferences; +import android.os.Handler; import com.squareup.otto.Bus; - -import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; +import org.robolectric.RobolectricGradleTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import org.solovyev.android.CalculatorTestRunner; -import org.solovyev.android.calculator.CalculatorTestUtils; +import org.solovyev.android.calculator.BuildConfig; import org.solovyev.android.calculator.DisplayState; +import org.solovyev.android.calculator.Editor; import org.solovyev.android.calculator.EditorState; +import javax.annotation.Nonnull; import java.util.List; import java.util.concurrent.Executor; -import javax.annotation.Nonnull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; -@RunWith(CalculatorTestRunner.class) +@Config(constants = BuildConfig.class, sdk = CalculatorTestRunner.SUPPORTED_SDK) +@RunWith(RobolectricGradleTestRunner.class) public class HistoryTest { - @BeforeClass - public static void setUp() throws Exception { - CalculatorTestUtils.staticSetUp(); + private History history; + + @Before + public void setUp() throws Exception { + history = new History(Mockito.mock(Bus.class), Mockito.mock(Executor.class)); + history.handler = Mockito.mock(Handler.class); + history.preferences = Mockito.mock(SharedPreferences.class); + history.editor = Mockito.mock(Editor.class); + history.application = RuntimeEnvironment.application; } @Test public void testGetStates() throws Exception { - History history = new History(Mockito.any(Bus.class), new Executor() { - @Override - public void execute(@Nonnull Runnable command) { - command.run(); - } - }); - - addState(history, "1"); - addState(history, "12"); - addState(history, "123"); - addState(history, "123+"); - addState(history, "123+3"); - addState(history, ""); - addState(history, "2"); - addState(history, "23"); - addState(history, "235"); - addState(history, "2355"); - addState(history, "235"); - addState(history, "2354"); - addState(history, "23547"); + addState("1"); + addState("12"); + addState("123"); + addState("123+"); + addState("123+3"); + addState(""); + addState("2"); + addState("23"); + addState("235"); + addState("2355"); + addState("235"); + addState("2354"); + addState("23547"); final List states = history.getRecent(); - Assert.assertEquals(2, states.size()); - Assert.assertEquals("23547", states.get(1).editor.getTextString()); - Assert.assertEquals("123+3", states.get(0).editor.getTextString()); + assertEquals(2, states.size()); + assertEquals("23547", states.get(0).editor.getTextString()); + assertEquals("123+3", states.get(1).editor.getTextString()); } - private void addState(@Nonnull History history, @Nonnull String text) { + @Test + public void testRecentHistoryShouldNotContainEmptyStates() throws Exception { + addState(""); + addState("1"); + addState("12"); + addState(""); + addState(""); + addState("34"); + addState(""); + + final List states = history.getRecent(); + assertEquals(2, states.size()); + assertEquals("34", states.get(0).editor.getTextString()); + assertEquals("12", states.get(1).editor.getTextString()); + } + + private void addState(@Nonnull String text) { history.addRecent(HistoryState.newBuilder(EditorState.create(text, 3), DisplayState.empty())); } + + private static final String oldXml1 = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 3\n" + + " 1+1\n" + + " \n" + + " \n" + + " \n" + + " 0\n" + + " Error\n" + + " \n" + + " simplify\n" + + " \n" + + " \n" + + " \n" + + ""; + private static final String oldXml2 = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 3\n" + + " 1+1\n" + + " \n" + + " \n" + + " \n" + + " 0\n" + + " Error\n" + + " \n" + + " simplify\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 2\n" + + " 5/6\n" + + " \n" + + " \n" + + " \n" + + " 3\n" + + " 5/6\n" + + " \n" + + " numeric\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 0\n" + + " Error\n" + + " \n" + + " elementary\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 0\n" + + " 4+5/35sin(41)+dfdsfsdfs\n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " 4+5/35sin(41)+dfdsfsdfs\n" + + " \n" + + " numeric\n" + + " \n" + + " \n" + + " \n" + + ""; + + @Test + public void testShouldConvertOldHistory() throws Exception { + List states = History.convertOldHistory(oldXml1); + assertNotNull(states); + assertEquals(1, states.size()); + + HistoryState state = states.get(0); + assertEquals(100000000, state.time); + } } diff --git a/app/src/test/java/org/solovyev/android/calculator/history/HistoryUtilsTest.java b/app/src/test/java/org/solovyev/android/calculator/history/HistoryUtilsTest.java index b543e2c9..a4536b98 100644 --- a/app/src/test/java/org/solovyev/android/calculator/history/HistoryUtilsTest.java +++ b/app/src/test/java/org/solovyev/android/calculator/history/HistoryUtilsTest.java @@ -34,85 +34,6 @@ public class HistoryUtilsTest { private static final String emptyHistory = "\n" + " \n" + ""; - private static final String toXml1 = "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 3\n" + - " 1+1\n" + - " \n" + - " \n" + - " \n" + - " 0\n" + - " Error\n" + - " \n" + - " simplify\n" + - " \n" + - " \n" + - " \n" + - ""; - private static final String toXml2 = "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 3\n" + - " 1+1\n" + - " \n" + - " \n" + - " \n" + - " 0\n" + - " Error\n" + - " \n" + - " simplify\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 2\n" + - " 5/6\n" + - " \n" + - " \n" + - " \n" + - " 3\n" + - " 5/6\n" + - " \n" + - " numeric\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 1\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 0\n" + - " Error\n" + - " \n" + - " elementary\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " 0\n" + - " 4+5/35sin(41)+dfdsfsdfs\n" + - " \n" + - " \n" + - " \n" + - " 1\n" + - " 4+5/35sin(41)+dfdsfsdfs\n" + - " \n" + - " numeric\n" + - " \n" + - " \n" + - " \n" + - ""; - @Test public void testFromXml() throws Exception {