Skip to content

Commit d984b2c

Browse files
authored
Merge pull request #156 from solrudev/develop
0.19.2
2 parents 4fb2642 + a5bacd5 commit d984b2c

45 files changed

Lines changed: 2818 additions & 21 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ jobs:
1515
runs-on: ubuntu-latest
1616
name: Build Ackpine
1717

18+
permissions:
19+
checks: write
20+
1821
steps:
1922
- name: Checkout
2023
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # 6.0.0
@@ -34,6 +37,16 @@ jobs:
3437
run: |
3538
./gradlew :buildAckpine --stacktrace
3639
40+
- name: Run tests
41+
run: |
42+
./gradlew test
43+
44+
- name: Publish test report
45+
uses: mikepenz/action-junit-report@a294a61c909bd8a4b563024a2faa28897fd53ebc # 6.1.0
46+
if: success() || failure()
47+
with:
48+
report_paths: '**/build/test-results/*/TEST-*.xml'
49+
3750
status-check:
3851
runs-on: ubuntu-latest
3952
if: always()

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Ackpine depends on Jetpack libraries, so it's also necessary to add the `google(
3737

3838
```toml
3939
[versions]
40-
ackpine = "0.19.1"
40+
ackpine = "0.19.2"
4141

4242
[libraries]
4343
ackpine-core = { module = "ru.solrudev.ackpine:ackpine-core", version.ref = "ackpine" }
@@ -60,6 +60,9 @@ ackpine-shizuku = { module = "ru.solrudev.ackpine:ackpine-shizuku", version.ref
6060
# optional - Kotlin extensions for Shizuku plugin
6161
ackpine-shizuku-ktx = { module = "ru.solrudev.ackpine:ackpine-shizuku-ktx", version.ref = "ackpine" }
6262

63+
# optional - testing utilities
64+
ackpine-test = { module = "ru.solrudev.ackpine:ackpine-test", version.ref = "ackpine" }
65+
6366
[bundles]
6467
ackpine = [
6568
"ackpine-core",
@@ -78,7 +81,7 @@ ackpine = [
7881

7982
```kotlin
8083
dependencies {
81-
val ackpineVersion = "0.19.1"
84+
val ackpineVersion = "0.19.2"
8285
implementation("ru.solrudev.ackpine:ackpine-core:$ackpineVersion")
8386

8487
// optional - Kotlin extensions and Coroutines support
@@ -98,6 +101,9 @@ dependencies {
98101

99102
// optional - Kotlin extensions for Shizuku plugin
100103
implementation("ru.solrudev.ackpine:ackpine-shizuku-ktx:$ackpineVersion")
104+
105+
// optional - testing utilities
106+
testImplementation("ru.solrudev.ackpine:ackpine-test:$ackpineVersion")
101107
}
102108
```
103109
</details>

ackpine-resources/api/ackpine-resources.api

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ public final class ru/solrudev/ackpine/resources/ResolvableString$Companion {
1717

1818
public abstract class ru/solrudev/ackpine/resources/ResolvableString$Resource : ru/solrudev/ackpine/resources/ResolvableString {
1919
public fun <init> ([Ljava/io/Serializable;)V
20-
public final fun equals (Ljava/lang/Object;)Z
21-
public final fun hashCode ()I
20+
public fun equals (Ljava/lang/Object;)Z
21+
public fun hashCode ()I
2222
public final fun resolve (Landroid/content/Context;)Ljava/lang/String;
2323
protected abstract fun stringId ()I
2424
}

ackpine-resources/src/main/kotlin/ru/solrudev/ackpine/resources/ResolvableString.kt

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package ru.solrudev.ackpine.resources
2020

2121
import android.content.Context
2222
import androidx.annotation.StringRes
23+
import ru.solrudev.ackpine.resources.ResolvableString.Resource
2324
import java.io.Serializable
2425

2526
/**
@@ -73,12 +74,12 @@ public sealed interface ResolvableString : Serializable {
7374
}
7475

7576
/**
76-
* Creates an anonymous instance of [ResolvableString.Resource], which is a [ResolvableString] backed by
77+
* Creates a transient instance of [ResolvableString.Resource], which is a [ResolvableString] backed by
7778
* Android resource string with optional [arguments][args]. Arguments can be
7879
* [ResolvableStrings][ResolvableString] as well.
7980
*
80-
* This factory is meant to create only **transient** strings, i.e. not persisted in storage. For persisted
81-
* strings [ResolvableString.Resource] should be explicitly subclassed. Example:
81+
* This factory is meant to create only **transient** strings, i.e. not persisted in storage, because string IDs
82+
* are not stable. For persisted strings [ResolvableString.Resource] should be explicitly subclassed. Example:
8283
* ```
8384
* object InstallMessageTitle : ResolvableString.Resource() {
8485
* override fun stringId() = R.string.install_message_title
@@ -97,12 +98,9 @@ public sealed interface ResolvableString : Serializable {
9798
* @param stringId Android string resource ID
9899
* @param args string format arguments
99100
*/
100-
@Suppress("serial")
101101
@JvmStatic
102102
public fun transientResource(@StringRes stringId: Int, vararg args: Serializable): ResolvableString {
103-
return object : Resource(*args) {
104-
override fun stringId() = stringId
105-
}
103+
return TransientResource(stringId, args)
106104
}
107105
}
108106

@@ -147,14 +145,14 @@ public sealed interface ResolvableString : Serializable {
147145
}
148146
}.toTypedArray()
149147

150-
final override fun equals(other: Any?): Boolean {
148+
override fun equals(other: Any?): Boolean {
151149
if (this === other) return true
152150
if (javaClass != other?.javaClass) return false
153151
other as Resource
154152
return args.contentEquals(other.args)
155153
}
156154

157-
final override fun hashCode(): Int {
155+
override fun hashCode(): Int {
158156
return args.contentHashCode()
159157
}
160158

@@ -164,6 +162,34 @@ public sealed interface ResolvableString : Serializable {
164162
}
165163
}
166164

165+
private class TransientResource(
166+
@param:StringRes private val stringId: Int,
167+
private val args: Array<out Serializable>
168+
) : Resource(stringId, args) {
169+
170+
override fun stringId() = stringId
171+
172+
override fun equals(other: Any?): Boolean {
173+
if (this === other) return true
174+
if (javaClass != other?.javaClass) return false
175+
other as TransientResource
176+
if (stringId != other.stringId) return false
177+
if (!args.contentDeepEquals(other.args)) return false
178+
return true
179+
}
180+
181+
override fun hashCode(): Int {
182+
var result = super.hashCode()
183+
result = 31 * result + stringId
184+
result = 31 * result + args.contentDeepHashCode()
185+
return result
186+
}
187+
188+
private companion object {
189+
private const val serialVersionUID: Long = 2599070109225891907L
190+
}
191+
}
192+
167193
private data object Empty : ResolvableString {
168194
private const val serialVersionUID = 5194188194930148316L
169195
override fun resolve(context: Context): String = ""

ackpine-test/api/ackpine-test.api

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
public abstract interface class ru/solrudev/ackpine/test/TestInstallSessionFactory {
2+
public static final field Companion Lru/solrudev/ackpine/test/TestInstallSessionFactory$Companion;
3+
public abstract fun create (Ljava/util/UUID;Lru/solrudev/ackpine/installer/parameters/InstallParameters;)Lru/solrudev/ackpine/test/TestProgressSession;
4+
}
5+
6+
public final class ru/solrudev/ackpine/test/TestInstallSessionFactory$Companion {
7+
}
8+
9+
public final class ru/solrudev/ackpine/test/TestPackageInstaller : ru/solrudev/ackpine/installer/PackageInstaller {
10+
public fun <init> ()V
11+
public fun <init> (Lru/solrudev/ackpine/test/TestInstallSessionFactory;)V
12+
public synthetic fun <init> (Lru/solrudev/ackpine/test/TestInstallSessionFactory;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13+
public fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;)V
14+
public final fun clearSessions ()V
15+
public synthetic fun createSession (Lru/solrudev/ackpine/installer/parameters/InstallParameters;)Lru/solrudev/ackpine/session/ProgressSession;
16+
public fun createSession (Lru/solrudev/ackpine/installer/parameters/InstallParameters;)Lru/solrudev/ackpine/test/TestProgressSession;
17+
public fun getActiveSessionsAsync ()Lcom/google/common/util/concurrent/ListenableFuture;
18+
public fun getSessionAsync (Ljava/util/UUID;)Lcom/google/common/util/concurrent/ListenableFuture;
19+
public final fun getSessions ()Ljava/util/List;
20+
public fun getSessionsAsync ()Lcom/google/common/util/concurrent/ListenableFuture;
21+
public final fun seedSession (Lru/solrudev/ackpine/test/TestProgressSession;)V
22+
}
23+
24+
public final class ru/solrudev/ackpine/test/TestPackageUninstaller : ru/solrudev/ackpine/uninstaller/PackageUninstaller {
25+
public fun <init> ()V
26+
public fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;)V
27+
public fun <init> (Lru/solrudev/ackpine/test/TestUninstallSessionFactory;)V
28+
public synthetic fun <init> (Lru/solrudev/ackpine/test/TestUninstallSessionFactory;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
29+
public final fun clearSessions ()V
30+
public synthetic fun createSession (Lru/solrudev/ackpine/uninstaller/parameters/UninstallParameters;)Lru/solrudev/ackpine/session/Session;
31+
public fun createSession (Lru/solrudev/ackpine/uninstaller/parameters/UninstallParameters;)Lru/solrudev/ackpine/test/TestSession;
32+
public fun getActiveSessionsAsync ()Lcom/google/common/util/concurrent/ListenableFuture;
33+
public fun getSessionAsync (Ljava/util/UUID;)Lcom/google/common/util/concurrent/ListenableFuture;
34+
public final fun getSessions ()Ljava/util/List;
35+
public fun getSessionsAsync ()Lcom/google/common/util/concurrent/ListenableFuture;
36+
public final fun seedSession (Lru/solrudev/ackpine/test/TestSession;)V
37+
}
38+
39+
public final class ru/solrudev/ackpine/test/TestProgressSession : ru/solrudev/ackpine/test/TestSession, ru/solrudev/ackpine/session/ProgressSession {
40+
public fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;)V
41+
public fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;Ljava/util/UUID;)V
42+
public fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;Ljava/util/UUID;Lru/solrudev/ackpine/session/Session$State;)V
43+
public fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;Ljava/util/UUID;Lru/solrudev/ackpine/session/Session$State;Lru/solrudev/ackpine/session/Progress;)V
44+
public synthetic fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;Ljava/util/UUID;Lru/solrudev/ackpine/session/Session$State;Lru/solrudev/ackpine/session/Progress;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
45+
public fun addProgressListener (Lru/solrudev/ackpine/DisposableSubscriptionContainer;Lru/solrudev/ackpine/session/ProgressSession$ProgressListener;)Lru/solrudev/ackpine/DisposableSubscription;
46+
public final fun getProgress ()Lru/solrudev/ackpine/session/Progress;
47+
public final fun getProgressHistory ()Ljava/util/List;
48+
public fun removeProgressListener (Lru/solrudev/ackpine/session/ProgressSession$ProgressListener;)V
49+
public fun reset (Lru/solrudev/ackpine/session/Session$State;Z)V
50+
public final fun resetProgress ()V
51+
public final fun resetProgress (Lru/solrudev/ackpine/session/Progress;)V
52+
public final fun resetProgress (Lru/solrudev/ackpine/session/Progress;Z)V
53+
public static synthetic fun resetProgress$default (Lru/solrudev/ackpine/test/TestProgressSession;Lru/solrudev/ackpine/session/Progress;ZILjava/lang/Object;)V
54+
}
55+
56+
public final class ru/solrudev/ackpine/test/TestSdkInt {
57+
public static final field INSTANCE Lru/solrudev/ackpine/test/TestSdkInt;
58+
public static final fun get ()I
59+
public static final fun reset ()V
60+
public static final fun set (I)V
61+
}
62+
63+
public class ru/solrudev/ackpine/test/TestSession : ru/solrudev/ackpine/session/Session {
64+
public fun <init> ()V
65+
public fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;)V
66+
public fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;Ljava/util/UUID;)V
67+
public fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;Ljava/util/UUID;Lru/solrudev/ackpine/session/Session$State;)V
68+
public synthetic fun <init> (Lru/solrudev/ackpine/test/TestSessionScript;Ljava/util/UUID;Lru/solrudev/ackpine/session/Session$State;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
69+
public fun addStateListener (Lru/solrudev/ackpine/DisposableSubscriptionContainer;Lru/solrudev/ackpine/session/Session$StateListener;)Lru/solrudev/ackpine/DisposableSubscription;
70+
public fun cancel ()V
71+
public fun commit ()Z
72+
public final fun getController ()Lru/solrudev/ackpine/test/TestSessionController;
73+
public fun getId ()Ljava/util/UUID;
74+
public final fun getState ()Lru/solrudev/ackpine/session/Session$State;
75+
public final fun getStateHistory ()Ljava/util/List;
76+
public fun isActive ()Z
77+
public fun isCancelled ()Z
78+
public fun isCompleted ()Z
79+
public fun launch ()Z
80+
public fun removeStateListener (Lru/solrudev/ackpine/session/Session$StateListener;)V
81+
public final fun reset ()V
82+
public final fun reset (Lru/solrudev/ackpine/session/Session$State;)V
83+
public fun reset (Lru/solrudev/ackpine/session/Session$State;Z)V
84+
public static synthetic fun reset$default (Lru/solrudev/ackpine/test/TestSession;Lru/solrudev/ackpine/session/Session$State;ZILjava/lang/Object;)V
85+
}
86+
87+
public final class ru/solrudev/ackpine/test/TestSessionController {
88+
public synthetic fun <init> (Lru/solrudev/ackpine/test/TestSession;Lru/solrudev/ackpine/test/TestSessionScript;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
89+
public final fun cancel ()Lru/solrudev/ackpine/test/TestSessionController;
90+
public final fun fail (Lru/solrudev/ackpine/session/Failure;)Lru/solrudev/ackpine/test/TestSessionController;
91+
public final fun getCancelCalls ()I
92+
public final fun getCommitCalls ()I
93+
public final fun getLaunchCalls ()I
94+
public final fun resetCalls ()Lru/solrudev/ackpine/test/TestSessionController;
95+
public final fun setProgress (Lru/solrudev/ackpine/session/Progress;)Lru/solrudev/ackpine/test/TestSessionController;
96+
public final fun setState (Lru/solrudev/ackpine/session/Session$State;)Lru/solrudev/ackpine/test/TestSessionController;
97+
public final fun succeed ()Lru/solrudev/ackpine/test/TestSessionController;
98+
}
99+
100+
public final class ru/solrudev/ackpine/test/TestSessionScript {
101+
public static final field Companion Lru/solrudev/ackpine/test/TestSessionScript$Companion;
102+
public static final fun auto (Lru/solrudev/ackpine/session/Session$State$Terminal;)Lru/solrudev/ackpine/test/TestSessionScript;
103+
public final fun clear ()Lru/solrudev/ackpine/test/TestSessionScript;
104+
public final fun clearCancel ()Lru/solrudev/ackpine/test/TestSessionScript;
105+
public final fun clearCommit ()Lru/solrudev/ackpine/test/TestSessionScript;
106+
public final fun clearLaunch ()Lru/solrudev/ackpine/test/TestSessionScript;
107+
public static final fun empty ()Lru/solrudev/ackpine/test/TestSessionScript;
108+
public final fun onCancel (Lru/solrudev/ackpine/session/Session$State;)Lru/solrudev/ackpine/test/TestSessionScript;
109+
public final fun onCommit ([Lru/solrudev/ackpine/session/Session$State;)Lru/solrudev/ackpine/test/TestSessionScript;
110+
public final fun onLaunch ([Lru/solrudev/ackpine/session/Session$State;)Lru/solrudev/ackpine/test/TestSessionScript;
111+
}
112+
113+
public final class ru/solrudev/ackpine/test/TestSessionScript$Companion {
114+
public final fun auto (Lru/solrudev/ackpine/session/Session$State$Terminal;)Lru/solrudev/ackpine/test/TestSessionScript;
115+
public final fun empty ()Lru/solrudev/ackpine/test/TestSessionScript;
116+
}
117+
118+
public abstract interface class ru/solrudev/ackpine/test/TestUninstallSessionFactory {
119+
public static final field Companion Lru/solrudev/ackpine/test/TestUninstallSessionFactory$Companion;
120+
public abstract fun create (Ljava/util/UUID;Lru/solrudev/ackpine/uninstaller/parameters/UninstallParameters;)Lru/solrudev/ackpine/test/TestSession;
121+
}
122+
123+
public final class ru/solrudev/ackpine/test/TestUninstallSessionFactory$Companion {
124+
}
125+
126+
public final class ru/solrudev/ackpine/test/futures/ImmediateFuture : com/google/common/util/concurrent/ListenableFuture {
127+
public static final field Companion Lru/solrudev/ackpine/test/futures/ImmediateFuture$Companion;
128+
public synthetic fun <init> (Ljava/lang/Object;Ljava/lang/Throwable;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
129+
public fun addListener (Ljava/lang/Runnable;Ljava/util/concurrent/Executor;)V
130+
public fun cancel (Z)Z
131+
public static final fun failure (Ljava/lang/Throwable;)Lru/solrudev/ackpine/test/futures/ImmediateFuture;
132+
public fun get ()Ljava/lang/Object;
133+
public fun get (JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;
134+
public fun isCancelled ()Z
135+
public fun isDone ()Z
136+
public static final fun success (Ljava/lang/Object;)Lru/solrudev/ackpine/test/futures/ImmediateFuture;
137+
}
138+
139+
public final class ru/solrudev/ackpine/test/futures/ImmediateFuture$Companion {
140+
public final fun failure (Ljava/lang/Throwable;)Lru/solrudev/ackpine/test/futures/ImmediateFuture;
141+
public final fun success (Ljava/lang/Object;)Lru/solrudev/ackpine/test/futures/ImmediateFuture;
142+
}
143+

ackpine-test/build.gradle.kts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (C) 2026 Ilya Fomichev
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+
description = "Testing utilities for Ackpine"
18+
19+
plugins {
20+
id("ru.solrudev.ackpine.library")
21+
id("ru.solrudev.ackpine.library-publish")
22+
id("ru.solrudev.ackpine.dokka")
23+
}
24+
25+
ackpine {
26+
id = "test"
27+
artifact {
28+
name = "Ackpine Test"
29+
inceptionYear = "2026"
30+
}
31+
}
32+
33+
dependencies {
34+
api(projects.ackpineApi.apiMain)
35+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (C) 2026 Ilya Fomichev
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 ru.solrudev.ackpine
18+
19+
import ru.solrudev.ackpine.test.TestSdkInt
20+
21+
@Suppress("Unused")
22+
internal object SdkInt {
23+
@JvmSynthetic
24+
@JvmName("get")
25+
fun get() = TestSdkInt.get()
26+
}

0 commit comments

Comments
 (0)