Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix an issue that Android Instrumentation Test fails #895

Merged
merged 12 commits into from Aug 29, 2022

Conversation

kubode
Copy link
Contributor

@kubode kubode commented Aug 24, 2022

To fix #894.

@kubode kubode marked this pull request as draft August 24, 2022 09:45
@kubode
Copy link
Contributor Author

kubode commented Aug 24, 2022

After checking at hand, another problem arises.
I will look into it a bit.

java.lang.IllegalAccessError: Illegal class access: 'kotlin.sequences.SequencesKt__SequencesKt' attempting to access 'kotlin.sequences.GeneratorSequence' (declaration of 'kotlin.sequences.SequencesKt__SequencesKt' appears in /data/app/~~YbK6coZSvv0ODMk3y0Y_Uw==/myapp.debug-pj9V59qD4OtzIPJvj2zhxg==/base.apk!classes33.dex)
at kotlin.sequences.SequencesKt__SequencesKt.generateSequence(Sequences.kt:641)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation.computeProperties(DeserializedMemberScope.kt:623)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation.access$computeProperties(DeserializedMemberScope.kt:228)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation$properties$1.invoke(DeserializedMemberScope.kt:253)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation$properties$1.invoke(DeserializedMemberScope.kt:253)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:578)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:651)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation.getContributedVariables(DeserializedMemberScope.kt:338)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$OptimizedImplementation.addFunctionsAndPropertiesTo(DeserializedMemberScope.kt:352)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.computeDescriptors(DeserializedMemberScope.kt:115)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope$allDescriptors$1.invoke(DeserializedClassDescriptor.kt:301)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope$allDescriptors$1.invoke(DeserializedClassDescriptor.kt:300)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:408)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(LockBasedStorageManager.java:527)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.getContributedDescriptors(DeserializedClassDescriptor.kt:311)
at kotlin.reflect.jvm.internal.impl.resolve.scopes.ResolutionScope$DefaultImpls.getContributedDescriptors$default(ResolutionScope.kt:50)
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.getMembers(KDeclarationContainerImpl.kt:56)
at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(KClassImpl.kt:162)
at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(KClassImpl.kt:162)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getDeclaredNonStaticMembers(KClassImpl.kt:162)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticMembers$2.invoke(KClassImpl.kt:171)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticMembers$2.invoke(KClassImpl.kt:171)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getAllNonStaticMembers(KClassImpl.kt:171)
at kotlin.reflect.full.KClasses.getMemberProperties(KClasses.kt:148)
at io.mockk.impl.annotations.JvmMockInitializer.initMock(JvmMockInitializer.kt:40)
at io.mockk.impl.annotations.JvmMockInitializer.initAnnotatedMocks(JvmMockInitializer.kt:24)
at MyTest.setUp(MyTest.kt:672)

@kubode
Copy link
Contributor Author

kubode commented Aug 24, 2022

The size of dispatcher.jar is much larger than in 1.12.5.
image

This contains unnecessary class files.
This is because android-application.gradle.kts, which applies the Kotlin plugin, adds a Kotlin dependency to the agent-android app.

@kubode
Copy link
Contributor Author

kubode commented Aug 24, 2022

It is fixed at f770509.
I have confirmed that testing with 1.12.8-SNAPSHOT on my local is successful.

@kubode kubode marked this pull request as ready for review August 24, 2022 10:22
@@ -3,15 +3,24 @@ import buildsrc.config.asProvider
import com.android.build.gradle.internal.tasks.DexMergingTask

