├── examplelib
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ └── AndroidManifest.xml
│ └── test
│ │ └── java
│ │ └── de
│ │ └── mobilej
│ │ └── examplelib
│ │ └── SimpleTest.java
├── proguard-rules.pro
└── build.gradle
├── gradle.properties
├── example
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── 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
│ │ │ │ └── dimens.xml
│ │ │ └── layout
│ │ │ │ └── activity_main.xml
│ │ ├── java
│ │ │ └── de
│ │ │ │ └── mobilej
│ │ │ │ └── testproject
│ │ │ │ ├── AsyncTaskSubclass.java
│ │ │ │ └── MainActivity.java
│ │ └── AndroidManifest.xml
│ └── test
│ │ └── java
│ │ └── de
│ │ └── mobilej
│ │ └── testproject
│ │ ├── RenamedClassNeededTest.java
│ │ ├── DelegateClassWithFloatTest.java
│ │ ├── DelegatedClassTest.java
│ │ ├── AutoDelegateNativeMethodToABridgeTest.java
│ │ ├── SimpleTest.java
│ │ ├── ComplexSetupNeededTest.java
│ │ └── ParcelTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradlew.bat
├── README.md
├── gradlew
└── LICENSE.txt
/examplelib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.parallel=true
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | local.properties
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':example', ':examplelib'
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bjoernQ/unmock-plugin/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /.idea/workspace.xml
3 | /.idea/libraries
4 | .idea
5 | .DS_Store
6 | build
7 | *.iml
8 | local.properties
--------------------------------------------------------------------------------
/examplelib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Example Lib
3 |
4 |
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bjoernQ/unmock-plugin/HEAD/example/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bjoernQ/unmock-plugin/HEAD/example/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bjoernQ/unmock-plugin/HEAD/example/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bjoernQ/unmock-plugin/HEAD/example/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | TestProject
3 |
4 | Hello world!
5 |
6 |
--------------------------------------------------------------------------------
/example/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/examplelib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/example/src/main/java/de/mobilej/testproject/AsyncTaskSubclass.java:
--------------------------------------------------------------------------------
1 | package de.mobilej.testproject;
2 |
3 | import android.os.AsyncTask;
4 | import android.util.Log;
5 |
6 |
7 | /**
8 | * A subclass of AsyncTask
9 | *
{
13 | @Override
14 | protected Void doInBackground(Void... params) {
15 | Log.d("XXX", "doInBackground");
16 | return null;
17 | }
18 |
19 | @Override
20 | protected void onPostExecute(Void aVoid) {
21 | Log.d("XXX", "onPostExecute");
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/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/bjorn/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 |
--------------------------------------------------------------------------------
/examplelib/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/bjoernquentin/Library/Android/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 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/example/src/test/java/de/mobilej/testproject/RenamedClassNeededTest.java:
--------------------------------------------------------------------------------
1 | package de.mobilej.testproject;
2 |
3 | import android.net.Uri;
4 |
5 | import org.junit.Test;
6 |
7 | import static org.junit.Assert.assertEquals;
8 |
9 | /**
10 | * Makes sure that renaming a class works.
11 | *
12 | * Here we test android.net.Uri which depends on java.nio.charset.Charsets internally.
13 | * This class isn't part of Java SE so we need to get it from the real Android.jar.
14 | * However since it's located in the Java package we cannot load it from the regular classpath.
15 | * See the build.gradle of this example to see how java.nio.charset.Charsets is renamed.
16 | *
17 | * Created by bjoernquentin on 02.06.15.
18 | */
19 | public class RenamedClassNeededTest {
20 |
21 | @Test
22 | public void testUri() throws Exception {
23 | Uri uri = Uri.parse("http://www.google.de?q=Unmock+Plugin");
24 |
25 | assertEquals("Unmock Plugin", uri.getQueryParameter("q"));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/example/src/main/java/de/mobilej/testproject/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Björn Quentin
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package de.mobilej.testproject;
18 |
19 | import android.app.Activity;
20 | import android.os.Bundle;
21 |
22 |
23 | public class MainActivity extends Activity {
24 |
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.activity_main);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/example/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
21 |
22 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/example/src/test/java/de/mobilej/testproject/DelegateClassWithFloatTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Björn Quentin
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package de.mobilej.testproject;
17 |
18 | import android.hardware.Sensor;
19 |
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.powermock.core.classloader.annotations.PrepareForTest;
23 | import org.powermock.modules.junit4.PowerMockRunner;
24 | import org.powermock.reflect.Whitebox;
25 |
26 | import de.mobilej.ABridge;
27 |
28 | import static junit.framework.Assert.assertEquals;
29 | import static org.mockito.Matchers.any;
30 | import static org.mockito.Matchers.eq;
31 | import static org.powermock.api.mockito.PowerMockito.mockStatic;
32 | import static org.powermock.api.mockito.PowerMockito.when;
33 |
34 | /**
35 | * Tests that callFloat is invoked in ABridge
36 | * Created by bjoern on 01.06.2016.
37 | */
38 | @RunWith(PowerMockRunner.class)
39 | @PrepareForTest(ABridge.class)
40 | public class DelegateClassWithFloatTest {
41 |
42 | @Test
43 | public void testCallFloat() throws Exception {
44 | Sensor sensor = Whitebox.newInstance(Sensor.class);
45 |
46 | mockStatic(ABridge.class);
47 | when(ABridge.callFloat(eq("android.hardware.Sensor.getPower()"), any(Object.class), any(Object[].class))).thenReturn(42f);
48 |
49 | assertEquals(42f, sensor.getPower(), 0f);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/example/src/test/java/de/mobilej/testproject/DelegatedClassTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Björn Quentin
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package de.mobilej.testproject;
17 |
18 | import android.content.res.Resources;
19 |
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.mockito.invocation.InvocationOnMock;
23 | import org.mockito.stubbing.Answer;
24 | import org.powermock.core.classloader.annotations.PrepareForTest;
25 | import org.powermock.modules.junit4.PowerMockRunner;
26 |
27 | import de.mobilej.ABridge;
28 |
29 | import static junit.framework.Assert.assertTrue;
30 | import static org.mockito.Matchers.any;
31 | import static org.mockito.Matchers.anyObject;
32 | import static org.mockito.Matchers.eq;
33 | import static org.powermock.api.mockito.PowerMockito.doAnswer;
34 | import static org.powermock.api.mockito.PowerMockito.mockStatic;
35 |
36 | /**
37 | * Makes sure that delegating all methods of a class works.
38 | *
39 | * Here we test a subclass of android.os.AsyncTask.
40 | *
41 | * Created by bjoern on 14.05.2016.
42 | */
43 | @RunWith(PowerMockRunner.class)
44 | @PrepareForTest({Resources.class, ABridge.class})
45 | public class DelegatedClassTest {
46 |
47 | @Test
48 | public void testDelegateClass() throws Exception {
49 | mockStatic(ABridge.class);
50 |
51 | final boolean[] called = new boolean[]{false};
52 | doAnswer(new Answer() {
53 | @Override
54 | public Object answer(InvocationOnMock invocation) throws Throwable {
55 | called[0] = true;
56 | return null;
57 | }
58 | }).when(ABridge.class, "callObject", eq("android.os.AsyncTask.execute(java.lang.Object[])"), anyObject(), any(Object[].class));
59 |
60 | AsyncTaskSubclass sut = new AsyncTaskSubclass();
61 | sut.execute();
62 |
63 | assertTrue(called[0]);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/example/src/test/java/de/mobilej/testproject/AutoDelegateNativeMethodToABridgeTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Björn Quentin
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | package de.mobilej.testproject;
17 |
18 | import android.os.Parcel;
19 |
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.powermock.core.classloader.annotations.PrepareForTest;
23 | import org.powermock.modules.junit4.PowerMockRunner;
24 |
25 | import de.mobilej.ABridge;
26 |
27 | import static junit.framework.Assert.assertEquals;
28 | import static org.mockito.Matchers.any;
29 | import static org.mockito.Matchers.eq;
30 | import static org.powermock.api.mockito.PowerMockito.mockStatic;
31 | import static org.powermock.api.mockito.PowerMockito.when;
32 |
33 | /**
34 | * Tests that native methods are correctly delegated to ABridge.
35 | *
36 | * Created by bjoern on 01.06.2016.
37 | */
38 | @RunWith(PowerMockRunner.class)
39 | @PrepareForTest(ABridge.class)
40 | public class AutoDelegateNativeMethodToABridgeTest {
41 |
42 | @Test
43 | public void testCallIntDelegation() throws Exception {
44 | Parcel p = Parcel.obtain();
45 | mockStatic(ABridge.class);
46 | when(ABridge.callInt(eq("android.os.Parcel.nativeReadInt(long)"), any(Object.class), any(Object[].class))).thenReturn(42);
47 | assertEquals(42, p.readInt());
48 | }
49 |
50 | @Test
51 | public void testCallLongDelegation() throws Exception {
52 | Parcel p = Parcel.obtain();
53 | mockStatic(ABridge.class);
54 | when(ABridge.callLong(eq("android.os.Parcel.nativeReadLong(long)"), any(Object.class), any(Object[].class))).thenReturn(42L);
55 | assertEquals(42L, p.readLong());
56 | }
57 |
58 | @Test
59 | public void testCallFloatDelegation() throws Exception {
60 | Parcel p = Parcel.obtain();
61 | mockStatic(ABridge.class);
62 | when(ABridge.callFloat(eq("android.os.Parcel.nativeReadFloat(long)"), any(Object.class), any(Object[].class))).thenReturn(42f);
63 | assertEquals(42f, p.readFloat(), 0f);
64 | }
65 |
66 | @Test
67 | public void testCallDoubleDelegation() throws Exception {
68 | Parcel p = Parcel.obtain();
69 | mockStatic(ABridge.class);
70 | when(ABridge.callDouble(eq("android.os.Parcel.nativeReadDouble(long)"), any(Object.class), any(Object[].class))).thenReturn(42d);
71 | assertEquals(42d, p.readDouble(), 0d);
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/examplelib/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Björn Quentin
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | apply plugin: 'com.android.library'
18 | apply plugin: 'de.mobilej.unmock'
19 |
20 |
21 | android {
22 | compileSdkVersion 28
23 | buildToolsVersion '28.0.3'
24 | namespace "de.mobilej.examplelib"
25 |
26 | defaultConfig {
27 | minSdkVersion 24
28 | targetSdkVersion 28
29 | versionCode 1
30 | versionName "1.0"
31 | }
32 | buildTypes {
33 | release {
34 | minifyEnabled false
35 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
36 | }
37 | }
38 | }
39 |
40 | // this time no config closure for the unmock plugin - use the defaults
41 |
42 | dependencies {
43 | implementation fileTree(dir: 'libs', include: ['*.jar'])
44 |
45 | testImplementation 'org.powermock:powermock-api-mockito:1.6.5'
46 | testImplementation 'org.powermock:powermock-module-junit4-rule-agent:1.6.5'
47 | testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.5'
48 | testImplementation 'org.powermock:powermock-module-junit4:1.6.5'
49 | testImplementation 'junit:junit:4.12'
50 |
51 | unmock 'org.robolectric:android-all:7.1.0_r7-robolectric-0'
52 | }
53 |
54 |
55 | unMock {
56 | keep "android.widget.BaseAdapter"
57 | keep "android.widget.ArrayAdapter"
58 | keep "android.os.Bundle"
59 | keepStartingWith "android.database.MatrixCursor"
60 | keep "android.database.AbstractCursor"
61 | keep "android.database.CrossProcessCursor"
62 | keepStartingWith "android.text.TextUtils"
63 | keepStartingWith "android.util."
64 | keepStartingWith "android.text."
65 | keepStartingWith "android.content.ContentValues"
66 | keepStartingWith "android.content.ComponentName"
67 | keepStartingWith "android.content.ContentUris"
68 | keepStartingWith "android.content.ContentProviderOperation"
69 | keepStartingWith "android.content.ContentProviderResult"
70 | keepStartingWith "android.content.UriMatcher"
71 | keepStartingWith "android.content.Intent"
72 | keep "android.location.Location"
73 | keepStartingWith "android.content.res.Configuration"
74 | keepStartingWith "org."
75 | keepStartingWith "libcore."
76 | keepStartingWith "com.android.internal.R"
77 | keepStartingWith "com.android.internal.util."
78 | keep "android.net.Uri"
79 |
80 | keepAndRename "java.nio.charset.Charsets" to "xjava.nio.charset.Charsets"
81 |
82 | keepStartingWith "android.icu."
83 | }
84 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo. 1>&2
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
48 | echo. 1>&2
49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
50 | echo location of your Java installation. 1>&2
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo. 1>&2
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
62 | echo. 1>&2
63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
64 | echo location of your Java installation. 1>&2
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/example/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Björn Quentin
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | apply plugin: 'com.android.application'
18 | apply plugin: 'de.mobilej.unmock'
19 |
20 | android {
21 | compileSdkVersion 28
22 | buildToolsVersion '28.0.3'
23 | namespace "de.mobilej.testproject"
24 |
25 | defaultConfig {
26 | applicationId "de.mobilej.testproject"
27 | minSdkVersion 21
28 | targetSdkVersion 28
29 | versionCode 1
30 | versionName "1.0"
31 | }
32 | buildTypes {
33 | release {
34 | minifyEnabled false
35 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
36 | }
37 | }
38 |
39 | testOptions {
40 | unitTests.returnDefaultValues = true
41 | }
42 | }
43 |
44 |
45 | unMock {
46 | keep "android.widget.BaseAdapter"
47 | keep "android.widget.ArrayAdapter"
48 | keep "android.os.Bundle"
49 | keepStartingWith "android.database.MatrixCursor"
50 | keep "android.database.AbstractCursor"
51 | keep "android.database.CrossProcessCursor"
52 | keepStartingWith "android.text.TextUtils"
53 | keepStartingWith "android.util."
54 | keepStartingWith "android.text."
55 | keepStartingWith "android.content.ContentValues"
56 | keepStartingWith "android.content.ComponentName"
57 | keepStartingWith "android.content.ContentUris"
58 | keepStartingWith "android.content.ContentProviderOperation"
59 | keepStartingWith "android.content.ContentProviderResult"
60 | keepStartingWith "android.content.UriMatcher"
61 | keepStartingWith "android.content.Intent"
62 | keep "android.location.Location"
63 | keepStartingWith "android.content.res.Configuration"
64 | keepStartingWith "org."
65 | keepStartingWith "libcore."
66 | keepStartingWith "com.android.internal.R"
67 | keepStartingWith "com.android.internal.util."
68 | keep "android.net.Uri"
69 |
70 | keepAndRename "java.nio.charset.Charsets" to "xjava.nio.charset.Charsets"
71 |
72 | delegateClass "android.os.AsyncTask"
73 |
74 | keep "android.os.Parcel"
75 | keep "android.os.ParcelFileDescriptor"
76 | keep "android.os.PersistableBundle"
77 | keep "android.os.ServiceSpecificException"
78 |
79 | keep "android.os.LocaleList"
80 |
81 |
82 | delegateClass "android.hardware.Sensor"
83 | }
84 |
85 | dependencies {
86 | implementation fileTree(dir: 'libs', include: ['*.jar'])
87 |
88 | testImplementation 'org.powermock:powermock-api-mockito:1.6.1'
89 | testImplementation 'org.powermock:powermock-module-junit4-rule-agent:1.6.1'
90 | testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
91 | testImplementation 'org.powermock:powermock-module-junit4:1.6.1'
92 | testImplementation 'junit:junit:4.11'
93 |
94 | unmock 'org.robolectric:android-all:7.1.0_r7-robolectric-0'
95 | }
96 |
--------------------------------------------------------------------------------
/example/src/test/java/de/mobilej/testproject/SimpleTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Björn Quentin
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package de.mobilej.testproject;
18 |
19 | import org.junit.Test;
20 | import org.xmlpull.v1.XmlPullParser;
21 |
22 | import android.content.ContentValues;
23 | import android.content.Intent;
24 | import android.location.Location;
25 | import android.location.LocationManager;
26 | import android.text.Editable;
27 | import android.text.Html;
28 | import android.text.Spannable;
29 | import android.text.SpannableString;
30 | import android.text.TextUtils;
31 | import android.text.util.Linkify;
32 | import android.util.Base64;
33 | import android.util.JsonWriter;
34 | import android.util.SparseIntArray;
35 | import android.util.Xml;
36 |
37 | import java.io.StringReader;
38 | import java.io.StringWriter;
39 |
40 | import static junit.framework.Assert.assertTrue;
41 | import static org.junit.Assert.assertEquals;
42 | import static org.powermock.api.mockito.PowerMockito.mock;
43 |
44 | /**
45 | * Some simple tests which prove that the "unmocked" Android classes are actually working.
46 | *
47 | * Created by bjorn on 12.02.15.
48 | */
49 |
50 | public class SimpleTest {
51 |
52 | @Test
53 | public void testBase64() {
54 | assertEquals("Hello World", new String(Base64.decode(
55 | Base64.encodeToString("Hello World".getBytes(), Base64.NO_WRAP), Base64.NO_WRAP)));
56 | }
57 |
58 | @Test
59 | public void testContentValues() {
60 | ContentValues cv = new ContentValues();
61 | cv.put("foo", "bar");
62 | assertTrue(cv.containsKey("foo"));
63 | }
64 |
65 | @Test
66 | public void testEditable() {
67 | Editable e = Editable.Factory.getInstance().newEditable("Hello World");
68 | e.append("!!!!");
69 |
70 | assertEquals("Hello World!!!!", e.toString());
71 | }
72 |
73 | @Test
74 | public void testIntent() {
75 | Intent i = new Intent("TEST");
76 |
77 | assertEquals("TEST", i.getAction());
78 | }
79 |
80 | @Test
81 | public void testIsEmpty() {
82 | assertTrue(TextUtils.isEmpty(""));
83 | }
84 |
85 | @Test
86 | public void testJsonWriter() throws Exception {
87 | StringWriter sw = new StringWriter();
88 | JsonWriter jw = new JsonWriter(sw);
89 | jw.beginObject();
90 | jw.name("test");
91 | jw.value("world");
92 | jw.endObject();
93 | jw.flush();
94 |
95 | assertEquals("{\"test\":\"world\"}", sw.toString());
96 |
97 | }
98 |
99 | @Test
100 | public void testLocation() {
101 | Location loc = new Location("GPS");
102 | loc.setLongitude(50);
103 | loc.setLatitude(8);
104 |
105 | Location loc2 = new Location("GPS");
106 | loc2.setLongitude(50);
107 | loc2.setLatitude(9);
108 |
109 | assertEquals(110598.56, loc.distanceTo(loc2), 0.5);
110 | }
111 |
112 | @Test
113 | public void testLocationManagerIsNotTaken() {
114 | // will raise an error on a copied LocationManager
115 | mock(LocationManager.class);
116 | }
117 |
118 | @Test
119 | public void testPullParser() throws Exception {
120 | XmlPullParser pp = Xml.newPullParser();
121 | pp.setInput(new StringReader(" "));
122 | pp.nextTag();
123 |
124 | assertEquals("a", pp.getName());
125 |
126 | }
127 |
128 | @Test
129 | public void testSpannable() {
130 | final Spannable text = new SpannableString("Test http://www.test.de !");
131 | Linkify.addLinks(text, Linkify.WEB_URLS);
132 | assertEquals(
133 | "
Test http://www.test.de !
\n",
134 | Html.toHtml(text));
135 | }
136 |
137 | @Test
138 | public void testSparseIntArray() {
139 | SparseIntArray sia = new SparseIntArray();
140 | sia.put(12, 999);
141 | sia.put(99, 12);
142 |
143 | assertEquals(999, sia.get(12));
144 | }
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/examplelib/src/test/java/de/mobilej/examplelib/SimpleTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Björn Quentin
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package de.mobilej.examplelib;
18 |
19 | import android.content.ContentValues;
20 | import android.content.Intent;
21 | import android.icu.text.DateFormat;
22 | import android.icu.text.DateIntervalFormat;
23 | import android.icu.util.DateInterval;
24 | import android.location.Location;
25 | import android.location.LocationManager;
26 | import android.text.Editable;
27 | import android.text.Html;
28 | import android.text.Spannable;
29 | import android.text.SpannableString;
30 | import android.text.TextUtils;
31 | import android.text.util.Linkify;
32 | import android.util.Base64;
33 | import android.util.JsonWriter;
34 | import android.util.SparseIntArray;
35 | import android.util.Xml;
36 |
37 | import org.junit.Test;
38 | import org.xmlpull.v1.XmlPullParser;
39 |
40 | import java.io.StringReader;
41 | import java.io.StringWriter;
42 | import java.text.FieldPosition;
43 | import java.util.Locale;
44 |
45 | import static junit.framework.Assert.assertTrue;
46 | import static org.junit.Assert.assertEquals;
47 | import static org.powermock.api.mockito.PowerMockito.mock;
48 |
49 | /**
50 | * Some simple tests which prove that the "unmocked" Android classes are actually working.
51 | *
52 | * Created by bjorn on 12.02.15.
53 | */
54 |
55 | public class SimpleTest {
56 |
57 | @Test
58 | public void testBase64() {
59 | assertEquals("Hello World", new String(Base64.decode(
60 | Base64.encodeToString("Hello World".getBytes(), Base64.NO_WRAP), Base64.NO_WRAP)));
61 | }
62 |
63 | @Test
64 | public void testContentValues() {
65 | ContentValues cv = new ContentValues();
66 | cv.put("foo", "bar");
67 | assertTrue(cv.containsKey("foo"));
68 | }
69 |
70 | @Test
71 | public void testEditable() {
72 | Editable e = Editable.Factory.getInstance().newEditable("Hello World");
73 | e.append("!!!!");
74 |
75 | assertEquals("Hello World!!!!", e.toString());
76 | }
77 |
78 | @Test
79 | public void testIntent() {
80 | Intent i = new Intent("TEST");
81 |
82 | assertEquals("TEST", i.getAction());
83 | }
84 |
85 | @Test
86 | public void testIsEmpty() {
87 | assertTrue(TextUtils.isEmpty(""));
88 | }
89 |
90 | @Test
91 | public void testJsonWriter() throws Exception {
92 | StringWriter sw = new StringWriter();
93 | JsonWriter jw = new JsonWriter(sw);
94 | jw.beginObject();
95 | jw.name("test");
96 | jw.value("world");
97 | jw.endObject();
98 | jw.flush();
99 |
100 | assertEquals("{\"test\":\"world\"}", sw.toString());
101 |
102 | }
103 |
104 | @Test
105 | public void testLocation() {
106 | Location loc = new Location("GPS");
107 | loc.setLongitude(50);
108 | loc.setLatitude(8);
109 |
110 | Location loc2 = new Location("GPS");
111 | loc2.setLongitude(50);
112 | loc2.setLatitude(9);
113 |
114 | assertEquals(110598.56, loc.distanceTo(loc2), 0.5);
115 | }
116 |
117 | @Test
118 | public void testLocationManagerIsNotTaken() {
119 | // will raise an error on a copied LocationManager
120 | mock(LocationManager.class);
121 | }
122 |
123 | @Test
124 | public void testPullParser() throws Exception {
125 | XmlPullParser pp = Xml.newPullParser();
126 | pp.setInput(new StringReader(" "));
127 | pp.nextTag();
128 |
129 | assertEquals("a", pp.getName());
130 |
131 | }
132 |
133 | @Test
134 | public void testSpannable() {
135 | final Spannable text = new SpannableString("Test http://www.test.de !");
136 | Linkify.addLinks(text, Linkify.WEB_URLS);
137 | assertEquals(
138 | "Test http://www.test.de !
\n",
139 | Html.toHtml(text));
140 | }
141 |
142 | @Test
143 | public void testSparseIntArray() {
144 | SparseIntArray sia = new SparseIntArray();
145 | sia.put(12, 999);
146 | sia.put(99, 12);
147 |
148 | assertEquals(999, sia.get(12));
149 | }
150 |
151 | @Test
152 | public void testIssue42() {
153 | DateInterval dtInterval = new DateInterval(1000 * 3600 * 24L, 1000 * 3600 * 24 * 2L);
154 | DateIntervalFormat dtIntervalFmt = DateIntervalFormat.getInstance(DateFormat.YEAR_MONTH_DAY, new Locale("en", "GB", ""));
155 | StringBuffer str = new StringBuffer("");
156 | FieldPosition pos = new FieldPosition(0);
157 | // formatting
158 | dtIntervalFmt.format(dtInterval, str, pos);
159 |
160 | assertEquals("1 – 2 January 1970", str.toString());
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://maven-badges.herokuapp.com/maven-central/com.github.bjoernq/unmockplugin) [](http://choosealicense.com/licenses/apache-2.0/)
2 |
3 | # Android Unmock Gradle Plugin
4 |
5 | ## Purpose
6 |
7 | This is a super simple plugin to be used in combination with the new unit testing feature of the Gradle Plugin / Android Studio. ( http://tools.android.com/tech-docs/unit-testing-support )
8 |
9 | It tries to solve the problem that you have to mock each and every Android SDK class (even SparseArray, TextUtils etc.) by allowing you to use selected classes from a real Android-Jarfile.
10 |
11 | ## How to use
12 |
13 | Add the plugin to your buildscript dependencies and make sure to use the maven central repository:
14 |
15 | ```groovy
16 | buildscript {
17 | repositories {
18 | mavenCentral()
19 | }
20 |
21 | dependencies {
22 | classpath "com.github.bjoernq:unmockplugin:${unmockpluginVersion}"
23 | }
24 | }
25 | ```
26 |
27 | Please note: Versions prior to 0.7.6 are not available on Maven Central.
28 |
29 | And this to the module's build script:
30 |
31 | ```groovy
32 | apply plugin: 'de.mobilej.unmock'
33 | ```
34 |
35 | Additionally you have to configure which classes to use and where to get the real Android.jar from. e.g:
36 |
37 | ```groovy
38 | unMock {
39 | keep "android.widget.BaseAdapter"
40 | keep "android.widget.ArrayAdapter"
41 | keep "android.os.Bundle"
42 | keepStartingWith "android.database.MatrixCursor"
43 | keep "android.database.AbstractCursor"
44 | keep "android.database.CrossProcessCursor"
45 | keepStartingWith "android.text.TextUtils"
46 | keepStartingWith "android.util."
47 | keepStartingWith "android.text."
48 | keepStartingWith "android.content.ContentValues"
49 | keepStartingWith "android.content.ComponentName"
50 | keepStartingWith "android.content.ContentUris"
51 | keepStartingWith "android.content.ContentProviderOperation"
52 | keepStartingWith "android.content.ContentProviderResult"
53 | keepStartingWith "android.content.UriMatcher"
54 | keepStartingWith "android.content.Intent"
55 | keep "android.location.Location"
56 | keepStartingWith "android.content.res.Configuration"
57 | keepStartingWith "org."
58 | keepStartingWith "libcore."
59 | keepStartingWith "com.android.internal.R"
60 | keepStartingWith "com.android.internal.util."
61 | keep "android.net.Uri"
62 |
63 | keepAndRename "java.nio.charset.Charsets" to "xjava.nio.charset.Charsets"
64 | }
65 |
66 | dependencies {
67 | // dependency to android-all to use
68 | unmock 'org.robolectric:android-all:4.3_r2-robolectric-0'
69 | }
70 |
71 | ```
72 |
73 | |Statement|Description|
74 | |-------|-----------|
75 | |keep|keeps the specified class (and it's possibly present inner classes)|
76 | |keepStartingWith|keeps every class which FQN starts with the given string|
77 | |keepAndRename|let you keep a class while renaming it (e.g. needed for classes in the "java" top-level package since these are only allowed to be loaded from the boot classpath)|
78 | |delegateClass|every method (and constructor) in the given class is delegated to de.mobilej.ABridge. Makes it easier to mock things in a framework class you inherit from|
79 |
80 | That's it!
81 |
82 | Have a look at the example contained in this repository for more details.
83 |
84 | Starting from version 0.3.5 you can leave out the configuration closure which will result using defaults (which are shown in the example above).
85 |
86 | If you use any of the keep statements the default configuration will be cleared. (So your own configuration is not adding but replaces the default).
87 |
88 | If you don't configure the unmock dependency the plugin will use `org.robolectric:android-all:4.3_r2-robolectric-0`
89 |
90 | ## Versions
91 |
92 | |Version|Description|
93 | |-------|-----------|
94 | |0.1.0|initial public release|
95 | |0.1.1|added the '-' matching|
96 | |0.1.2|fixed a bug preventing the plugin to work correctly on Windows systems|
97 | |0.1.3|the binary is targeting Java 1.7, again|
98 | |0.2.0|support class renaming, rebuild jar if build file changed|
99 | |0.3.0|use Gradle way of upToDate check, have a DSL for the configuration|
100 | |0.3.1|compile with Gradle 2.4|
101 | |0.3.2|lib-sample and some bugfixes (frozen class problem)|
102 | |0.3.3|Android Gradle Plugin 1.3.0 compatibility|
103 | |0.3.5|Use default config if no configuration closure is given|
104 | |0.3.6|Optionally you can specify a directory to download the all-android.jar to|
105 | |0.4.0|Support for "delegateClass" added|
106 | |0.5.0|ABridge now includes callByte, callDouble and callFloat, this _might_ break tests that rely on ABrdige.callObject to be called in these cases|
107 | |0.5.1|Unique names for unmocked-android.jar to workaround an Android Studio problem|
108 | |0.6.0|Use Gradle's dependency management to get the android-all.jar, more magic to workaround issues using unmocked Android-6.0+ classes|
109 | |0.6.1|Make it work with Gradle 4.0-milestone and Android Gradle plugin to 3.0.0.-alpha1 while keep it working on previous versions|
110 | |0.6.2|Make it work with activated Kotlin plugin|
111 | |0.6.3|Make it possible to use Gradle 4 with Android Gradle plugin < 3.0|
112 | |0.6.4|Works with kapt3|
113 | |0.6.5|Also copy non-class files when they are matched by keepStartingWith|
114 | |0.7.0|Using downloadFrom will make your build fail - use unmock scoped dependency now|
115 | |0.7.1|Add support for proper Gradle up-to-date checks (thanks to @drewhannay)|
116 | |0.7.2|Enable relocatable Gradle build cache support (thanks to @drewhannay)|
117 | |0.7.3|Several internal improvements (PR 52, 53) contributed by @drewhannay and @stephanenicolas|
118 | |0.7.4|Bump Javassist version
119 | |0.7.5|Allow unmocked classes in any variant (PR 62)
120 | |0.7.6|Bump Javassist version to 3.27.0-GA
121 | |0.7.7| ---
122 | |0.7.8|Gradle 7.0 compatability, contributed by @calvarez-ov
123 | |0.7.9|Fix #77, contributed by @matejdro
124 | |0.8.0|#83, contributed by @matejdro
125 | |0.9.0|#69
126 |
127 | ## License
128 |
129 | ```
130 | Copyright 2015-2024 Björn Quentin
131 |
132 | Licensed under the Apache License, Version 2.0 (the "License");
133 | you may not use this file except in compliance with the License.
134 | You may obtain a copy of the License at
135 |
136 | http://www.apache.org/licenses/LICENSE-2.0
137 |
138 | Unless required by applicable law or agreed to in writing, software
139 | distributed under the License is distributed on an "AS IS" BASIS,
140 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
141 | See the License for the specific language governing permissions and
142 | limitations under the License.
143 | ```
144 |
--------------------------------------------------------------------------------
/example/src/test/java/de/mobilej/testproject/ComplexSetupNeededTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Björn Quentin
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | package de.mobilej.testproject;
18 |
19 | import android.content.res.Configuration;
20 | import android.content.res.Resources;
21 | import android.text.format.DateUtils;
22 |
23 | import org.junit.Test;
24 | import org.junit.runner.RunWith;
25 | import org.mockito.invocation.InvocationOnMock;
26 | import org.mockito.stubbing.Answer;
27 | import org.powermock.core.classloader.annotations.PrepareForTest;
28 | import org.powermock.modules.junit4.PowerMockRunner;
29 |
30 | import de.mobilej.ABridge;
31 | import libcore.icu.LocaleData;
32 |
33 | import static org.junit.Assert.assertEquals;
34 | import static org.mockito.Matchers.any;
35 | import static org.mockito.Matchers.eq;
36 | import static org.mockito.Matchers.isNull;
37 | import static org.mockito.Mockito.mock;
38 | import static org.powermock.api.mockito.PowerMockito.mockStatic;
39 | import static org.powermock.api.mockito.PowerMockito.when;
40 |
41 | /**
42 | * For some simple helper we need a complex mock setup.
43 | *
44 | * Here we use DateUtils.formatElapsedTime which internally uses libcore.icu and needs some strings
45 | * from system resources to work.
46 | *
47 | * The ICU setup is somewhat problematic and here it comes handy that the plugin will change every
48 | * native method to call de.mobilej.ABridge which can be easily mocked.
49 | *
50 | * Created by bjorn on 16.02.15.
51 | */
52 |
53 | @RunWith(PowerMockRunner.class)
54 | @PrepareForTest({Resources.class, ABridge.class})
55 | public class ComplexSetupNeededTest {
56 |
57 | @Test
58 | public void testFormatElapsedTime() {
59 | mockStatic(ABridge.class);
60 |
61 | // ABridge.callBoolean is called by the patched ICU class
62 | // with the parameters:
63 | // Signature of the original method
64 | // "this" (since we are called from a static method it is null)
65 | // array of original method's parameters
66 | when(ABridge.callBoolean(
67 | eq("libcore.icu.ICU.initLocaleDataImpl(java.lang.String,libcore.icu.LocaleData)"),
68 | isNull(), any(Object[].class))).thenAnswer(new Answer() {
69 | @Override
70 | public Object answer(final InvocationOnMock invocation) throws Throwable {
71 | LocaleData ld = (LocaleData) ((Object[]) (invocation.getArguments()[2]))[1];
72 |
73 | ld.amPm = new String[]{"AM", "PM"};
74 | ld.NaN = "NaN";
75 | ld.currencyPattern = "¤#,##0.00";
76 | ld.currencySymbol = "$";
77 | ld.eras = new String[]{"BC", "AD"};
78 | ld.exponentSeparator = "E";
79 | ld.firstDayOfWeek = 1;
80 | ld.fullDateFormat = "EEEE, MMMM d, y";
81 | ld.fullTimeFormat = "h:mm:ss a zzzz";
82 | ld.infinity = "∞";
83 | ld.integerPattern = "#,##0";
84 | ld.internationalCurrencySymbol = "USD";
85 | ld.longDateFormat = "MMMM d, y";
86 | ld.longMonthNames = new String[]{"January", "February", "March", "April", "May",
87 | "June", "July", "August", "September", "October", "November", "December"};
88 | ld.longStandAloneMonthNames = new String[]{"January", "February", "March", "April",
89 | "May", "June", "July", "August", "September", "October", "November",
90 | "December"};
91 | ld.longStandAloneWeekdayNames = new String[]{"", "Sunday", "Monday", "Tuesday",
92 | "Wednesday", "Thursday", "Friday", "Saturday"};
93 | ld.longTimeFormat = "h:mm:ss a z";
94 | ld.longWeekdayNames = new String[]{"", "Sunday", "Monday", "Tuesday", "Wednesday",
95 | "Thursday", "Friday", "Saturday"};
96 | ld.mediumDateFormat = "MMM d, y";
97 | ld.mediumTimeFormat = "h:mm:ss a";
98 | ld.minimalDaysInFirstWeek = 1;
99 | ld.minusSign = "-";
100 | // ld.narrowAm = "a";
101 | // ld.narrowPm = "p";
102 | ld.numberPattern = "#,##0.###";
103 | ld.percentPattern = "#,##0%";
104 | ld.shortDateFormat = "M/d/yy";
105 | // ld.shortDateFormat4 = "M/d/y";
106 | ld.shortMonthNames = new String[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
107 | "Aug", "Sep", "Oct", "Nov", "Dec"};
108 | ld.shortStandAloneMonthNames = new String[]{"Jan", "Feb", "Mar", "Apr", "May",
109 | "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
110 | ld.shortStandAloneWeekdayNames = new String[]{"", "Sun", "Mon", "Tue", "Wed", "Thu",
111 | "Fri", "Sat"};
112 | ld.shortTimeFormat = "h:mm a";
113 | ld.shortWeekdayNames = new String[]{"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
114 | "Sat"};
115 | //ld.timeFormat12 = "h:mm a";
116 | //ld.timeFormat24 = "HH:mm";
117 | ld.tinyMonthNames = new String[]{"J", "F", "M", "A", "M", "J", "J", "A", "S", "O",
118 | "N", "D"};
119 | ld.tinyStandAloneMonthNames = new String[]{"J", "F", "M", "A", "M", "J", "J", "A",
120 | "S", "O", "N", "D"};
121 | ld.tinyStandAloneWeekdayNames = new String[]{"", "S", "M", "T", "W", "T", "F", "S"};
122 | ld.tinyWeekdayNames = new String[]{"", "S", "M", "T", "W", "T", "F", "S"};
123 | ld.today = "Today";
124 | ld.tomorrow = "Tomorrow";
125 | ld.yesterday = "Yesterday";
126 | ld.decimalSeparator = '.';
127 | ld.groupingSeparator = ',';
128 | ld.monetarySeparator = '.';
129 | ld.patternSeparator = ';';
130 | ld.perMill = '‰';
131 | ld.percent = "%";
132 | ld.zeroDigit = '0';
133 |
134 | return true;
135 | }
136 | });
137 |
138 | Resources mockResources = mock(Resources.class);
139 | Configuration mockConfiguration = new Configuration();
140 | when(mockResources.getConfiguration()).thenReturn(mockConfiguration);
141 |
142 | when(mockResources
143 | .getString(eq(com.android.internal.R.string.elapsed_time_short_format_mm_ss)))
144 | .thenReturn(
145 | "%1$02d:%2$02d");
146 |
147 | when(mockResources
148 | .getString(eq(com.android.internal.R.string.time_of_day)))
149 | .thenReturn(
150 | "%H:%M:%S");
151 | when(mockResources
152 | .getString(eq(com.android.internal.R.string.month_day_year)))
153 | .thenReturn(
154 | "%-e. %B %Y");
155 |
156 | when(mockResources
157 | .getString(eq(com.android.internal.R.string.date_and_time)))
158 | .thenReturn(
159 | "%1$s, %2$s");
160 |
161 | when(mockResources
162 | .getString(eq(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss)))
163 | .thenReturn("%1$d:%2$02d:%3$02d");
164 |
165 | when(mockResources
166 | .getString(eq(com.android.internal.R.string.elapsed_time_short_format_mm_ss)))
167 | .thenReturn("%1$02d:%2$02d");
168 |
169 | when(mockResources
170 | .getString(eq(com.android.internal.R.string.time_of_day)))
171 | .thenReturn("%H:%M:%S");
172 | when(mockResources
173 | .getString(eq(com.android.internal.R.string.month_day_year)))
174 | .thenReturn("%-e. %B %Y");
175 | when(mockResources
176 | .getString(eq(com.android.internal.R.string.date_and_time)))
177 | .thenReturn("%1$s, %2$s");
178 |
179 | mockStatic(Resources.class);
180 | when(Resources.getSystem()).thenReturn(mockResources);
181 |
182 | // after a quite complex setup we can finally call DateUtils.formatElapsedTime
183 | // in a real world use case we would move the setup a static method in a helper class
184 | assertEquals("33:20", DateUtils.formatElapsedTime(2000));
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | # This is normally unused
84 | # shellcheck disable=SC2034
85 | APP_BASE_NAME=${0##*/}
86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
88 |
89 | # Use the maximum available, or set MAX_FD != -1 to use that value.
90 | MAX_FD=maximum
91 |
92 | warn () {
93 | echo "$*"
94 | } >&2
95 |
96 | die () {
97 | echo
98 | echo "$*"
99 | echo
100 | exit 1
101 | } >&2
102 |
103 | # OS specific support (must be 'true' or 'false').
104 | cygwin=false
105 | msys=false
106 | darwin=false
107 | nonstop=false
108 | case "$( uname )" in #(
109 | CYGWIN* ) cygwin=true ;; #(
110 | Darwin* ) darwin=true ;; #(
111 | MSYS* | MINGW* ) msys=true ;; #(
112 | NONSTOP* ) nonstop=true ;;
113 | esac
114 |
115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
116 |
117 |
118 | # Determine the Java command to use to start the JVM.
119 | if [ -n "$JAVA_HOME" ] ; then
120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
121 | # IBM's JDK on AIX uses strange locations for the executables
122 | JAVACMD=$JAVA_HOME/jre/sh/java
123 | else
124 | JAVACMD=$JAVA_HOME/bin/java
125 | fi
126 | if [ ! -x "$JAVACMD" ] ; then
127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
128 |
129 | Please set the JAVA_HOME variable in your environment to match the
130 | location of your Java installation."
131 | fi
132 | else
133 | JAVACMD=java
134 | if ! command -v java >/dev/null 2>&1
135 | then
136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 | fi
142 |
143 | # Increase the maximum file descriptors if we can.
144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
145 | case $MAX_FD in #(
146 | max*)
147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
148 | # shellcheck disable=SC2039,SC3045
149 | MAX_FD=$( ulimit -H -n ) ||
150 | warn "Could not query maximum file descriptor limit"
151 | esac
152 | case $MAX_FD in #(
153 | '' | soft) :;; #(
154 | *)
155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
156 | # shellcheck disable=SC2039,SC3045
157 | ulimit -n "$MAX_FD" ||
158 | warn "Could not set maximum file descriptor limit to $MAX_FD"
159 | esac
160 | fi
161 |
162 | # Collect all arguments for the java command, stacking in reverse order:
163 | # * args from the command line
164 | # * the main class name
165 | # * -classpath
166 | # * -D...appname settings
167 | # * --module-path (only if needed)
168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
169 |
170 | # For Cygwin or MSYS, switch paths to Windows format before running java
171 | if "$cygwin" || "$msys" ; then
172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
174 |
175 | JAVACMD=$( cygpath --unix "$JAVACMD" )
176 |
177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
178 | for arg do
179 | if
180 | case $arg in #(
181 | -*) false ;; # don't mess with options #(
182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
183 | [ -e "$t" ] ;; #(
184 | *) false ;;
185 | esac
186 | then
187 | arg=$( cygpath --path --ignore --mixed "$arg" )
188 | fi
189 | # Roll the args list around exactly as many times as the number of
190 | # args, so each arg winds up back in the position where it started, but
191 | # possibly modified.
192 | #
193 | # NB: a `for` loop captures its iteration list before it begins, so
194 | # changing the positional parameters here affects neither the number of
195 | # iterations, nor the values presented in `arg`.
196 | shift # remove old arg
197 | set -- "$@" "$arg" # push replacement arg
198 | done
199 | fi
200 |
201 |
202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
204 |
205 | # Collect all arguments for the java command:
206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
207 | # and any embedded shellness will be escaped.
208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
209 | # treated as '${Hostname}' itself on the command line.
210 |
211 | set -- \
212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
213 | -classpath "$CLASSPATH" \
214 | org.gradle.wrapper.GradleWrapperMain \
215 | "$@"
216 |
217 | # Stop when "xargs" is not available.
218 | if ! command -v xargs >/dev/null 2>&1
219 | then
220 | die "xargs is not available"
221 | fi
222 |
223 | # Use "xargs" to parse quoted args.
224 | #
225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
226 | #
227 | # In Bash we could simply go:
228 | #
229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
230 | # set -- "${ARGS[@]}" "$@"
231 | #
232 | # but POSIX shell has neither arrays nor command substitution, so instead we
233 | # post-process each arg (as a line of input to sed) to backslash-escape any
234 | # character that might be a shell metacharacter, then use eval to reverse
235 | # that process (while maintaining the separation between arguments), and wrap
236 | # the whole thing up as a single "set" statement.
237 | #
238 | # This will of course break if any of these variables contains a newline or
239 | # an unmatched quote.
240 | #
241 |
242 | eval "set -- $(
243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
244 | xargs -n1 |
245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
246 | tr '\n' ' '
247 | )" '"$@"'
248 |
249 | exec "$JAVACMD" "$@"
250 |
--------------------------------------------------------------------------------
/example/src/test/java/de/mobilej/testproject/ParcelTest.java:
--------------------------------------------------------------------------------
1 | package de.mobilej.testproject;
2 |
3 | import android.os.Parcel;
4 |
5 | import org.junit.Before;
6 | import org.junit.Test;
7 | import org.junit.runner.RunWith;
8 | import org.mockito.invocation.InvocationOnMock;
9 | import org.mockito.stubbing.Answer;
10 | import org.powermock.core.classloader.annotations.PrepareForTest;
11 | import org.powermock.modules.junit4.PowerMockRunner;
12 |
13 | import java.io.UnsupportedEncodingException;
14 | import java.nio.ByteBuffer;
15 | import java.util.HashMap;
16 |
17 | import de.mobilej.ABridge;
18 |
19 | import static org.hamcrest.core.IsEqual.equalTo;
20 | import static org.hamcrest.core.IsNull.notNullValue;
21 | import static org.hamcrest.core.IsNull.nullValue;
22 | import static org.junit.Assert.assertThat;
23 | import static org.powermock.api.mockito.PowerMockito.mockStatic;
24 |
25 | /**
26 | * Shows how you can test Parcel
27 | *
28 | * Created by bjoern on 25.12.2016.
29 | */
30 | @RunWith(PowerMockRunner.class)
31 | @PrepareForTest(ABridge.class)
32 | public class ParcelTest {
33 | private Parcel parcel;
34 |
35 | @Before
36 | public void setup() {
37 | MockParcel();
38 |
39 | parcel = Parcel.obtain();
40 | }
41 |
42 | @Test
43 | public void testTwoParcels() {
44 | Parcel p1 = Parcel.obtain();
45 | Parcel p2 = Parcel.obtain();
46 |
47 | p1.writeInt(42);
48 | p2.writeInt(23);
49 |
50 | assertThat(p2.readInt(), equalTo(23));
51 | assertThat(p1.readInt(), equalTo(42));
52 | }
53 |
54 | @Test
55 | public void testObtain() {
56 | assertThat(parcel, notNullValue());
57 | }
58 |
59 | @Test
60 | public void testReadIntWhenEmpty() {
61 | assertThat(parcel.readInt(), equalTo(0));
62 | }
63 |
64 | @Test
65 | public void testReadLongWhenEmpty() {
66 | assertThat(parcel.readLong(), equalTo(0L));
67 | }
68 |
69 | @Test
70 | public void testReadStringWhenEmpty() {
71 | assertThat(parcel.readString(), nullValue());
72 | }
73 |
74 | @Test
75 | public void testReadWriteSingleString() {
76 | String val = "test";
77 | parcel.writeString(val);
78 | assertThat(parcel.readString(), equalTo(val));
79 | }
80 |
81 | @Test
82 | public void testWriteNullString() {
83 | parcel.writeString(null);
84 | assertThat(parcel.readString(), nullValue());
85 | }
86 |
87 | @Test
88 | public void testReadWriteMultipleStrings() {
89 | for (int i = 0; i < 10; ++i) {
90 | parcel.writeString(Integer.toString(i));
91 | }
92 | for (int i = 0; i < 10; ++i) {
93 | assertThat(parcel.readString(), equalTo(Integer.toString(i)));
94 | }
95 | // now try to read past the number of items written and see what happens
96 | assertThat(parcel.readString(), nullValue());
97 | }
98 |
99 | @Test
100 | public void testReadWriteSingleInt() {
101 | int val = 5;
102 | parcel.writeInt(val);
103 | assertThat(parcel.readInt(), equalTo(val));
104 | }
105 |
106 | @Test
107 | public void testReadWriteMultipleInts() {
108 | for (int i = 0; i < 10; ++i) {
109 | parcel.writeInt(i);
110 | }
111 | for (int i = 0; i < 10; ++i) {
112 | assertThat(parcel.readInt(), equalTo(i));
113 | }
114 | // now try to read past the number of items written and see what happens
115 | assertThat(parcel.readInt(), equalTo(0));
116 | }
117 |
118 | @Test
119 | public void testReadWriteStringInt() {
120 | for (int i = 0; i < 10; ++i) {
121 | parcel.writeString(Integer.toString(i));
122 | parcel.writeInt(i);
123 | }
124 | for (int i = 0; i < 10; ++i) {
125 | assertThat(parcel.readString(), equalTo(Integer.toString(i)));
126 | assertThat(parcel.readInt(), equalTo(i));
127 | }
128 | // now try to read past the number of items written and see what happens
129 | assertThat(parcel.readString(), nullValue());
130 | assertThat(parcel.readInt(), equalTo(0));
131 | }
132 |
133 | @Test(expected = ClassCastException.class)
134 | public void testWriteStringReadInt() {
135 | String val = "test";
136 | parcel.writeString(val);
137 | parcel.readInt();
138 | }
139 |
140 | @Test(expected = ClassCastException.class)
141 | public void testWriteIntReadString() {
142 | int val = 9;
143 | parcel.writeInt(val);
144 | parcel.readString();
145 | }
146 |
147 | @Test
148 | public void testReadWriteSingleLong() {
149 | long val = 5;
150 | parcel.writeLong(val);
151 | assertThat(parcel.readLong(), equalTo(val));
152 | }
153 |
154 | @Test
155 | public void testReadWriteMultipleLongs() {
156 | for (long i = 0; i < 10; ++i) {
157 | parcel.writeLong(i);
158 | }
159 | for (long i = 0; i < 10; ++i) {
160 | assertThat(parcel.readLong(), equalTo(i));
161 | }
162 | // now try to read past the number of items written and see what happens
163 | assertThat(parcel.readLong(), equalTo(0L));
164 | }
165 |
166 | @Test
167 | public void testReadWriteStringLong() {
168 | for (long i = 0; i < 10; ++i) {
169 | parcel.writeString(Long.toString(i));
170 | parcel.writeLong(i);
171 | }
172 | for (long i = 0; i < 10; ++i) {
173 | assertThat(parcel.readString(), equalTo(Long.toString(i)));
174 | assertThat(parcel.readLong(), equalTo(i));
175 | }
176 | // now try to read past the number of items written and see what happens
177 | assertThat(parcel.readString(), nullValue());
178 | assertThat(parcel.readLong(), equalTo(0L));
179 | }
180 |
181 | @Test(expected = ClassCastException.class)
182 | public void testWriteStringReadLong() {
183 | String val = "test";
184 | parcel.writeString(val);
185 | parcel.readLong();
186 | }
187 |
188 | @Test(expected = ClassCastException.class)
189 | public void testWriteLongReadString() {
190 | long val = 9;
191 | parcel.writeLong(val);
192 | parcel.readString();
193 | }
194 |
195 | /**
196 | * Uses PowerMock to setup mocking/fakeing of android.os.Parcel
197 | *
198 | * Incomplete implementation only supports read/write int,long,String just to show how it can be done.
199 | */
200 | public static void MockParcel() {
201 | final HashMap data = new HashMap<>();
202 | final long fakeNativePtr[] = new long[]{1};
203 |
204 | final Answer defaultAnswer = new Answer() {
205 | @Override
206 | public Object answer(InvocationOnMock invocation) throws Throwable {
207 | String method = (String) invocation.getArguments()[0];
208 | Object[] realParams = (Object[]) invocation.getArguments()[2];
209 |
210 | if (method.startsWith("android.os.Parcel.nativeWrite")) {
211 | ByteBufferWrapper buffer = data.get(realParams[0]);
212 | if (buffer == null) {
213 | buffer = new ByteBufferWrapper();
214 | data.put((Long) realParams[0], buffer);
215 | }
216 |
217 | if (method.contains("Int")) {
218 | buffer.putInt((Integer) realParams[1]);
219 | } else if (method.contains("String")) {
220 | buffer.putString((String) realParams[1]);
221 | } else if (method.contains("Long")) {
222 | buffer.putLong((Long) realParams[1]);
223 | }
224 | } else if (method.startsWith("android.os.Parcel.nativeRead")) {
225 | ByteBufferWrapper buffer = data.get(realParams[0]);
226 | if (buffer != null) {
227 | if (method.contains("Int")) {
228 | return buffer.getInt();
229 | } else if (method.contains("String")) {
230 | return buffer.getString();
231 | } else if (method.contains("Long")) {
232 | return buffer.getLong();
233 | }
234 | }
235 | } else if (method.startsWith("android.os.Parcel.nativeCreate()")) {
236 | return fakeNativePtr[0]++;
237 | }
238 |
239 | return null;
240 | }
241 | };
242 |
243 | mockStatic(ABridge.class, defaultAnswer);
244 | }
245 |
246 | public static class ByteBufferWrapper {
247 | private static final int TYPE_INT = 1;
248 | private static final int TYPE_STRING = 2;
249 | private static final int TYPE_LONG = 3;
250 |
251 | private ByteBuffer buffer = ByteBuffer.allocate(500000);
252 | private ByteBuffer readBuffer = ByteBuffer.wrap(buffer.array());
253 |
254 | public int getInt() {
255 | if (checkType(TYPE_INT)) return 0;
256 | return readBuffer.getInt();
257 | }
258 |
259 | public void putInt(int v) {
260 | buffer.putInt(TYPE_INT);
261 | buffer.putInt(v);
262 | }
263 |
264 | public long getLong() {
265 | if (checkType(TYPE_LONG)) return 0;
266 | return readBuffer.getLong();
267 | }
268 |
269 | public void putLong(long v) {
270 | buffer.putInt(TYPE_LONG);
271 | buffer.putLong(v);
272 | }
273 |
274 | public String getString() {
275 | if (checkType(TYPE_STRING)) return null;
276 | int l = readBuffer.getInt();
277 | if (l == -1) {
278 | return null;
279 | }
280 | byte[] bytes = new byte[l];
281 | readBuffer.get(bytes);
282 | try {
283 | return new String(bytes, "UTF-8");
284 | } catch (UnsupportedEncodingException e) {
285 | throw new RuntimeException(e);
286 | }
287 | }
288 |
289 | public void putString(String v) {
290 | buffer.putInt(TYPE_STRING);
291 | if (v == null) {
292 | buffer.putInt(-1);
293 | return;
294 | }
295 | byte[] bytes = new byte[0];
296 | try {
297 | bytes = v.getBytes("UTF-8");
298 | } catch (UnsupportedEncodingException e) {
299 | throw new RuntimeException(e);
300 | }
301 | buffer.putInt(bytes.length);
302 | buffer.put(bytes);
303 | }
304 |
305 | private boolean checkType(int type) {
306 | int t = readBuffer.getInt();
307 | if (t == 0) {
308 | return true;
309 | }
310 | if (t != type) {
311 | throw new ClassCastException();
312 | }
313 | return false;
314 | }
315 | }
316 | }
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2018 Björn Quentin
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------