├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── maximefimov.xml
├── gradle.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── modules.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── redmadrobot
│ │ └── chronos_sample
│ │ ├── MainActivity.java
│ │ ├── Sample.java
│ │ ├── operations
│ │ └── SimpleOperation.java
│ │ └── samples
│ │ ├── DataLoad.java
│ │ ├── DataLoadCancel.java
│ │ └── SimpleRun.java
│ └── res
│ ├── layout
│ ├── activity_data_load.xml
│ ├── activity_data_load_cancel.xml
│ ├── activity_main.xml
│ └── activity_simple_run.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ └── values
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── chronos
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── redmadrobot
│ │ └── chronos
│ │ ├── ActivityRunTest.java
│ │ ├── BroadcastRunTest.java
│ │ ├── FragmentRunTest.java
│ │ ├── MemoryTest.java
│ │ ├── SetupTest.java
│ │ ├── TestSettings.java
│ │ ├── mock
│ │ ├── BigObject.java
│ │ ├── gui
│ │ │ ├── MockActivity.java
│ │ │ ├── MockFragment.java
│ │ │ ├── SampleHeavyActivity.java
│ │ │ ├── SimpleMockActivity.java
│ │ │ ├── SimpleMockFragment.java
│ │ │ └── State.java
│ │ └── operation
│ │ │ ├── HeavyOperation.java
│ │ │ ├── HeavyOperationResult.java
│ │ │ ├── SimpleErrorOperation.java
│ │ │ ├── SimpleOperation.java
│ │ │ └── SimpleOperationResult.java
│ │ └── util
│ │ └── TimingUtils.java
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── redmadrobot
│ └── chronos
│ ├── Chronos.java
│ ├── ChronosConnector.java
│ ├── ChronosListener.java
│ ├── ChronosListenerManager.java
│ ├── ChronosOperation.java
│ ├── ChronosOperationResult.java
│ ├── ChronosService.java
│ ├── RunningOperationStorage.java
│ └── gui
│ ├── ChronosConnectorWrapper.java
│ ├── activity
│ ├── ChronosActivity.java
│ ├── ChronosAppCompatActivity.java
│ └── ChronosSupportActivity.java
│ └── fragment
│ ├── ChronosFragment.java
│ ├── ChronosSupportFragment.java
│ └── dialog
│ ├── ChronosDialogFragment.java
│ └── ChronosSupportDialogFragment.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | # Built application files
4 | *.apk
5 | *.ap_
6 |
7 | # Files for the Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 |
17 | # Gradle files
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | #Log Files
28 | *.log
29 |
30 | #Android Studio
31 | .idea
32 | *.iml
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Chronos
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/maximefimov.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Redmadrobot
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Chronos
2 | Android library that handles asynchronous jobs.
3 | To read the full description, please take a look at [wiki page](https://github.com/RedMadRobot/Chronos/wiki).
4 |
5 | To add Chronos to your project simply add the following code to `dependencies` section of your `build.gradle` file:
6 |
7 | `compile 'com.redmadrobot:chronos:1.0.7'`
8 |
9 | ## Release notes
10 |
11 | 1.0.7
12 | - Added AppCompat default Acitivty. Use this version only if your app uses compileSdkVersion >= 23.
13 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.redmadrobot.chronos_sample"
9 | minSdkVersion 9
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | compile 'com.android.support:appcompat-v7:23.1.1'
25 | compile project(':chronos')
26 | }
27 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/maximefimov/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/redmadrobot/chronos_sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos_sample;
2 |
3 | import com.redmadrobot.chronos_sample.samples.DataLoad;
4 | import com.redmadrobot.chronos_sample.samples.DataLoadCancel;
5 | import com.redmadrobot.chronos_sample.samples.SimpleRun;
6 |
7 | import android.app.Activity;
8 | import android.content.Intent;
9 | import android.os.Bundle;
10 | import android.support.annotation.NonNull;
11 | import android.view.View;
12 | import android.widget.AdapterView;
13 | import android.widget.ArrayAdapter;
14 | import android.widget.ListAdapter;
15 | import android.widget.ListView;
16 |
17 | import java.util.ArrayList;
18 | import java.util.List;
19 |
20 | /**
21 | * Home screen for the sample app.
22 | *
23 | * @author maximefimov
24 | */
25 | public final class MainActivity extends Activity {
26 |
27 | @Override
28 | protected void onCreate(final Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_main);
31 |
32 | final ListView sampleList = (ListView) findViewById(R.id.list_samples);
33 |
34 | final ListAdapter adapter = new ArrayAdapter<>(this,
35 | android.R.layout.simple_list_item_1, getSamples());
36 |
37 | sampleList.setAdapter(adapter);
38 | sampleList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
39 | @Override
40 | public void onItemClick(final AdapterView> parent, final View view,
41 | final int position, final long id) {
42 | showSample((Sample) parent.getAdapter().getItem(position));
43 |
44 | }
45 | });
46 | }
47 |
48 | private List getSamples() {
49 | final List samples = new ArrayList<>();
50 |
51 | samples.add(new Sample("Simple run", SimpleRun.class));
52 | samples.add(new Sample("Data loading", DataLoad.class));
53 | samples.add(new Sample("Data loading with cancel", DataLoadCancel.class));
54 |
55 | return samples;
56 | }
57 |
58 | private void showSample(@NonNull final Sample sample) {
59 | startActivity(new Intent(this, sample.getActivityClass()));
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/redmadrobot/chronos_sample/Sample.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos_sample;
2 |
3 | import android.app.Activity;
4 | import android.support.annotation.NonNull;
5 |
6 | /**
7 | * A entity represents a Chronos sample.
8 | *
9 | * @author maximefimov
10 | */
11 | public final class Sample {
12 |
13 | private final String mName;
14 |
15 | private final Class extends Activity> mActivityClass;
16 |
17 | public Sample(@NonNull final String name,
18 | @NonNull final Class extends Activity> activityClass) {
19 | mName = name;
20 | mActivityClass = activityClass;
21 | }
22 |
23 | @NonNull
24 | public final Class extends Activity> getActivityClass() {
25 | return mActivityClass;
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | return mName;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/redmadrobot/chronos_sample/operations/SimpleOperation.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos_sample.operations;
2 |
3 | import com.redmadrobot.chronos.ChronosOperation;
4 | import com.redmadrobot.chronos.ChronosOperationResult;
5 |
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 |
9 | /**
10 | * An operation that calculates a string length, mocking it is being a time-consuming task.
11 | *
12 | * @author maximefimov
13 | */
14 | public final class SimpleOperation extends ChronosOperation {
15 |
16 | private final String mInput;
17 |
18 | public SimpleOperation(@NonNull final String input) {
19 | mInput = input;
20 | }
21 |
22 | @Nullable
23 | @Override
24 | //Chronos will run this method in a background thread, which means you can put
25 | //any time-consuming calls here, as it will not affect UI thread performance
26 | public String run() {
27 | final String result = "String length is " + mInput.length();
28 |
29 | try {
30 | Thread.sleep(3000);
31 | } catch (InterruptedException e) {
32 | // do nothing, thread is interrupted, which means a system wants to stop the run
33 | }
34 |
35 | return result;
36 | }
37 |
38 | @NonNull
39 | @Override
40 | // To be able to distinguish results from different operations in one Chronos client
41 | // (most commonly an activity, or a fragment)
42 | // you should create an 'OperationResult<>' subclass in each operation,
43 | // so that it will be used as a parameter
44 | // in a callback method 'onOperationFinished'
45 | public Class extends ChronosOperationResult> getResultClass() {
46 | return Result.class;
47 | }
48 |
49 | public final static class Result extends ChronosOperationResult {
50 |
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/redmadrobot/chronos_sample/samples/DataLoad.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos_sample.samples;
2 |
3 | import com.redmadrobot.chronos.gui.activity.ChronosActivity;
4 | import com.redmadrobot.chronos_sample.R;
5 | import com.redmadrobot.chronos_sample.operations.SimpleOperation;
6 |
7 | import android.os.Bundle;
8 | import android.support.annotation.NonNull;
9 | import android.widget.TextView;
10 |
11 | /**
12 | * A sample of how you can easily initiate your layout with data provided by some source, that takes
13 | * some time to give a response, such as remote server, or a database.
14 | *
15 | * @author maximefimov
16 | */
17 | public final class DataLoad extends ChronosActivity {
18 |
19 | // a key by which the activity saves and restores already loaded data
20 | private final static String KEY_DATA = "data";
21 |
22 | // a tag which represents a group of operations that can't run simultaneously
23 | private final static String TAG_DATA_LOADING = "data_loading";
24 |
25 | private TextView mTextOutput;
26 |
27 | // a data that has to be loaded
28 | private String mData = null;
29 |
30 | @Override
31 | protected void onCreate(final Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_data_load);
34 |
35 | mTextOutput = (TextView) findViewById(R.id.text_output);
36 |
37 | if (savedInstanceState != null) {
38 | //first of all, the activity tries to restored already loaded data
39 | mData = savedInstanceState.getString(KEY_DATA);
40 | }
41 | }
42 |
43 | @Override
44 | protected void onResume() {
45 | super.onResume();
46 | //after this point all pending OperationResults are delivered, so that you may be sure,
47 | // that all proper 'onOperationFinished' calls are done
48 |
49 | if (mData == null) {// if it is still no data
50 | // The activity launches a loading operations with a tag
51 | // so that if it comes to this point once again and the data is not loaded yet,
52 | // the next launch will be ignored.
53 | // That means, no matter now often user rotates the device,
54 | // only one operation with a given tag may be pending in a single moment of time.
55 | runOperation(new SimpleOperation(""), TAG_DATA_LOADING);
56 | } else {
57 | // If there is a data already, just show it;
58 | showData();
59 | }
60 | }
61 |
62 | @Override
63 | protected void onSaveInstanceState(@NonNull final Bundle outState) {
64 | super.onSaveInstanceState(outState);
65 | // It's important to manually save loaded data, as for now Chronos doesn't have an built-in cache
66 | outState.putString(KEY_DATA, mData);
67 | }
68 |
69 | private void showData() {
70 | mTextOutput.setText("Data is '" + mData + "'");
71 | }
72 |
73 | public void onOperationFinished(final SimpleOperation.Result result) {
74 | if (result.isSuccessful()) {
75 | // After the activity got the data, it is being saved to a local variable.
76 | // The programmer should take care of saving it during activity destroy-recreation process.
77 | mData = result.getOutput();
78 | showData();
79 | } else {
80 | // Here the negative result is not stored, so it
81 | mTextOutput.setText(result.getErrorMessage());
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/com/redmadrobot/chronos_sample/samples/DataLoadCancel.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos_sample.samples;
2 |
3 | import com.redmadrobot.chronos.gui.activity.ChronosActivity;
4 | import com.redmadrobot.chronos_sample.R;
5 | import com.redmadrobot.chronos_sample.operations.SimpleOperation;
6 |
7 | import android.os.Bundle;
8 | import android.support.annotation.NonNull;
9 | import android.view.View;
10 | import android.widget.TextView;
11 | import android.widget.Toast;
12 |
13 | /**
14 | * An sample of it is possible to cancell a running operation.
15 | *
16 | * @author maximefimov
17 | */
18 | public final class DataLoadCancel extends ChronosActivity {
19 |
20 | private final static String KEY_DATA = "data";
21 |
22 | private final static String TAG_DATA_LOADING = "data_loading";
23 |
24 | private TextView mTextOutput;
25 |
26 | private String mData = null;
27 |
28 | @Override
29 | protected void onCreate(final Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_data_load_cancel);
32 |
33 | mTextOutput = (TextView) findViewById(R.id.text_output);
34 |
35 | if (savedInstanceState != null) {
36 | mData = savedInstanceState.getString(KEY_DATA);
37 | }
38 |
39 | final View cancelView = findViewById(R.id.button_cancel);
40 | cancelView.setOnClickListener(new View.OnClickListener() {
41 | @Override
42 | public void onClick(final View v) {
43 | // in any moment of time you can try to cancel a running operation
44 | // though the run may not be cancelled, e.g. the run has been finished already, or never been issued at all
45 | final boolean cancelResult = cancelOperation(TAG_DATA_LOADING);
46 | if (cancelResult) {
47 | mTextOutput.setText("Operation launch is cancelled");
48 | } else {
49 | showToast("Can't cancel operation launch");
50 | }
51 | }
52 | });
53 | }
54 |
55 | @Override
56 | protected void onResume() {
57 | super.onResume();
58 | if (mData == null) {
59 | runOperation(new SimpleOperation(""), TAG_DATA_LOADING);
60 | } else {
61 | showData();
62 | }
63 | }
64 |
65 | @Override
66 | protected void onSaveInstanceState(@NonNull final Bundle outState) {
67 | super.onSaveInstanceState(outState);
68 | outState.putString(KEY_DATA, mData);
69 | }
70 |
71 | private void showData() {
72 | mTextOutput.setText("Data is '" + mData + "'");
73 | }
74 |
75 | // if Operations run is cancelled, there would be no call to this method, thus you should handle
76 | // cancelling in the place it happened
77 | public void onOperationFinished(final SimpleOperation.Result result) {
78 | if (result.isSuccessful()) {
79 | mData = result.getOutput();
80 | showData();
81 | } else {
82 | mTextOutput.setText(result.getErrorMessage());
83 | }
84 | }
85 |
86 | private void showToast(@NonNull final String message) {
87 | Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/app/src/main/java/com/redmadrobot/chronos_sample/samples/SimpleRun.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos_sample.samples;
2 |
3 | import com.redmadrobot.chronos.gui.activity.ChronosActivity;
4 | import com.redmadrobot.chronos_sample.R;
5 | import com.redmadrobot.chronos_sample.operations.SimpleOperation;
6 |
7 | import android.os.Bundle;
8 | import android.view.View;
9 | import android.widget.EditText;
10 | import android.widget.TextView;
11 |
12 | /**
13 | * A sample of how to use Chronos in a most minimalistic way.
14 | *
15 | * @author maximefimov
16 | */
17 | public final class SimpleRun extends ChronosActivity {
18 |
19 | private TextView mTextOutput;
20 |
21 | @Override
22 | protected void onCreate(final Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(R.layout.activity_simple_run);
25 |
26 | final EditText editInput = (EditText) findViewById(R.id.edit_input);
27 | final View startView = findViewById(R.id.button_start);
28 | mTextOutput = (TextView) findViewById(R.id.text_output);
29 |
30 | startView.setOnClickListener(new View.OnClickListener() {
31 | @Override
32 | public void onClick(final View v) {
33 | // call the 'runOperation' method and it will begin executing of the operation
34 | // in background thread, so it will not block your GUI.
35 | runOperation(new SimpleOperation(editInput.getText().toString()));
36 | // after run is started, you can rotate, or put the sample to background
37 | // but the result of the operation will be delivered to an 'onOperationFinished' method
38 | // when the app goes to foreground once again.
39 | }
40 | });
41 | }
42 |
43 | //most IDEs may assume this method as 'not-used', which is a side effect of Chronos software design,
44 | //so may want to suppress the warning to not get confused
45 | public void onOperationFinished(final SimpleOperation.Result result) {
46 | //Here you process the result
47 | if (result
48 | .isSuccessful()) { // this case happens when no exception was thrown during the operation run
49 | mTextOutput.setText(result.getOutput());
50 | } else { // this happens if there was an exception
51 | mTextOutput.setText(result.getErrorMessage());
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_data_load.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
12 |
13 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_data_load_cancel.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
12 |
13 |
18 |
19 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_simple_run.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
18 |
19 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedMadRobot/Chronos/cf7fbcf6072b3508c45b253b79f19ed81304a76e/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedMadRobot/Chronos/cf7fbcf6072b3508c45b253b79f19ed81304a76e/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedMadRobot/Chronos/cf7fbcf6072b3508c45b253b79f19ed81304a76e/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedMadRobot/Chronos/cf7fbcf6072b3508c45b253b79f19ed81304a76e/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Chronos
3 | Enter an input string
4 | Start
5 | Here will be an output
6 | Here will be a data
7 | Every time this activity is resumed it tries to load a data. But it will not start multiple loading tasks.
8 | Cancel
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | maven {
6 | url "http://dl.bintray.com/rmr/maven"
7 | }
8 | jcenter()
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:1.5.0'
12 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
13 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | jcenter()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/chronos/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chronos/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | apply plugin: 'com.jfrog.bintray'
4 |
5 | // This is the library version used when deploying the artifact
6 | version = "1.0.7"
7 |
8 |
9 | android {
10 | compileSdkVersion 23
11 | buildToolsVersion "23.0.2"
12 |
13 | defaultConfig {
14 | minSdkVersion 9
15 | targetSdkVersion 23
16 | versionCode 1
17 | versionName "1.0"
18 | }
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | }
26 |
27 | def siteUrl = 'https://github.com/RedMadRobot/Chronos' // Homepage URL of the library
28 | def gitUrl = 'https://github.com/RedMadRobot/Chronos.git' // Git repository URL
29 | group = "com.redmadrobot"
30 |
31 | install {
32 | repositories.mavenInstaller {
33 | // This generates POM.xml with proper parameters
34 | pom {
35 | project {
36 | packaging 'aar'
37 |
38 | // Add your description here
39 | name 'Chronos'
40 | description 'Android library that handles asynchronous tasks in a proper way'
41 | url siteUrl
42 |
43 | // Set your license
44 | licenses {
45 | license {
46 | name 'MIT License'
47 | url 'http://opensource.org/licenses/MIT'
48 | }
49 | }
50 | developers {
51 | developer {
52 | id 'm_efimov'
53 | name 'Maxim Efimov'
54 | email 'me@redmadrobot.com'
55 | }
56 | }
57 | scm {
58 | connection gitUrl
59 | developerConnection gitUrl
60 | url siteUrl
61 |
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
68 |
69 | dependencies {
70 | compile fileTree(dir: 'libs', include: ['*.jar'])
71 | compile 'com.android.support:appcompat-v7:23.1.1'
72 | compile 'com.android.support:support-annotations:23.1.1'
73 | compile 'de.greenrobot:eventbus:2.4.0'
74 | compile 'org.jetbrains:annotations:13.0'
75 |
76 | testCompile 'junit:junit:4.12'
77 | }
78 |
79 | task sourcesJar(type: Jar) {
80 | from android.sourceSets.main.java.srcDirs
81 | classifier = 'sources'
82 | }
83 |
84 | task javadoc(type: Javadoc) {
85 | android.libraryVariants.all { variant ->
86 | task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
87 | description "Generates Javadoc for $variant.name."
88 | source = variant.javaCompile.source
89 | ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
90 | classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar)
91 | options.links("http://docs.oracle.com/javase/7/docs/api/");
92 | options.links("http://d.android.com/reference/");
93 | }
94 | }
95 | }
96 |
97 | task javadocJar(type: Jar, dependsOn: javadoc) {
98 | classifier = 'javadoc'
99 | from javadoc.destinationDir
100 | }
101 |
102 | artifacts {
103 | archives javadocJar
104 | archives sourcesJar
105 | }
106 |
107 | Properties properties = new Properties()
108 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
109 |
110 | bintray {
111 | user = properties.getProperty("bintray.user")
112 | key = properties.getProperty("bintray.apikey")
113 | def gpgPassphrase = properties.getProperty("oss.password")
114 |
115 | configurations = ['archives']
116 | pkg {
117 | repo = "maven"
118 | name = "chronos"
119 | desc = 'Android library that handles asynchronous tasks in a proper way'
120 | websiteUrl = siteUrl
121 | vcsUrl = gitUrl
122 | licenses = ["MIT"]
123 | publish = true
124 | version {
125 | gpg {
126 | sign = true //Determines whether to GPG sign the files. The default is false
127 | passphrase = gpgPassphrase //Optional. The passphrase for GPG signing'
128 | }
129 | }
130 | }
131 | }
--------------------------------------------------------------------------------
/chronos/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/maximefimov/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/ActivityRunTest.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos;
2 |
3 | import com.redmadrobot.chronos.mock.gui.SimpleMockActivity;
4 | import com.redmadrobot.chronos.mock.operation.SimpleErrorOperation;
5 | import com.redmadrobot.chronos.mock.operation.SimpleOperation;
6 |
7 | import android.test.AndroidTestCase;
8 | import android.test.suitebuilder.annotation.SmallTest;
9 |
10 | import static com.redmadrobot.chronos.TestSettings.INPUT;
11 | import static com.redmadrobot.chronos.TestSettings.SHORT_WAIT;
12 | import static com.redmadrobot.chronos.util.TimingUtils.sleep;
13 |
14 | /**
15 | * Test for operation runs in Activity.
16 | *
17 | * @author maximefimov
18 | */
19 | public class ActivityRunTest extends AndroidTestCase {
20 |
21 | @SmallTest
22 | public void testNormalRun() {
23 | final SimpleMockActivity activity = new SimpleMockActivity();
24 | activity.start();
25 | activity.runSimple(INPUT);
26 | sleep();
27 | assertTrue(activity.getResultObtained() == 1);
28 | assertTrue(SimpleOperation.isTransform(INPUT, activity.getResult()));
29 | assertNull(activity.getError());
30 | }
31 |
32 | @SmallTest
33 | public void testNormalRunRotate() {
34 | final SimpleMockActivity activity = new SimpleMockActivity();
35 | activity.start();
36 | activity.runSimple(INPUT);
37 | activity.stop();
38 | sleep();
39 | activity.start();
40 | assertTrue(activity.getResultObtained() == 1);
41 | assertTrue(SimpleOperation.isTransform(INPUT, activity.getResult()));
42 | assertNull(activity.getError());
43 | }
44 |
45 | @SmallTest
46 | public void testErrorRun() {
47 | final SimpleMockActivity activity = new SimpleMockActivity();
48 | activity.start();
49 | activity.runErrorSimple();
50 | sleep();
51 | assertTrue(activity.getResultObtained() == 1);
52 | assertNotNull(SimpleErrorOperation.isExpectedException(activity.getError()));
53 | assertNull(activity.getResult());
54 | }
55 |
56 | @SmallTest
57 | public void testErrorRunRotate() {
58 | final SimpleMockActivity activity = new SimpleMockActivity();
59 | activity.start();
60 | activity.runErrorSimple();
61 | activity.stop();
62 | sleep();
63 | activity.start();
64 | assertTrue(activity.getResultObtained() == 1);
65 | assertNotNull(SimpleErrorOperation.isExpectedException(activity.getError()));
66 | assertNull(activity.getResult());
67 | }
68 |
69 | @SmallTest
70 | public void testCancelRun() {
71 | final SimpleMockActivity activity = new SimpleMockActivity();
72 | activity.start();
73 | final int runId = activity.runSimple(INPUT);
74 | final boolean cancelResult = activity.cancel(runId);
75 | assertTrue(cancelResult);
76 | sleep();
77 | assertFalse(activity.gotResult());
78 | }
79 |
80 | @SmallTest
81 | public void testCancelRunRotate() {
82 | final SimpleMockActivity activity = new SimpleMockActivity();
83 | activity.start();
84 | final int runId = activity.runSimple(INPUT);
85 | final boolean cancelResult = activity.cancel(runId);
86 | assertTrue(cancelResult);
87 | activity.stop();
88 | sleep();
89 | activity.start();
90 | assertFalse(activity.gotResult());
91 | }
92 |
93 | @SmallTest
94 | public void testCancelAfterRun() {
95 | final SimpleMockActivity activity = new SimpleMockActivity();
96 | activity.start();
97 | final int runId = activity.runSimple(INPUT);
98 | sleep();
99 | final boolean cancelResult = activity.cancel(runId);
100 | assertFalse(cancelResult);
101 | assertTrue(activity.gotResult());
102 | }
103 |
104 | @SmallTest
105 | public void testCancelWrongId() {
106 | final SimpleMockActivity activity = new SimpleMockActivity();
107 | activity.start();
108 | final int runId = activity.runSimple(INPUT);
109 | final int wrongId = -1 * runId;
110 | final boolean cancelResult = activity.cancel(wrongId);
111 | assertFalse(cancelResult);
112 | sleep();
113 | assertTrue(activity.gotResult());
114 | }
115 |
116 | @SmallTest
117 | public void testNormalRunTagged() {
118 | final SimpleMockActivity activity = new SimpleMockActivity();
119 | activity.start();
120 | final int firstRunId = activity.runSimpleTagged(INPUT);
121 | final int secondRunId = activity.runSimpleTagged(INPUT);
122 | assertTrue(firstRunId == secondRunId);
123 | sleep();
124 | assertTrue(activity.getResultObtained() == 1);
125 | assertTrue(SimpleOperation.isTransform(INPUT, activity.getResult()));
126 | assertNull(activity.getError());
127 | }
128 |
129 | @SmallTest
130 | public void testNormalRunTaggedSequential() {
131 | final SimpleMockActivity activity = new SimpleMockActivity();
132 | activity.start();
133 | final int firstRunId = activity.runSimpleTagged(INPUT);
134 | sleep();
135 | assertTrue(activity.getResultObtained() == 1);
136 | assertTrue(SimpleOperation.isTransform(INPUT, activity.getResult()));
137 | assertNull(activity.getError());
138 |
139 | final int secondRunId = activity.runSimpleTagged(INPUT);
140 | assertTrue(firstRunId != secondRunId);
141 | sleep();
142 | assertTrue(activity.getResultObtained() == 2);
143 | assertTrue(SimpleOperation.isTransform(INPUT, activity.getResult()));
144 | assertNull(activity.getError());
145 | }
146 |
147 | @SmallTest
148 | public void testNormalRunRotateTagged() {
149 | final SimpleMockActivity activity = new SimpleMockActivity();
150 | activity.start();
151 | final int firstRunId = activity.runSimpleTagged(INPUT);
152 | activity.stop();
153 | activity.start();
154 | final int secondRunId = activity.runSimpleTagged(INPUT);
155 | assertTrue(firstRunId == secondRunId);
156 | sleep();
157 | assertTrue(activity.getResultObtained() == 1);
158 | assertTrue(SimpleOperation.isTransform(INPUT, activity.getResult()));
159 | assertNull(activity.getError());
160 | }
161 |
162 | @SmallTest
163 | public void testCancelRunTaggedById() {
164 | final SimpleMockActivity activity = new SimpleMockActivity();
165 | activity.start();
166 | final int runId = activity.runSimpleTagged(INPUT);
167 | final boolean cancelResult = activity.cancel(runId);
168 | assertTrue(cancelResult);
169 | sleep();
170 | assertFalse(activity.gotResult());
171 | }
172 |
173 | @SmallTest
174 | public void testCancelRunTaggedByTag() {
175 | final SimpleMockActivity activity = new SimpleMockActivity();
176 | activity.start();
177 | activity.runSimpleTagged(INPUT);
178 | final boolean cancelResult = activity.cancelTagged();
179 | assertTrue(cancelResult);
180 | sleep();
181 | assertFalse(activity.gotResult());
182 | }
183 |
184 | @SmallTest
185 | public void testRelaunchCancelledTaggedRunByTag() {
186 | final SimpleMockActivity activity = new SimpleMockActivity();
187 | activity.start();
188 | final int firstRunId = activity.runSimpleTagged(INPUT);
189 | final boolean cancelResult = activity.cancelTagged();
190 | assertTrue(cancelResult);
191 |
192 | final int secondRunId = activity.runSimpleTagged(INPUT);
193 | assertTrue(firstRunId != secondRunId);
194 | sleep();
195 | assertTrue(activity.getResultObtained() == 1);
196 | assertTrue(SimpleOperation.isTransform(INPUT, activity.getResult()));
197 | assertNull(activity.getError());
198 | }
199 |
200 | @SmallTest
201 | public void testRunningState() {
202 | final SimpleMockActivity activity = new SimpleMockActivity();
203 | activity.start();
204 | final int runId = activity.runSimple(INPUT);
205 | sleep(SHORT_WAIT);
206 | assertTrue(activity.isRunning(runId));
207 | sleep();
208 | assertFalse(activity.isRunning(runId));
209 | }
210 |
211 | @SmallTest
212 | public void testRunningStateRotate() {
213 | final SimpleMockActivity activity = new SimpleMockActivity();
214 | activity.start();
215 | final int runId = activity.runSimple(INPUT);
216 | activity.stop();
217 | sleep(SHORT_WAIT);
218 | activity.start();
219 | assertTrue(activity.isRunning(runId));
220 | activity.stop();
221 | sleep();
222 | activity.start();
223 | assertFalse(activity.isRunning(runId));
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/BroadcastRunTest.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos;
2 |
3 | import com.redmadrobot.chronos.mock.gui.SimpleMockActivity;
4 | import com.redmadrobot.chronos.mock.gui.SimpleMockFragment;
5 | import com.redmadrobot.chronos.mock.operation.SimpleOperation;
6 |
7 | import android.test.AndroidTestCase;
8 | import android.test.suitebuilder.annotation.SmallTest;
9 |
10 | import static com.redmadrobot.chronos.TestSettings.INPUT;
11 | import static com.redmadrobot.chronos.util.TimingUtils.sleep;
12 |
13 | /**
14 | * Test for broadcast operation runs.
15 | *
16 | * @author maximefimov
17 | */
18 | public class BroadcastRunTest extends AndroidTestCase {
19 |
20 | @SmallTest
21 | public void testNormalRunFromActivity() {
22 | final SimpleMockActivity firstActivity = new SimpleMockActivity();
23 | final SimpleMockFragment fragment = new SimpleMockFragment();
24 | firstActivity.addFragment(fragment);
25 | final SimpleMockActivity secondActivity = new SimpleMockActivity();
26 |
27 | firstActivity.start();
28 | secondActivity.start();
29 |
30 | secondActivity.runBroadcast(INPUT);
31 | sleep();
32 |
33 | assertTrue(secondActivity.getResultObtained() == 1);
34 | assertTrue(SimpleOperation.isTransform(INPUT, secondActivity.getResult()));
35 | assertNull(secondActivity.getError());
36 |
37 | assertFalse(secondActivity.gotBroadcastResult());
38 |
39 | assertFalse(firstActivity.gotResult());
40 | assertTrue(firstActivity.getBroadcastResultObtained() == 1);
41 | assertTrue(SimpleOperation.isTransform(INPUT, firstActivity.getBroadcastResult()));
42 | assertNull(firstActivity.getBroadcastError());
43 |
44 | assertFalse(fragment.gotResult());
45 | assertTrue(fragment.getBroadcastResultObtained() == 1);
46 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getBroadcastResult()));
47 | assertNull(fragment.getBroadcastError());
48 | }
49 |
50 | @SmallTest
51 | public void testNormalRunFromFragment() {
52 | final SimpleMockActivity firstActivity = new SimpleMockActivity();
53 | final SimpleMockFragment fragment = new SimpleMockFragment();
54 | firstActivity.addFragment(fragment);
55 | final SimpleMockActivity secondActivity = new SimpleMockActivity();
56 |
57 | firstActivity.start();
58 | secondActivity.start();
59 |
60 | fragment.runBroadcast(INPUT);
61 | sleep();
62 |
63 | assertTrue(fragment.getResultObtained() == 1);
64 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getResult()));
65 | assertNull(fragment.getError());
66 |
67 | assertFalse(fragment.gotBroadcastResult());
68 |
69 | assertFalse(firstActivity.gotResult());
70 | assertTrue(firstActivity.getBroadcastResultObtained() == 1);
71 | assertTrue(SimpleOperation.isTransform(INPUT, firstActivity.getBroadcastResult()));
72 | assertNull(firstActivity.getBroadcastError());
73 |
74 | assertFalse(secondActivity.gotResult());
75 | assertTrue(secondActivity.getBroadcastResultObtained() == 1);
76 | assertTrue(SimpleOperation.isTransform(INPUT, secondActivity.getBroadcastResult()));
77 | assertNull(secondActivity.getBroadcastError());
78 | }
79 |
80 | @SmallTest
81 | public void testCancelRun() {
82 | final SimpleMockActivity firstActivity = new SimpleMockActivity();
83 | final SimpleMockFragment fragment = new SimpleMockFragment();
84 | firstActivity.addFragment(fragment);
85 | final SimpleMockActivity secondActivity = new SimpleMockActivity();
86 |
87 | firstActivity.start();
88 | secondActivity.start();
89 |
90 | final int runId = secondActivity.runBroadcast(INPUT);
91 | final boolean cancelResult = secondActivity.cancel(runId);
92 | assertTrue(cancelResult);
93 | sleep();
94 |
95 | assertFalse(secondActivity.gotResult());
96 | assertFalse(secondActivity.gotBroadcastResult());
97 |
98 | assertFalse(firstActivity.gotResult());
99 | assertFalse(firstActivity.gotBroadcastResult());
100 |
101 | assertFalse(fragment.gotResult());
102 | assertFalse(fragment.gotBroadcastResult());
103 | }
104 |
105 |
106 | @SmallTest
107 | public void testNormalRunFromActivityRotate() {
108 | final SimpleMockActivity firstActivity = new SimpleMockActivity();
109 | final SimpleMockFragment fragment = new SimpleMockFragment();
110 | firstActivity.addFragment(fragment);
111 | final SimpleMockActivity secondActivity = new SimpleMockActivity();
112 |
113 | firstActivity.start();
114 | secondActivity.start();
115 |
116 | secondActivity.runBroadcast(INPUT);
117 | firstActivity.stop();
118 | sleep();
119 |
120 | assertTrue(secondActivity.getResultObtained() == 1);
121 | assertTrue(SimpleOperation.isTransform(INPUT, secondActivity.getResult()));
122 | assertNull(secondActivity.getError());
123 |
124 | assertFalse(secondActivity.gotBroadcastResult());
125 |
126 | assertFalse(firstActivity.gotResult());
127 | assertFalse(firstActivity.gotBroadcastResult());
128 |
129 | assertFalse(fragment.gotResult());
130 | assertFalse(fragment.gotBroadcastResult());
131 |
132 | firstActivity.start();
133 |
134 | assertFalse(firstActivity.gotResult());
135 | assertTrue(firstActivity.getBroadcastResultObtained() == 1);
136 | assertTrue(SimpleOperation.isTransform(INPUT, firstActivity.getBroadcastResult()));
137 | assertNull(firstActivity.getBroadcastError());
138 |
139 | assertFalse(fragment.gotResult());
140 | assertTrue(fragment.getBroadcastResultObtained() == 1);
141 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getBroadcastResult()));
142 | assertNull(fragment.getBroadcastError());
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/FragmentRunTest.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos;
2 |
3 | import com.redmadrobot.chronos.mock.gui.SimpleMockActivity;
4 | import com.redmadrobot.chronos.mock.gui.SimpleMockFragment;
5 | import com.redmadrobot.chronos.mock.operation.SimpleErrorOperation;
6 | import com.redmadrobot.chronos.mock.operation.SimpleOperation;
7 |
8 | import android.test.AndroidTestCase;
9 | import android.test.suitebuilder.annotation.SmallTest;
10 |
11 | import static com.redmadrobot.chronos.TestSettings.INPUT;
12 | import static com.redmadrobot.chronos.util.TimingUtils.sleep;
13 |
14 | /**
15 | * Test for operation runs in Fragment.
16 | *
17 | * @author maximefimov
18 | */
19 | public class FragmentRunTest extends AndroidTestCase {
20 |
21 | @SmallTest
22 | public void testNormalRun() {
23 | final SimpleMockActivity activity = new SimpleMockActivity();
24 | final SimpleMockFragment fragment = new SimpleMockFragment();
25 | activity.addFragment(fragment);
26 |
27 | activity.start();
28 | fragment.runSimple(INPUT);
29 | sleep();
30 | assertTrue(fragment.getResultObtained() == 1);
31 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getResult()));
32 | assertNull(fragment.getError());
33 | }
34 |
35 | @SmallTest
36 | public void testNormalRunRotate() {
37 | final SimpleMockActivity activity = new SimpleMockActivity();
38 | final SimpleMockFragment fragment = new SimpleMockFragment();
39 | activity.addFragment(fragment);
40 |
41 | activity.start();
42 | fragment.runSimple(INPUT);
43 | activity.stop();
44 | sleep();
45 | activity.start();
46 | assertTrue(fragment.getResultObtained() == 1);
47 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getResult()));
48 | assertNull(fragment.getError());
49 | }
50 |
51 | @SmallTest
52 | public void testErrorRun() {
53 | final SimpleMockActivity activity = new SimpleMockActivity();
54 | final SimpleMockFragment fragment = new SimpleMockFragment();
55 | activity.addFragment(fragment);
56 |
57 | activity.start();
58 | fragment.runErrorSimple();
59 | sleep();
60 | assertTrue(fragment.getResultObtained() == 1);
61 | assertNotNull(SimpleErrorOperation.isExpectedException(fragment.getError()));
62 | assertNull(fragment.getResult());
63 | }
64 |
65 | @SmallTest
66 | public void testErrorRunRotate() {
67 | final SimpleMockActivity activity = new SimpleMockActivity();
68 | final SimpleMockFragment fragment = new SimpleMockFragment();
69 | activity.addFragment(fragment);
70 |
71 | activity.start();
72 | fragment.runErrorSimple();
73 | activity.stop();
74 | sleep();
75 | activity.start();
76 | assertTrue(fragment.getResultObtained() == 1);
77 | assertNotNull(SimpleErrorOperation.isExpectedException(fragment.getError()));
78 | assertNull(fragment.getResult());
79 | }
80 |
81 | @SmallTest
82 | public void testCancelRun() {
83 | final SimpleMockActivity activity = new SimpleMockActivity();
84 | final SimpleMockFragment fragment = new SimpleMockFragment();
85 | activity.addFragment(fragment);
86 |
87 | activity.start();
88 | final int runId = fragment.runSimple(INPUT);
89 | final boolean cancelResult = fragment.cancel(runId);
90 | assertTrue(cancelResult);
91 | sleep();
92 | assertFalse(fragment.gotResult());
93 | }
94 |
95 | @SmallTest
96 | public void testCancelRunRotate() {
97 | final SimpleMockActivity activity = new SimpleMockActivity();
98 | final SimpleMockFragment fragment = new SimpleMockFragment();
99 | activity.addFragment(fragment);
100 |
101 | activity.start();
102 | final int runId = fragment.runSimple(INPUT);
103 | final boolean cancelResult = fragment.cancel(runId);
104 | assertTrue(cancelResult);
105 | activity.stop();
106 | sleep();
107 | activity.start();
108 | assertFalse(fragment.gotResult());
109 | }
110 |
111 | @SmallTest
112 | public void testCancelAfterRun() {
113 | final SimpleMockActivity activity = new SimpleMockActivity();
114 | final SimpleMockFragment fragment = new SimpleMockFragment();
115 | activity.addFragment(fragment);
116 |
117 | activity.start();
118 | final int runId = fragment.runSimple(INPUT);
119 | sleep();
120 | final boolean cancelResult = fragment.cancel(runId);
121 | assertFalse(cancelResult);
122 | assertTrue(fragment.gotResult());
123 | }
124 |
125 | @SmallTest
126 | public void testCancelWrongId() {
127 | final SimpleMockActivity activity = new SimpleMockActivity();
128 | final SimpleMockFragment fragment = new SimpleMockFragment();
129 | activity.addFragment(fragment);
130 |
131 | activity.start();
132 | final int runId = fragment.runSimple(INPUT);
133 | final int wrongId = -1 * runId;
134 | final boolean cancelResult = fragment.cancel(wrongId);
135 | assertFalse(cancelResult);
136 | sleep();
137 | assertTrue(fragment.gotResult());
138 | }
139 |
140 | @SmallTest
141 | public void testNormalRunTagged() {
142 | final SimpleMockActivity activity = new SimpleMockActivity();
143 | final SimpleMockFragment fragment = new SimpleMockFragment();
144 | activity.addFragment(fragment);
145 |
146 | activity.start();
147 | final int firstRunId = fragment.runSimpleTagged(INPUT);
148 | final int secondRunId = fragment.runSimpleTagged(INPUT);
149 | assertTrue(firstRunId == secondRunId);
150 | sleep();
151 | assertTrue(fragment.getResultObtained() == 1);
152 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getResult()));
153 | assertNull(fragment.getError());
154 | }
155 |
156 | @SmallTest
157 | public void testNormalRunTaggedSequential() {
158 | final SimpleMockActivity activity = new SimpleMockActivity();
159 | final SimpleMockFragment fragment = new SimpleMockFragment();
160 | activity.addFragment(fragment);
161 |
162 | activity.start();
163 | final int firstRunId = fragment.runSimpleTagged(INPUT);
164 | sleep();
165 | assertTrue(fragment.getResultObtained() == 1);
166 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getResult()));
167 | assertNull(fragment.getError());
168 |
169 | final int secondRunId = fragment.runSimpleTagged(INPUT);
170 | assertTrue(firstRunId != secondRunId);
171 | sleep();
172 | assertTrue(fragment.getResultObtained() == 2);
173 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getResult()));
174 | assertNull(fragment.getError());
175 | }
176 |
177 | @SmallTest
178 | public void testNormalRunRotateTagged() {
179 | final SimpleMockActivity activity = new SimpleMockActivity();
180 | final SimpleMockFragment fragment = new SimpleMockFragment();
181 | activity.addFragment(fragment);
182 |
183 | activity.start();
184 | final int firstRunId = fragment.runSimpleTagged(INPUT);
185 | activity.stop();
186 | activity.start();
187 | final int secondRunId = fragment.runSimpleTagged(INPUT);
188 | assertTrue(firstRunId == secondRunId);
189 | sleep();
190 | assertTrue(fragment.getResultObtained() == 1);
191 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getResult()));
192 | assertNull(fragment.getError());
193 | }
194 |
195 | @SmallTest
196 | public void testCancelRunTaggedById() {
197 | final SimpleMockActivity activity = new SimpleMockActivity();
198 | final SimpleMockFragment fragment = new SimpleMockFragment();
199 | activity.addFragment(fragment);
200 |
201 | activity.start();
202 | final int runId = fragment.runSimpleTagged(INPUT);
203 | final boolean cancelResult = fragment.cancel(runId);
204 | assertTrue(cancelResult);
205 | sleep();
206 | assertFalse(fragment.gotResult());
207 | }
208 |
209 | @SmallTest
210 | public void testCancelRunTaggedByTag() {
211 | final SimpleMockActivity activity = new SimpleMockActivity();
212 | final SimpleMockFragment fragment = new SimpleMockFragment();
213 | activity.addFragment(fragment);
214 |
215 | activity.start();
216 | fragment.runSimpleTagged(INPUT);
217 | final boolean cancelResult = fragment.cancelTagged();
218 | assertTrue(cancelResult);
219 | sleep();
220 | assertFalse(fragment.gotResult());
221 | }
222 |
223 | @SmallTest
224 | public void testRelaunchCancelledTaggedRunByTag() {
225 | final SimpleMockActivity activity = new SimpleMockActivity();
226 | final SimpleMockFragment fragment = new SimpleMockFragment();
227 | activity.addFragment(fragment);
228 |
229 | activity.start();
230 | final int firstRunId = fragment.runSimpleTagged(INPUT);
231 | final boolean cancelResult = fragment.cancelTagged();
232 | assertTrue(cancelResult);
233 |
234 | final int secondRunId = fragment.runSimpleTagged(INPUT);
235 | assertTrue(firstRunId != secondRunId);
236 | sleep();
237 | assertTrue(fragment.getResultObtained() == 1);
238 | assertTrue(SimpleOperation.isTransform(INPUT, fragment.getResult()));
239 | assertNull(fragment.getError());
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/MemoryTest.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos;
2 |
3 | import com.redmadrobot.chronos.mock.gui.SampleHeavyActivity;
4 |
5 | import android.test.AndroidTestCase;
6 | import android.test.suitebuilder.annotation.MediumTest;
7 | import android.test.suitebuilder.annotation.SmallTest;
8 |
9 | import java.util.LinkedList;
10 | import java.util.List;
11 |
12 | import static com.redmadrobot.chronos.util.TimingUtils.sleep;
13 |
14 | /**
15 | * Test for proper memory management.
16 | *
17 | * @author maximefimov
18 | */
19 | public class MemoryTest extends AndroidTestCase {
20 |
21 | @SmallTest
22 | public void testSingleResultFits() {
23 | final SampleHeavyActivity activity = new SampleHeavyActivity();
24 | activity.start();
25 | activity.run();
26 | sleep();
27 | assertFalse(activity.isOutOfMemory());
28 | }
29 |
30 | @MediumTest
31 | public void testMultipleResultFits() {
32 | final List activities = new LinkedList<>();
33 | final int activityCount = 100;
34 | for (int i = 0; i < activityCount; i++) {
35 | activities.add(new SampleHeavyActivity());
36 | }
37 |
38 | for (final SampleHeavyActivity activity : activities) {
39 | activity.start();
40 | activity.run();
41 | sleep(TestSettings.SHORT_WAIT);
42 | activity.stop();
43 | }
44 |
45 | sleep();
46 |
47 | for (final SampleHeavyActivity activity : activities) {
48 | activity.start();
49 | assertFalse(activity.isOutOfMemory());
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/SetupTest.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos;
2 |
3 | import com.redmadrobot.chronos.mock.gui.MockActivity;
4 | import com.redmadrobot.chronos.mock.gui.MockFragment;
5 | import com.redmadrobot.chronos.mock.gui.SimpleMockActivity;
6 | import com.redmadrobot.chronos.mock.gui.SimpleMockFragment;
7 | import com.redmadrobot.chronos.mock.operation.SimpleOperation;
8 |
9 | import junit.framework.Assert;
10 |
11 | import android.test.AndroidTestCase;
12 | import android.test.suitebuilder.annotation.SmallTest;
13 |
14 | import static com.redmadrobot.chronos.TestSettings.INPUT;
15 |
16 | /**
17 | * Test for test equipment.
18 | *
19 | * @author maximefimov
20 | */
21 | public class SetupTest extends AndroidTestCase {
22 |
23 | @SmallTest
24 | public void testSimpleOperation() {
25 | final SimpleOperation operation = new SimpleOperation(INPUT);
26 | final String output = operation.run();
27 | Assert.assertTrue(SimpleOperation.isTransform(INPUT, output));
28 | }
29 |
30 | @SmallTest
31 | public void testActivityLifecycleNormal() {
32 | final MockActivity activity = new SimpleMockActivity();
33 |
34 | activity.start();
35 | activity.stop();
36 | activity.start();
37 | activity.stop();
38 | activity.start();
39 | }
40 |
41 | @SmallTest
42 | public void testActivityLifecycleInvalid1() {
43 | final MockActivity activity = new SimpleMockActivity();
44 |
45 | IllegalStateException exception = null;
46 | try {
47 | activity.stop();
48 | } catch (IllegalStateException e) {
49 | exception = e;
50 | }
51 | Assert.assertNotNull(exception);
52 | }
53 |
54 | @SmallTest
55 | public void testActivityLifecycleInvalid2() {
56 | final MockActivity activity = new SimpleMockActivity();
57 |
58 | IllegalStateException exception = null;
59 | try {
60 | activity.start();
61 | activity.start();
62 | } catch (IllegalStateException e) {
63 | exception = e;
64 | }
65 | Assert.assertNotNull(exception);
66 | }
67 |
68 | @SmallTest
69 | public void testActivityLifecycleInvalid3() {
70 | final MockActivity activity = new SimpleMockActivity();
71 |
72 | IllegalStateException exception = null;
73 | try {
74 | activity.start();
75 | activity.stop();
76 | activity.stop();
77 | } catch (IllegalStateException e) {
78 | exception = e;
79 | }
80 | Assert.assertNotNull(exception);
81 | }
82 |
83 | @SmallTest
84 | public void testActivityFragmentLifecycleNormal() {
85 | final MockActivity activity = new SimpleMockActivity();
86 | final MockFragment firstFragment = new SimpleMockFragment();
87 | final MockFragment secondFragment = new SimpleMockFragment();
88 | activity.addFragment(firstFragment);
89 | activity.addFragment(secondFragment);
90 |
91 | activity.start();
92 | activity.stop();
93 | activity.start();
94 | activity.stop();
95 | activity.start();
96 | }
97 |
98 | @SmallTest
99 | public void testActivityFragmentLifecycleInvalid1() {
100 | final MockActivity activity = new SimpleMockActivity();
101 | final MockFragment fragment = new SimpleMockFragment();
102 | activity.addFragment(fragment);
103 |
104 | IllegalStateException exception = null;
105 | try {
106 | activity.stop();
107 | } catch (IllegalStateException e) {
108 | exception = e;
109 | }
110 | Assert.assertNotNull(exception);
111 | }
112 |
113 | @SmallTest
114 | public void testActivityFragmentLifecycleInvalid2() {
115 | final MockActivity activity = new SimpleMockActivity();
116 | final MockFragment fragment = new SimpleMockFragment();
117 | activity.addFragment(fragment);
118 |
119 | IllegalStateException exception = null;
120 | try {
121 | activity.start();
122 | activity.start();
123 | } catch (IllegalStateException e) {
124 | exception = e;
125 | }
126 | Assert.assertNotNull(exception);
127 | }
128 |
129 | @SmallTest
130 | public void testActivityFragmentLifecycleInvalid3() {
131 | final MockActivity activity = new SimpleMockActivity();
132 | final MockFragment fragment = new SimpleMockFragment();
133 | activity.addFragment(fragment);
134 |
135 | IllegalStateException exception = null;
136 | try {
137 | activity.start();
138 | activity.stop();
139 | activity.stop();
140 | } catch (IllegalStateException e) {
141 | exception = e;
142 | }
143 | Assert.assertNotNull(exception);
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/TestSettings.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos;
2 |
3 | /**
4 | * Tests setup.
5 | *
6 | * @author maximefimov
7 | */
8 | public final class TestSettings {
9 |
10 | public final static long MICRO_WAIT = 10L;
11 |
12 | public final static long SHORT_WAIT = 50L;
13 |
14 | public final static long OPERATION_WAIT = 100L;
15 |
16 | public final static long RESPONSE_WAIT = 200L;
17 |
18 | public final static String INPUT = "test_input_string";
19 |
20 | private TestSettings() {
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/BigObject.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock;
2 |
3 | import org.jetbrains.annotations.Contract;
4 |
5 | import android.support.annotation.NonNull;
6 |
7 | /**
8 | * A mock class that represents a very memory-consuming object.
9 | *
10 | * @author maximefimov
11 | */
12 | public final class BigObject {
13 |
14 | private final static int LARGE_COUNT = 1_000_000_0;
15 |
16 | private final int[] mData;
17 |
18 | public BigObject() {
19 | mData = new int[LARGE_COUNT];
20 | }
21 |
22 | @NonNull
23 | @Contract(pure = true)
24 | @SuppressWarnings("unused")
25 | public int[] getData() {
26 | return mData;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/gui/MockActivity.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.gui;
2 |
3 | import com.redmadrobot.chronos.Chronos;
4 | import com.redmadrobot.chronos.ChronosConnector;
5 | import com.redmadrobot.chronos.ChronosOperation;
6 |
7 | import org.jetbrains.annotations.Contract;
8 |
9 | import android.os.Bundle;
10 | import android.support.annotation.NonNull;
11 |
12 | import java.util.LinkedList;
13 | import java.util.List;
14 |
15 | /**
16 | * Test class mocking activity behaviour.
17 | *
18 | * @author maximefimov
19 | */
20 | public abstract class MockActivity {
21 |
22 | /**
23 | * An entry point to access Chronos functions.
24 | */
25 | private final ChronosConnector mHelper = new ChronosConnector();
26 |
27 | private final List mMockFragments = new LinkedList<>();
28 |
29 | private Bundle mSavedInstanceState = null;
30 |
31 | private State mState = State.INSTANCED;
32 |
33 | public final void start() {
34 | onCreate();
35 | onResume();
36 | }
37 |
38 | public final void stop() {
39 | onSaveInstanceState();
40 | onPause();
41 | }
42 |
43 | public final void addFragment(@NonNull final MockFragment mockFragment) {
44 | if (mState == State.SAVED || mState == State.PAUSED) {
45 | throw new IllegalStateException("Wrong state: " + mState);
46 | }
47 | mockFragment.setMockActivity(this);
48 | mMockFragments.add(mockFragment);
49 | mockFragment.setState(mState);
50 | }
51 |
52 | protected void onCreate() {
53 | if (!(mState == State.INSTANCED || mState == State.PAUSED)) {
54 | throw new IllegalStateException("Wrong state: " + mState);
55 | }
56 | mState = State.CREATED;
57 | mHelper.onCreate(this, mSavedInstanceState);
58 | for (final MockFragment fragment : mMockFragments) {
59 | fragment.onCreate();
60 | }
61 | }
62 |
63 | protected void onResume() {
64 | if (mState != State.CREATED) {
65 | throw new IllegalStateException("Wrong state: " + mState);
66 | }
67 | mState = State.RESUMED;
68 | mHelper.onResume();
69 | for (final MockFragment fragment : mMockFragments) {
70 | fragment.onResume();
71 | }
72 | }
73 |
74 | protected void onSaveInstanceState() {
75 | if (mState != State.RESUMED) {
76 | throw new IllegalStateException("Wrong state: " + mState);
77 | }
78 | mState = State.SAVED;
79 | mSavedInstanceState = new Bundle();
80 | mHelper.onSaveInstanceState(mSavedInstanceState);
81 | for (final MockFragment fragment : mMockFragments) {
82 | fragment.onSaveInstanceState();
83 | }
84 | }
85 |
86 | protected void onPause() {
87 | if (mState != State.SAVED) {
88 | throw new IllegalStateException("Wrong state: " + mState);
89 | }
90 | mState = State.PAUSED;
91 | mHelper.onPause();
92 | for (final MockFragment fragment : mMockFragments) {
93 | fragment.onPause();
94 | }
95 | }
96 |
97 | /**
98 | * Runs an operation in a background thread. Only one operation with the given tag may run in a
99 | * single moment of time. The result will be delivered to {@link Chronos#OWN_CALLBACK_METHOD_NAME}
100 | * method. This method must have only one parameter of type {@link ChronosOperation#getResultClass()}
101 | * to receive a result.
102 | *
103 | * @param operation an operation to be run in background
104 | * @param tag value which prohibits running new operations with the same tag while there
105 | * is a running one
106 | * @return a unique launch id, may be the same with the previous run with the same tag, if the
107 | * operation is still running
108 | * @see #runOperation(ChronosOperation)
109 | * @see #runOperationBroadcast(ChronosOperation, String)
110 | * @see #cancelOperation(int)
111 | * @see #cancelOperation(String)
112 | */
113 | @SuppressWarnings("unused")
114 | protected final int runOperation(@NonNull final ChronosOperation operation,
115 | @NonNull final String tag) {
116 | return mHelper.runOperation(operation, tag, false);
117 | }
118 |
119 | /**
120 | * Runs an operation in a background thread. The result will be delivered to {@link
121 | * Chronos#OWN_CALLBACK_METHOD_NAME} method. This method must have only one parameter of type
122 | * {@link ChronosOperation#getResultClass()} to receive a result.
123 | *
124 | * @param operation an operation to be run in background
125 | * @return a unique launch id
126 | * @see #runOperation(ChronosOperation, String)
127 | * @see #runOperationBroadcast(ChronosOperation)
128 | * @see #cancelOperation(int)
129 | */
130 | @SuppressWarnings("unused")
131 | protected final int runOperation(@NonNull final ChronosOperation operation) {
132 | return mHelper.runOperation(operation, false);
133 | }
134 |
135 | /**
136 | * Runs an operation in a background thread, and broadcast it result when finished. Only one
137 | * operation with the given tag may run in a single moment of time. The result will be delivered
138 | * to {@link Chronos#OWN_CALLBACK_METHOD_NAME} method. All other Chronos clients will receive
139 | * the result in {@link Chronos#BROADCAST_CALLBACK_METHOD_NAME} method. Both method must have
140 | * only one parameter of type {@link ChronosOperation#getResultClass()} to receive a result.
141 | *
142 | * @param operation an operation to be run in background
143 | * @param tag value which prohibits running new operations with the same tag while there
144 | * is a running one
145 | * @return a unique launch id, may be the same with the previous run with the same tag, if the
146 | * operation is still running
147 | * @see #runOperationBroadcast(ChronosOperation)
148 | * @see #runOperation(ChronosOperation, String)
149 | * @see #cancelOperation(int)
150 | * @see #cancelOperation(String)
151 | */
152 | @SuppressWarnings("unused")
153 | protected final int runOperationBroadcast(@NonNull final ChronosOperation operation,
154 | @NonNull final String tag) {
155 | return mHelper.runOperation(operation, tag, true);
156 | }
157 |
158 | /**
159 | * Runs an operation in a background thread, and broadcast it result when finished. The result
160 | * will be delivered to {@link Chronos#OWN_CALLBACK_METHOD_NAME} method. All other Chronos
161 | * clients will receive the result in {@link Chronos#BROADCAST_CALLBACK_METHOD_NAME} method.
162 | * Both method must have only one parameter of type {@link ChronosOperation#getResultClass()} to
163 | * receive a result.
164 | *
165 | * @param operation an operation to be run in background
166 | * @return a unique launch id
167 | * @see #runOperation(ChronosOperation)
168 | * @see #runOperationBroadcast(ChronosOperation, String)
169 | * @see #cancelOperation(int)
170 | */
171 | @SuppressWarnings("unused")
172 | protected final int runOperationBroadcast(@NonNull final ChronosOperation operation) {
173 | return mHelper.runOperation(operation, true);
174 | }
175 |
176 | /**
177 | * Cancels a running operation by its launch id. It is not guaranteed that execution would be
178 | * interrupted immediately, however, no result would be delivered to the activity, or any other
179 | * Chronos clients, if it was a broadcast run.
180 | *
181 | * @param id id of launch, that needs to be cancelled
182 | * @return {@code false} if the task could not be cancelled, typically because it has already
183 | * completed normally; {@code true} otherwise
184 | * @see #cancelOperation(String)
185 | * @see #runOperation(ChronosOperation)
186 | * @see #runOperation(ChronosOperation, String)
187 | * @see #runOperationBroadcast(ChronosOperation)
188 | * @see #runOperationBroadcast(ChronosOperation, String)
189 | */
190 | @SuppressWarnings("unused")
191 | protected final boolean cancelOperation(final int id) {
192 | return mHelper.cancelOperation(id, true);
193 | }
194 |
195 | /**
196 | * Cancels a running operation by its tag. It is not guaranteed that execution would be
197 | * interrupted immediately, however, no result would be delivered to the activity, or any other
198 | * Chronos clients, if it was a broadcast run.
199 | *
200 | * @param tag a tag with the operation was launched
201 | * @return {@code false} if the task could not be cancelled, typically because it has already
202 | * completed normally or there is no running operation with a given tag; {@code true} otherwise
203 | * @see #cancelOperation(int)
204 | * @see #runOperation(ChronosOperation)
205 | * @see #runOperation(ChronosOperation, String)
206 | * @see #runOperationBroadcast(ChronosOperation)
207 | * @see #runOperationBroadcast(ChronosOperation, String)
208 | */
209 | @SuppressWarnings("unused")
210 | protected final boolean cancelOperation(@NonNull final String tag) {
211 | return mHelper.cancelOperation(tag, true);
212 | }
213 |
214 | /**
215 | * Checks if an operation with given launch id is running.
216 | *
217 | * @param id an id of the operation launch
218 | * @return {@code true} if the operation is running, {@code false} otherwise
219 | */
220 | @SuppressWarnings("unused")
221 | @Contract(pure = true)
222 | public final boolean isOperationRunning(final int id) {
223 | return mHelper.isOperationRunning(id);
224 | }
225 |
226 | /**
227 | * Checks if an operation with given launch tag is running.
228 | *
229 | * @param tag a pre-cache key of the operation launch
230 | * @return {@code true} if the operation is running, {@code false} if it is not running, or
231 | * there was no operation launch with the tag at all
232 | */
233 | @SuppressWarnings("unused")
234 | @Contract(pure = true)
235 | public final boolean isOperationRunning(@NonNull final String tag) {
236 | return mHelper.isOperationRunning(tag);
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/gui/MockFragment.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.gui;
2 |
3 | import com.redmadrobot.chronos.Chronos;
4 | import com.redmadrobot.chronos.ChronosConnector;
5 | import com.redmadrobot.chronos.ChronosOperation;
6 |
7 | import org.jetbrains.annotations.Contract;
8 |
9 | import android.os.Bundle;
10 | import android.support.annotation.NonNull;
11 | import android.support.annotation.Nullable;
12 |
13 | /**
14 | * Test class mocking fragment behaviour.
15 | *
16 | * @author maximefimov
17 | */
18 | public abstract class MockFragment {
19 |
20 | private State mState = State.INSTANCED;
21 |
22 | private MockActivity mMockActivity;
23 |
24 | @Nullable
25 | @Contract(pure = true)
26 | public final MockActivity getMockActivity() {
27 | return mMockActivity;
28 | }
29 |
30 | public final void setMockActivity(@Nullable final MockActivity mockActivity) {
31 | if (mMockActivity != null) {
32 | throw new IllegalStateException("Activity has already been set.");
33 | }
34 | mMockActivity = mockActivity;
35 | }
36 |
37 | private final ChronosConnector mHelper = new ChronosConnector();
38 |
39 | private Bundle mSavedInstanceState = null;
40 |
41 | public void setState(final @NonNull State state) {
42 | mState = state;
43 | }
44 |
45 | public void onCreate() {
46 | if (!(mState == State.INSTANCED || mState == State.PAUSED)) {
47 | throw new IllegalStateException("Wrong state: " + mState);
48 | }
49 | mState = State.CREATED;
50 | mHelper.onCreate(this, mSavedInstanceState);
51 | }
52 |
53 | public void onResume() {
54 | if (mState != State.CREATED) {
55 | throw new IllegalStateException("Wrong state: " + mState);
56 | }
57 | mState = State.RESUMED;
58 | mHelper.onResume();
59 | }
60 |
61 | public void onSaveInstanceState() {
62 | if (mState != State.RESUMED) {
63 | throw new IllegalStateException("Wrong state: " + mState);
64 | }
65 | mState = State.SAVED;
66 | mSavedInstanceState = new Bundle();
67 | mHelper.onSaveInstanceState(mSavedInstanceState);
68 | }
69 |
70 | public void onPause() {
71 | if (mState != State.SAVED) {
72 | throw new IllegalStateException("Wrong state: " + mState);
73 | }
74 | mState = State.PAUSED;
75 | mHelper.onPause();
76 | }
77 |
78 | /**
79 | * Runs an operation in a background thread. Only one operation with the given tag may run in a
80 | * single moment of time. The result will be delivered to {@link Chronos#OWN_CALLBACK_METHOD_NAME}
81 | * method. This method must have only one parameter of type {@link ChronosOperation#getResultClass()}
82 | * to receive a result.
83 | *
84 | * @param operation an operation to be run in background
85 | * @param tag value which prohibits running new operations with the same tag while there
86 | * is a running one
87 | * @return a unique launch id, may be the same with the previous run with the same tag, if the
88 | * operation is still running
89 | * @see #runOperation(ChronosOperation)
90 | * @see #runOperationBroadcast(ChronosOperation, String)
91 | * @see #cancelOperation(int)
92 | * @see #cancelOperation(String)
93 | */
94 | @SuppressWarnings("unused")
95 | protected final int runOperation(@NonNull final ChronosOperation operation,
96 | @NonNull final String tag) {
97 | return mHelper.runOperation(operation, tag, false);
98 | }
99 |
100 | /**
101 | * Runs an operation in a background thread. The result will be delivered to {@link
102 | * Chronos#OWN_CALLBACK_METHOD_NAME} method. This method must have only one parameter
103 | * of type {@link ChronosOperation#getResultClass()} to receive a result.
104 | *
105 | * @param operation an operation to be run in background
106 | * @return a unique launch id
107 | * @see #runOperation(ChronosOperation, String)
108 | * @see #runOperationBroadcast(ChronosOperation)
109 | * @see #cancelOperation(int)
110 | */
111 | @SuppressWarnings("unused")
112 | protected final int runOperation(@NonNull final ChronosOperation operation) {
113 | return mHelper.runOperation(operation, false);
114 | }
115 |
116 | /**
117 | * Runs an operation in a background thread, and broadcast it result when finished. Only one
118 | * operation with the given tag may run in a single moment of time. The result will be delivered
119 | * to {@link Chronos#OWN_CALLBACK_METHOD_NAME} method. All other Chronos clients will
120 | * receive the result in {@link Chronos#BROADCAST_CALLBACK_METHOD_NAME} method. Both
121 | * method must have only one parameter of type {@link ChronosOperation#getResultClass()} to receive a
122 | * result.
123 | *
124 | * @param operation an operation to be run in background
125 | * @param tag value which prohibits running new operations with the same tag while there
126 | * is a running one
127 | * @return a unique launch id, may be the same with the previous run with the same tag, if the
128 | * operation is still running
129 | * @see #runOperationBroadcast(ChronosOperation)
130 | * @see #runOperation(ChronosOperation, String)
131 | * @see #cancelOperation(int)
132 | * @see #cancelOperation(String)
133 | */
134 | @SuppressWarnings("unused")
135 | protected final int runOperationBroadcast(@NonNull final ChronosOperation operation,
136 | @NonNull final String tag) {
137 | return mHelper.runOperation(operation, tag, true);
138 | }
139 |
140 | /**
141 | * Runs an operation in a background thread, and broadcast it result when finished. The result
142 | * will be delivered to {@link Chronos#OWN_CALLBACK_METHOD_NAME} method. All other
143 | * Chronos clients will receive the result in {@link Chronos#BROADCAST_CALLBACK_METHOD_NAME}
144 | * method. Both method must have only one parameter of type {@link ChronosOperation#getResultClass()}
145 | * to receive a result.
146 | *
147 | * @param operation an operation to be run in background
148 | * @return a unique launch id
149 | * @see #runOperation(ChronosOperation)
150 | * @see #runOperationBroadcast(ChronosOperation, String)
151 | * @see #cancelOperation(int)
152 | */
153 | @SuppressWarnings("unused")
154 | protected final int runOperationBroadcast(@NonNull final ChronosOperation operation) {
155 | return mHelper.runOperation(operation, true);
156 | }
157 |
158 | /**
159 | * Cancels a running operation by its launch id. It is not guaranteed that execution would be
160 | * interrupted immediately, however, no result would be delivered to the fragment, or any other
161 | * Chronos clients, if it was a broadcast run.
162 | *
163 | * @param id id of launch, that needs to be cancelled
164 | * @return {@code false} if the task could not be cancelled, typically because it has already
165 | * completed normally; {@code true} otherwise
166 | * @see #cancelOperation(String)
167 | * @see #runOperation(ChronosOperation)
168 | * @see #runOperation(ChronosOperation, String)
169 | * @see #runOperationBroadcast(ChronosOperation)
170 | * @see #runOperationBroadcast(ChronosOperation, String)
171 | */
172 | @SuppressWarnings("unused")
173 | protected final boolean cancelOperation(final int id) {
174 | return mHelper.cancelOperation(id, true);
175 | }
176 |
177 | /**
178 | * Cancels a running operation by its tag. It is not guaranteed that execution would be
179 | * interrupted immediately, however, no result would be delivered to the fragment, or any other
180 | * Chronos clients, if it was a broadcast run.
181 | *
182 | * @param tag a tag with the operation was launched
183 | * @return {@code false} if the task could not be cancelled, typically because it has already
184 | * completed normally or there is no running operation with a given tag; {@code true} otherwise
185 | * @see #cancelOperation(int)
186 | * @see #runOperation(ChronosOperation)
187 | * @see #runOperation(ChronosOperation, String)
188 | * @see #runOperationBroadcast(ChronosOperation)
189 | * @see #runOperationBroadcast(ChronosOperation, String)
190 | */
191 | @SuppressWarnings("unused")
192 | protected final boolean cancelOperation(@NonNull final String tag) {
193 | return mHelper.cancelOperation(tag, true);
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/gui/SampleHeavyActivity.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.gui;
2 |
3 | import com.redmadrobot.chronos.mock.operation.HeavyOperation;
4 | import com.redmadrobot.chronos.mock.operation.HeavyOperationResult;
5 |
6 | import org.jetbrains.annotations.Contract;
7 |
8 | /**
9 | * Mock activity that does memory-consuming operations.
10 | *
11 | * @author maximefimov
12 | */
13 | public final class SampleHeavyActivity extends MockActivity {
14 |
15 | private boolean isOutOfMemory = false;
16 |
17 | @Contract(pure = true)
18 | public boolean isOutOfMemory() {
19 | return isOutOfMemory;
20 | }
21 |
22 | public final int run() {
23 | return runOperation(new HeavyOperation());
24 | }
25 |
26 | @SuppressWarnings("UnusedDeclaration")
27 | public final void onOperationFinished(final HeavyOperationResult result) {
28 | isOutOfMemory = ((HeavyOperation) result.getOperation()).gotOutOfMemory();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/gui/SimpleMockActivity.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.gui;
2 |
3 | import com.redmadrobot.chronos.mock.operation.SimpleErrorOperation;
4 | import com.redmadrobot.chronos.mock.operation.SimpleOperation;
5 | import com.redmadrobot.chronos.mock.operation.SimpleOperationResult;
6 |
7 | import org.jetbrains.annotations.Contract;
8 |
9 | import android.support.annotation.NonNull;
10 | import android.support.annotation.Nullable;
11 |
12 | /**
13 | * Activity that can do a pre-defined operations and report its status.
14 | *
15 | * @author maximefimov
16 | */
17 | public final class SimpleMockActivity extends MockActivity {
18 |
19 | private final static String OPERATION_TAG = "activity_operation_tag";
20 |
21 | private String mResult;
22 |
23 | private Exception mError;
24 |
25 | private String mBroadcastResult;
26 |
27 | private Exception mBroadcastError;
28 |
29 | private int mResultObtained = 0;
30 |
31 | private int mBroadcastResultObtained = 0;
32 |
33 | @Nullable
34 | public String getResult() {
35 | return mResult;
36 | }
37 |
38 | @Nullable
39 | public Exception getError() {
40 | return mError;
41 | }
42 |
43 | @Nullable
44 | public String getBroadcastResult() {
45 | return mBroadcastResult;
46 | }
47 |
48 | @Nullable
49 | public Exception getBroadcastError() {
50 | return mBroadcastError;
51 | }
52 |
53 | public int getBroadcastResultObtained() {
54 | return mBroadcastResultObtained;
55 | }
56 |
57 | public final int runSimple(@NonNull final String input) {
58 | return runOperation(new SimpleOperation(input));
59 | }
60 |
61 | public final int runBroadcast(@NonNull final String input) {
62 | return runOperationBroadcast(new SimpleOperation(input));
63 | }
64 |
65 | public final int runSimpleTagged(@NonNull final String input) {
66 | return runOperation(new SimpleOperation(input), OPERATION_TAG);
67 | }
68 |
69 | public final int runBroadcastTagged(@NonNull final String input) {
70 | return runOperationBroadcast(new SimpleOperation(input), OPERATION_TAG);
71 | }
72 |
73 | public final int runErrorSimple() {
74 | return runOperation(new SimpleErrorOperation());
75 | }
76 |
77 | public final int runErrorBroadcast() {
78 | return runOperationBroadcast(new SimpleErrorOperation());
79 | }
80 |
81 | public final boolean cancel(final int id) {
82 | return cancelOperation(id);
83 | }
84 |
85 | public final boolean cancelTagged() {
86 | return cancelOperation(OPERATION_TAG);
87 | }
88 |
89 | public final boolean isRunning(final int id) {
90 | return isOperationRunning(id);
91 | }
92 |
93 | public final boolean isRunningTagged() {
94 | return isOperationRunning(OPERATION_TAG);
95 | }
96 |
97 | public final int getResultObtained() {
98 | return mResultObtained;
99 | }
100 |
101 | @Contract(pure = true)
102 | public final boolean gotResult() {
103 | return mResultObtained > 0;
104 | }
105 |
106 | @Contract(pure = true)
107 | public final boolean gotBroadcastResult() {
108 | return mBroadcastResultObtained > 0;
109 | }
110 |
111 | @SuppressWarnings("UnusedDeclaration")
112 | public final void onOperationFinished(final SimpleOperationResult result) {
113 | mResultObtained++;
114 | if (result.isSuccessful()) {
115 | mResult = result.getOutput();
116 | } else {
117 | mError = result.getException();
118 | }
119 | }
120 |
121 | @SuppressWarnings("UnusedDeclaration")
122 | public final void onBroadcastOperationFinished(final SimpleOperationResult result) {
123 | mBroadcastResultObtained++;
124 | if (result.isSuccessful()) {
125 | mBroadcastResult = result.getOutput();
126 | } else {
127 | mBroadcastError = result.getException();
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/gui/SimpleMockFragment.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.gui;
2 |
3 | import com.redmadrobot.chronos.mock.operation.SimpleErrorOperation;
4 | import com.redmadrobot.chronos.mock.operation.SimpleOperation;
5 | import com.redmadrobot.chronos.mock.operation.SimpleOperationResult;
6 |
7 | import org.jetbrains.annotations.Contract;
8 |
9 | import android.support.annotation.NonNull;
10 | import android.support.annotation.Nullable;
11 |
12 | /**
13 | * Fragment that can do a pre-defined operations and report its status.
14 | *
15 | * @author maximefimov
16 | */
17 | public final class SimpleMockFragment extends MockFragment {
18 |
19 | private final static String OPERATION_TAG = "fragment_operation_tag";
20 |
21 | private String mResult;
22 |
23 | private Exception mError;
24 |
25 | private String mBroadcastResult;
26 |
27 | private Exception mBroadcastError;
28 |
29 | private int mResultObtained = 0;
30 |
31 | private int mBroadcastResultObtained = 0;
32 |
33 | @Nullable
34 | public String getResult() {
35 | return mResult;
36 | }
37 |
38 | @Nullable
39 | public Exception getError() {
40 | return mError;
41 | }
42 |
43 | @Nullable
44 | public String getBroadcastResult() {
45 | return mBroadcastResult;
46 | }
47 |
48 | @Nullable
49 | public Exception getBroadcastError() {
50 | return mBroadcastError;
51 | }
52 |
53 | public int getBroadcastResultObtained() {
54 | return mBroadcastResultObtained;
55 | }
56 |
57 | public final int runSimple(@NonNull final String input) {
58 | return runOperation(new SimpleOperation(input));
59 | }
60 |
61 | public final int runBroadcast(@NonNull final String input) {
62 | return runOperationBroadcast(new SimpleOperation(input));
63 | }
64 |
65 | public final int runSimpleTagged(@NonNull final String input) {
66 | return runOperation(new SimpleOperation(input), OPERATION_TAG);
67 | }
68 |
69 | public final int runBroadcastTagged(@NonNull final String input) {
70 | return runOperationBroadcast(new SimpleOperation(input), OPERATION_TAG);
71 | }
72 |
73 | public final int runErrorSimple() {
74 | return runOperation(new SimpleErrorOperation());
75 | }
76 |
77 | public final int runErrorBroadcast() {
78 | return runOperationBroadcast(new SimpleErrorOperation());
79 | }
80 |
81 | public final boolean cancel(final int id) {
82 | return cancelOperation(id);
83 | }
84 |
85 | public final boolean cancelTagged() {
86 | return cancelOperation(OPERATION_TAG);
87 | }
88 |
89 | public final int getResultObtained() {
90 | return mResultObtained;
91 | }
92 |
93 | @Contract(pure = true)
94 | public final boolean gotResult() {
95 | return mResultObtained > 0;
96 | }
97 |
98 | @Contract(pure = true)
99 | public final boolean gotBroadcastResult() {
100 | return mBroadcastResultObtained > 0;
101 | }
102 |
103 | @SuppressWarnings("UnusedDeclaration")
104 | public final void onOperationFinished(final SimpleOperationResult result) {
105 | mResultObtained++;
106 | if (result.isSuccessful()) {
107 | mResult = result.getOutput();
108 | } else {
109 | mError = result.getException();
110 | }
111 | }
112 |
113 | @SuppressWarnings("UnusedDeclaration")
114 | public final void onBroadcastOperationFinished(final SimpleOperationResult result) {
115 | mBroadcastResultObtained++;
116 | if (result.isSuccessful()) {
117 | mBroadcastResult = result.getOutput();
118 | } else {
119 | mBroadcastError = result.getException();
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/gui/State.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.gui;
2 |
3 | /**
4 | * Mock of Android Activity and Fragment states.
5 | *
6 | * @author maximefimov
7 | */
8 | enum State {
9 | INSTANCED,
10 | CREATED,
11 | RESUMED,
12 | SAVED,
13 | PAUSED
14 | }
15 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/operation/HeavyOperation.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.operation;
2 |
3 | import com.redmadrobot.chronos.ChronosOperation;
4 | import com.redmadrobot.chronos.ChronosOperationResult;
5 | import com.redmadrobot.chronos.TestSettings;
6 | import com.redmadrobot.chronos.mock.BigObject;
7 |
8 | import org.jetbrains.annotations.Contract;
9 |
10 | import android.support.annotation.NonNull;
11 | import android.support.annotation.Nullable;
12 |
13 | import static com.redmadrobot.chronos.util.TimingUtils.sleep;
14 |
15 | /**
16 | * An operation that generates some very heavy result.
17 | *
18 | * @author maximefimov
19 | */
20 | public final class HeavyOperation extends ChronosOperation {
21 |
22 | private boolean hasOutOfMemory = false;
23 |
24 | @Contract(pure = true)
25 | public final boolean gotOutOfMemory() {
26 | return hasOutOfMemory;
27 | }
28 |
29 | @Nullable
30 | @Override
31 | public BigObject run() {
32 | sleep(TestSettings.OPERATION_WAIT);
33 | BigObject result = null;
34 | try {
35 | result = new BigObject();
36 | } catch (OutOfMemoryError error) {
37 | hasOutOfMemory = true;
38 | }
39 | return result;
40 | }
41 |
42 | @NonNull
43 | @Override
44 | public Class extends ChronosOperationResult> getResultClass() {
45 | return HeavyOperationResult.class;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/operation/HeavyOperationResult.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.operation;
2 |
3 | import com.redmadrobot.chronos.ChronosOperationResult;
4 | import com.redmadrobot.chronos.mock.BigObject;
5 |
6 | /**
7 | * Result class for test heavy operation.
8 | *
9 | * @author maximefimov
10 | */
11 | public final class HeavyOperationResult extends ChronosOperationResult {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/operation/SimpleErrorOperation.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.operation;
2 |
3 | import com.redmadrobot.chronos.ChronosOperation;
4 | import com.redmadrobot.chronos.ChronosOperationResult;
5 | import com.redmadrobot.chronos.TestSettings;
6 |
7 | import org.jetbrains.annotations.Contract;
8 |
9 | import android.support.annotation.NonNull;
10 | import android.support.annotation.Nullable;
11 |
12 | import static com.redmadrobot.chronos.util.TimingUtils.sleep;
13 |
14 | /**
15 | * Operation that always throw an exception during its {@code run()} method.
16 | *
17 | * @author maximefimov
18 | */
19 | public final class SimpleErrorOperation extends ChronosOperation {
20 |
21 | private final static RuntimeException EXCEPTION = new RuntimeException("Test exception");
22 |
23 | @Contract("null -> false")
24 | public static boolean isExpectedException(@Nullable final Exception exception) {
25 | return exception != null && exception.equals(EXCEPTION);
26 | }
27 |
28 | @Nullable
29 | @Override
30 | public String run() {
31 | sleep(TestSettings.OPERATION_WAIT);
32 | throw EXCEPTION;
33 | }
34 |
35 | @NonNull
36 | @Override
37 | public Class extends ChronosOperationResult> getResultClass() {
38 | return SimpleOperationResult.class;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/operation/SimpleOperation.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.operation;
2 |
3 | import com.redmadrobot.chronos.ChronosOperation;
4 | import com.redmadrobot.chronos.ChronosOperationResult;
5 | import com.redmadrobot.chronos.TestSettings;
6 |
7 | import android.support.annotation.NonNull;
8 | import android.support.annotation.Nullable;
9 |
10 | import static com.redmadrobot.chronos.util.TimingUtils.sleep;
11 |
12 | /**
13 | * Operation that converts one string to another.
14 | *
15 | * @author maximefimov
16 | */
17 | public final class SimpleOperation extends ChronosOperation {
18 |
19 | private final String mInput;
20 |
21 | public SimpleOperation(@NonNull final String input) {
22 | mInput = input;
23 | }
24 |
25 | @Nullable
26 | @Override
27 | public String run() {
28 | final String result = transform(mInput);
29 | sleep(TestSettings.OPERATION_WAIT);
30 | return result;
31 | }
32 |
33 | public static boolean isTransform(@NonNull final String input, @Nullable final String output) {
34 | return output != null && transform(input).equals(output);
35 | }
36 |
37 | @NonNull
38 | private static String transform(@NonNull final String input) {
39 | return input.concat(input);
40 | }
41 |
42 | @NonNull
43 | @Override
44 | public Class extends ChronosOperationResult> getResultClass() {
45 | return SimpleOperationResult.class;
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/mock/operation/SimpleOperationResult.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.mock.operation;
2 |
3 | import com.redmadrobot.chronos.ChronosOperationResult;
4 |
5 | /**
6 | * Result class for test operations.
7 | *
8 | * @author maximefimov
9 | */
10 | public final class SimpleOperationResult extends ChronosOperationResult {
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/chronos/src/androidTest/java/com/redmadrobot/chronos/util/TimingUtils.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos.util;
2 |
3 | import com.redmadrobot.chronos.TestSettings;
4 |
5 | /**
6 | * Utilities to mock waiting for long running tasks.
7 | *
8 | * @author maximefimov
9 | */
10 | public final class TimingUtils {
11 |
12 | private TimingUtils() {
13 | }
14 |
15 | /**
16 | * Current thread sleeps for a predefined amount of time. If it has been interrupted, the method
17 | * would be finished and no exception is thrown.
18 | */
19 | public static void sleep() {
20 | try {
21 | Thread.sleep(TestSettings.RESPONSE_WAIT);
22 | } catch (InterruptedException e) {
23 | //ignore it
24 | }
25 | }
26 |
27 | /**
28 | * Current thread sleeps for {@code mills} ms. If it has been interrupted, the method would be
29 | * finished and no exception is thrown.
30 | *
31 | * @param mills time to sleep
32 | */
33 | public static void sleep(final long mills) {
34 | try {
35 | Thread.sleep(mills);
36 | } catch (InterruptedException e) {
37 | //ignore it
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/chronos/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/chronos/src/main/java/com/redmadrobot/chronos/Chronos.java:
--------------------------------------------------------------------------------
1 | package com.redmadrobot.chronos;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | /**
6 | * Class, which provides a static access to the Chronos library.
7 | *
8 | * @author maximefimov
9 | */
10 | public final class Chronos {
11 |
12 | @SuppressWarnings("WeakerAccess")
13 | @NonNull
14 | public final static String OWN_CALLBACK_METHOD_NAME = "onOperationFinished";
15 |
16 | @SuppressWarnings("WeakerAccess")
17 | @NonNull
18 | public final static String BROADCAST_CALLBACK_METHOD_NAME = "onBroadcastOperationFinished";
19 |
20 | private Chronos() {
21 | }
22 |
23 | /**
24 | * Cancels all running operations for all objects.
25 | *
26 | * @param mayInterrupt {@code true} if threads executing operations task should be interrupted;
27 | * otherwise, in-progress tasks are allowed to complete
28 | */
29 | public static void cancelAll(final boolean mayInterrupt) {
30 | RunningOperationStorage.getInstance().cancelAll(mayInterrupt);
31 | }
32 |
33 | /**
34 | * Runs operation synchronously.
35 | *
36 | * @param operation Operation to be executed.
37 | * @param