plugins {
buildsrc.convention.`android-application`
id("com.android.application")
Copy link
Contributor Author

@kubode kubode Aug 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed android-application.gradle.kts since it is not used except for android-dispatcher module.
Instead, I moved the contents of android-application.gradle.kts to this build.gradle.kts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's intentional that build config that is shareable is defined in buildSrc, even if it's only used in one place. It helps keep the build logic organised and consistent. It makes it easier to compare and contrast the Android Library config to the Android Application config, and easier to see if there's any special treatment that's needed in the subprojects. So I think this should be reverted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, I think it is better to remove android-application.gradle.kts.
:mockk-agent-android-dispatcher module is a very specific Android Application module that only extracts the final DEX file, and the build configuration is completely independent and non-reusable.
If we were to add an Android sample application module in the future and try to reuse the configuration with :mockk-agent-android-dispatcher module, it would add an unnecessary dependency to :mockk-agent-android-dispatcher module and cause the same problems that encountered in this PR.

Copy link
Contributor

@aSemy aSemy Aug 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think the dependency on :mockk-agent-android-dispatcher should be removed from the buildSrc script

edit: I read your comment too quickly and my response doesn't make sense! I'll have another look

@aSemy
Copy link
Contributor

aSemy commented Aug 24, 2022

Do you know if there's a good way to write an automated test for this?

@kubode
Copy link
Contributor Author

kubode commented Aug 25, 2022

How about adding a verification task to make sure that the :mockk-agent-android-dispatcher module has no Kotlin dependencies?


By the way, it seems that there is already an Android Instrumentation Test for :mockk-android, but it doesn't seem to be working on either my local or CI.

https://github.com/mockk/mockk/runs/7992536177?check_suite_focus=true

> Task :modules:mockk-agent-android:connectedDebugAndroidTest
Starting 0 tests on test(AVD) - 8.0.0

I was getting the following error on my local.
It looks like I need to migrate Android Instrumentation Test.
I will try that migration.

2022-08-25 11:28:33.300 12901-12901/io.mockk.proxy.android.test E/AndroidRuntime: FATAL EXCEPTION: main
    Process: io.mockk.proxy.android.test, PID: 12901
    java.lang.RuntimeException: Unable to instantiate instrumentation ComponentInfo{io.mockk.proxy.android.test/android.support.test.runner.AndroidJUnitRunner}: java.lang.ClassNotFoundException: Didn't find class "android.support.test.runner.AndroidJUnitRunner" on path: DexPathList[[zip file "/data/app/~~yFm1Ji-ZgakvYB21oPnWpw==/io.mockk.proxy.android.test-pCFrw66KOowBzyq5tw_P3w==/base.apk"],nativeLibraryDirectories=[/data/app/~~yFm1Ji-ZgakvYB21oPnWpw==/io.mockk.proxy.android.test-pCFrw66KOowBzyq5tw_P3w==/lib/arm64, /data/app/~~yFm1Ji-ZgakvYB21oPnWpw==/io.mockk.proxy.android.test-pCFrw66KOowBzyq5tw_P3w==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]]
        at android.app.ActivityThread.initInstrumentation(ActivityThread.java:6939)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6723)
        at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2134)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7898)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.test.runner.AndroidJUnitRunner" on path: DexPathList[[zip file "/data/app/~~yFm1Ji-ZgakvYB21oPnWpw==/io.mockk.proxy.android.test-pCFrw66KOowBzyq5tw_P3w==/base.apk"],nativeLibraryDirectories=[/data/app/~~yFm1Ji-ZgakvYB21oPnWpw==/io.mockk.proxy.android.test-pCFrw66KOowBzyq5tw_P3w==/lib/arm64, /data/app/~~yFm1Ji-ZgakvYB21oPnWpw==/io.mockk.proxy.android.test-pCFrw66KOowBzyq5tw_P3w==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at android.app.ActivityThread.initInstrumentation(ActivityThread.java:6935)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6723) 
        at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2134) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loopOnce(Looper.java:201) 
        at android.os.Looper.loop(Looper.java:288) 
        at android.app.ActivityThread.main(ActivityThread.java:7898) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) 

androidTestImplementation(kotlin("test"))
androidTestImplementation(kotlin("test-junit"))
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝I thought it would be better to make the test configs common, so I moved them here.

}

