greyblue9 / dexmaker

Automatically exported from code.google.com/p/dexmaker
1 stars 0 forks source link

dexcache == null (and no default could be found; consider setting the 'dexmaker.dexcache' system property) #2

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Android (3.0) + Mockito 1.9.1 (Snapshot) + dexmaker
2. Create Android test project and mock a object using mockito

What is the expected output? What do you see instead?
Code should work but i get an error:

java.lang.IllegalArgumentException: dexcache == null (and no default could be 
found; consider setting the 'dexmaker.dexcache' system property)
at com.google.dexmaker.DexMaker.generateAndLoad(DexMaker.java:359)
at com.google.dexmaker.stock.ProxyBuilder.buildProxyClass(ProxyBuilder.java:252)
at 
com.google.dexmaker.mockito.DexmakerMockMaker.createMock(DexmakerMockMaker.java:
51)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:41)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:41)
at org.mockito.Mockito.mock(Mockito.java:1061)
at org.mockito.Mockito.mock(Mockito.java:955)
at 
nl.wowww.hallmark.kpp.android.tablet.test.CardSelection.testMockito(CardSelectio
n.java:102)
at java.lang.reflect.Method.invokeNative(Native Method)
at 
android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at 
android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at 
android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTes
tCase2.java:186)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at 
android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:52
5)
at 
android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1547)

What version of the product are you using? On what operating system?
dexmaker20120305 + android sdk r17

Original issue reported on code.google.com by johannes...@gmail.com on 23 Mar 2012 at 2:56

GoogleCodeExporter commented 8 years ago
When i add this line: System.setProperty("dexmaker.dexcache", "/sdcard");
Then i get this error:
03-26 14:58:17.261: E/dalvikvm(1322): Can't open dex cache 
'/data/dalvik-cache/sdcard@Generated1521942046.jar@classes.dex': No such file 
or directory

Original comment by johannes...@gmail.com on 26 Mar 2012 at 3:01

GoogleCodeExporter commented 8 years ago
Hugo, it looks like the AppDataDirGuesser isn't guessing correctly in this 
case. Could you take a look?

Original comment by jessewil...@google.com on 2 Apr 2012 at 2:37

GoogleCodeExporter commented 8 years ago
I am having the same problem, and AppDataDirGuesser is finding the right 
candidate (/data/data/com.my.app/cache), but the cache directory doesn't exist 
since my app doesn't use it, so the isWriteableDirectory(file) is false and 
it's not added as a result. 

Original comment by gruen0ae...@gmail.com on 25 Apr 2012 at 6:06

GoogleCodeExporter commented 8 years ago
The workaround is to add this to your test's setUp (you must make it an 
InstrumentationTestCase or subclass instead of just a TestCase if it's not 
already)

    public void setUp() throws Exception {
        getInstrumentation().getTargetContext().getCacheDir();
    }

This will make Android create the cache directory so that the AppDataDirGuesser 
will find it.

Original comment by gruen0ae...@gmail.com on 25 Apr 2012 at 6:23

GoogleCodeExporter commented 8 years ago
This issue is fixed in 524c023fb37b41e06b69f1b696100dd465acb353. Please confirm 
that it's working for you.

Original comment by klyu...@google.com on 25 Jun 2012 at 5:13

GoogleCodeExporter commented 8 years ago
I'm seeing this problem again after upgrading my phone to Android 4.3 - a load 
of tests suddenly started failing. Using mockito-core 1.9.5, dexmaker 1.0.

Adding this line to setUp() worked around it:
System.setProperty("dexmaker.dexcache", 
getInstrumentation().getTargetContext().getCacheDir().getPath());

The proposed workaround:
getInstrumentation().getTargetContext().getCacheDir();
had no effect.

Original comment by polly.k...@gmail.com on 1 Aug 2013 at 8:34

GoogleCodeExporter commented 8 years ago
It looks like DexMaker can't guess where the "cache" directory of the app is on 
Android 4.3: see 
https://code.google.com/p/dexmaker/source/browse/dexmaker/src/main/java/com/goog
le/dexmaker/AppDataDirGuesser.java#63. It appears that the format of 
dalvik.system.PathClassLoader.toString has changed. For example, I'm getting 
the following on my Android 4.3 device:

dalvik.system.PathClassLoader[DexPathList[[zip file 
"/system/framework/android.test.runner.jar", zip file 
"/data/app/com.abc.def.tests-2.apk", zip file 
"/data/app/com.abc.def-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.abc.d
ef.tests-2, /data/app-lib/com.abd.def-2, /vendor/lib, /system/lib]]]

Options/fixes sorted in the order of increasing time spent before fix is live:
1. Set dexmaker.dexcache system property before your tests start (either in 
your tests' setUp or in a custom InstrumentationTestRunner):
   System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
2. Fix DexMaker's AppDataDirGuesser to understand the new toString format (in a 
backward compatible way).
3. Submit a patch to AOSP to make PathClassLoader expose the path in a 
structured, reliable way.
4. Submit a patch to AOSP to query the location of the current app's cache 
directory without referencing a Context.

Original comment by klyu...@google.com on 1 Aug 2013 at 4:41

GoogleCodeExporter commented 8 years ago
Thanks for writing this issue. It also breaks with EasyMock for Android.

I hope some solution will come up, I use @klyu's number 1 solution and it's 
really ugly.

Original comment by steff.ni...@gmail.com on 21 Aug 2013 at 2:25