testOptions {
execution = "ANDROIDX_TEST_ORCHESTRATOR"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Using Test Orchestrator makes Instrumentation Test stable. Documentation


defaultConfig {
testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments["notAnnotation"] = "io.mockk.test.SkipInstrumentedAndroidTest"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝This class was not included in the test APK and an error log was displayed, so I remove this notAnnotation config.

Comment on lines -12 to -14
@Rule
@JvmField
val rule = ActivityTestRule(TestActivity::class.java)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Removed because it's unnecessary.

@Raibaz Raibaz closed this in #899 Aug 25, 2022
@Raibaz Raibaz reopened this Aug 25, 2022
@Raibaz
Copy link
Collaborator

Raibaz commented Aug 25, 2022

@kubode thanks a lot for putting this together. Is this complete? Can we merge it?

@aSemy
Copy link
Contributor

aSemy commented Aug 25, 2022

@kubode thanks a lot for putting this together. Is this complete? Can we merge it?

I'd like the changes to the buildSrc convention plugin to be reversed, the original problems were fixed in #899

@kubode
Copy link
Contributor Author

kubode commented Aug 26, 2022

#899 does not resolve all issues.
The IllegalAccessError issue remains. (See #895 (comment))
My opinion on the IllegalAccessError is #895 (comment).

Or should I revert the convention plugin and fix the convention plugin so that the IllegalAccessError does not occur?

@aSemy
Copy link
Contributor

aSemy commented Aug 26, 2022

#899 does not resolve all issues. The IllegalAccessError issue remains. (See #895 (comment)) My opinion on the IllegalAccessError is #895 (comment).

Or should I revert the convention plugin and fix the convention plugin so that the IllegalAccessError does not occur?

good point! Can you revert the convention plugin changes, then apply the specific fixes to the subproject's build.gradle.kts

@kubode
Copy link
Contributor Author

kubode commented Aug 26, 2022

good point! Can you revert the convention plugin changes, then apply the specific fixes to the subproject's build.gradle.kts

It is possible, however in that case we need to remove Kotlin plugins from the android-application convention plugin.
Are you okay with this way?

@aSemy
Copy link
Contributor

aSemy commented Aug 26, 2022

Remove kapt and allopen, right? Yeah, go ahead.

kotlin("kapt")
kotlin("plugin.allopen")

@kubode
Copy link
Contributor Author

kubode commented Aug 26, 2022

Fixed!
Also removed kotlin("android") because IllegalAccessError error occurs.

@aSemy
Copy link
Contributor

aSemy commented Aug 26, 2022

Ah okay, I thought that kotlin("jvm") was necessary. I think this is how it was applied before the Kotlin Multiplatform plugin and buildSrc convention plugins updates

apply<KotlinAndroidPluginWrapper>()
extensions.configure(KotlinAndroidProjectExtension::class) {
sourceSets["main"].dependencies {
implementation(Deps.Libs.kotlinStdLib(kotlinVersion()))
}
}

But if it's not necessary, then it can be removed.

@kubode
Copy link
Contributor Author

kubode commented Aug 26, 2022

In agent/android/dispatcher/build.gradle.kts of version 1.12.5, no Kotlin plugin is applied at all.
https://github.com/mockk/mockk/blob/1.12.5/agent/android/dispatcher/build.gradle.kts
So it is correct not to apply the Kotlin plugin.

@aSemy
Copy link
Contributor

aSemy commented Aug 26, 2022

Ah good point, I got confused between mockk-android and mockk-agent-android-dispatcher

# Conflicts:
#	modules/mockk-android/build.gradle.kts
@Raibaz Raibaz merged commit 6c571a6 into mockk:master Aug 29, 2022
@kubode kubode deleted the kubode/fix_android_fails_dispatcher branch August 30, 2022 02:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

mockk-android:1.12.7 always fails with 'dispatcher.jar' not found
3 participants