GoogleCodeExporter commented 8 years ago
Try polly.k's solution

> Adding this line to setUp() worked around it:
> System.setProperty("dexmaker.dexcache", 
getInstrumentation().getTargetContext().getCacheDir().getPath());

I have successfully used this solution twice and it is working beautifully.  
All of my UI test cases extend a base class, so I just put it in the setUp() in 
the abstract base class and it works wonderfully.

public abstract class BaseInstrumentationTestCase<T extends Activity> extends 
ActivityInstrumentationTestCase2<T> {

 @Override
    protected void setUp() throws Exception {

        super.setUp();

        System.setProperty( "dexmaker.dexcache", getInstrumentation().getTargetContext().getCacheDir().getPath() );

        ...
    }
}

Original comment by david.m...@metova.com on 21 Aug 2013 at 2:43

GoogleCodeExporter commented 8 years ago
Note on #7 klyu's number one solution: if you are setting the system property 
in your InstrumentationTestRunner, remember to use getTargetContext instead of 
getContext, getTargetContext returns the context for the target application 
being instrumented, instead of the instrumentation context.
http://developer.android.com/reference/android/app/Instrumentation.html#getTarge
tContext%28%29

public class InstrumentationTestRunner extends 
android.test.InstrumentationTestRunner {
    @Override
    public void onCreate(Bundle arguments) {
        super.onCreate(arguments);
        System.setProperty("dexmaker.dexcache", getTargetContext().getCacheDir().toString());
    }
...
}

Original comment by dh1...@gmail.com on 26 Aug 2013 at 10:52

GoogleCodeExporter commented 8 years ago
We have just updated out Nexus 7 to 4.3 and are experiencing this issue. For 
now we are holding off on updating any other devices. Is any progress being 
made on this issue?

Original comment by mcclure...@gmail.com on 13 Nov 2013 at 8:58

GoogleCodeExporter commented 8 years ago
+mcclure

There is nothing special to wait for, a patch of dexmaker would make it
easier, but meanwhile just use the dexmaker.dexcache property as proposed
above.

Original comment by steff.ni...@gmail.com on 14 Nov 2013 at 5:34

GoogleCodeExporter commented 8 years ago
We have created a library that is meant to be used both on android, and on a 
standard JVM. We want to run our unit tests in both environments. This prevents 
us from being able to set that property. We cannot turn our tests into 
InstrumentationTestCases, and cannot get a context to get the cacheDir from.

Original comment by mcclure...@gmail.com on 14 Nov 2013 at 4:50

GoogleCodeExporter commented 8 years ago
Here is a diff, a patch that patches this issue. This makes it work in 4.3.

This is #2.

Original comment by jake.sta...@gmail.com on 15 Nov 2013 at 4:26

Attachments:

GoogleCodeExporter commented 8 years ago
This appears to be the case in 4.4 as well. Any update on this?

Original comment by Christin...@gmail.com on 14 Oct 2014 at 2:43

GoogleCodeExporter commented 8 years ago
I am having this issue as well, the suggested work around did the trick:

public void setUp() {
        System.setProperty("dexmaker.dexcache", getInstrumentation().getTargetContext().getCacheDir().getPath());
    }

Original comment by JustinMa...@gmail.com on 1 Feb 2015 at 8:49

GoogleCodeExporter commented 8 years ago
The solution proposed in this thread assumes that all tests have 
instrumentation available. Is it possible to avoid this error in a TestCase or 
AndroidTestCase?

Original comment by bi...@jana.com on 23 Feb 2015 at 3:54

GoogleCodeExporter commented 8 years ago
You could use something like this for TestCase

System.setProperty("dexmaker.dexcache",
                "/data/data/" + BuildConfig.APPLICATION_ID + ".test/cache");

Original comment by Pascal.W...@gmail.com on 9 Mar 2015 at 12:52

GoogleCodeExporter commented 8 years ago
It looks like the dexmaker project has moved to github, see: 
https://code.google.com/p/dexmaker/

In the central repository there are versions 1.1 and 1.2 published in March 
2014 and December 2014: 
https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.google.dexmaker%22%20AND
%20a%3A%22dexmaker%22

I've verified this "dexcache == null" issue still exists through version 1.2 - 
but only on certain devices.  For example, a Galaxy S5 with Android 5.0 has the 
problem, and a Galaxy S4 with Android 4.4.2 does not.

I cloned the github repository (last commit March 12th 2015 - ca74669), and ran 
locally, and the problem has been fixed (there are also commits in the history 
that back this up).  So once there is a 1.3 release, hopefully this problem is 
gone for good!

Anyone else wanting to run a local copy of 1.3-SNAPSHOT, here's how I did that 
(on a Mac, but other platforms should work too):

- git clone https://github.com/crittercism/dexmaker.git
- cd dexmaker
- mvn install -Dmaven.test.skip=true
- cp -R ~/.m2/repository/com/google/dexmaker 
$ANDROID_HOME/extras/android/m2repository/com/google
- Then change version in app/build.gradle: androidTestCompile 
'com.google.dexmaker:dexmaker:1.3-SNAPSHOT'
-- Or pom.xml if using maven to build, or overwrite your libs/dexmaker.jar with 
~/.m2/repository/com/google/dexmaker/dexmaker/1.3-SNAPSHOT/dexmaker-1.3-SNAPSHOT
.jar if you are using eclipse/ant

Thanks,
-Stan

Original comment by akasek on 24 Mar 2015 at 11:15