Alex Newman commited on
Commit
2757bc6
·
unverified ·
2 Parent(s): 01199d4c8152b9

Merge pull request #25 from posix4e/tests

Browse files
puppet/app/build.gradle CHANGED
@@ -1,4 +1,3 @@
1
-
2
  plugins {
3
  id 'com.android.application'
4
  id 'org.jetbrains.kotlin.android'
@@ -16,10 +15,17 @@ android {
16
  }
17
  defaultConfig {
18
  applicationId "com.ttt246.puppet"
19
- minSdkVersion 32
20
  versionCode 1
21
  versionName "1.0"
22
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 
 
 
 
 
 
 
23
  }
24
 
25
  buildTypes {
@@ -35,13 +41,15 @@ android {
35
  }
36
  }
37
 
38
-
39
  dependencies {
40
  implementation 'androidx.appcompat:appcompat:1.6.1'
41
  implementation 'com.google.android.material:material:1.9.0'
42
- implementation 'com.eclipsesource.j2v8:j2v8:6.2.1@aar'
43
  implementation 'androidx.core:core-ktx:1.10.1'
 
44
  testImplementation 'junit:junit:4.13.2'
45
  androidTestImplementation 'androidx.test.ext:junit:1.1.5'
46
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
 
 
 
47
  }
 
 
1
  plugins {
2
  id 'com.android.application'
3
  id 'org.jetbrains.kotlin.android'
 
15
  }
16
  defaultConfig {
17
  applicationId "com.ttt246.puppet"
18
+ minSdkVersion 30
19
  versionCode 1
20
  versionName "1.0"
21
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
22
+
23
+ // Enable unit tests to run off the device using the JVM.
24
+ testOptions {
25
+ unitTests {
26
+ includeAndroidResources = true
27
+ }
28
+ }
29
  }
30
 
31
  buildTypes {
 
41
  }
42
  }
43
 
 
44
  dependencies {
45
  implementation 'androidx.appcompat:appcompat:1.6.1'
46
  implementation 'com.google.android.material:material:1.9.0'
 
47
  implementation 'androidx.core:core-ktx:1.10.1'
48
+ implementation 'androidx.test:core-ktx:1.5.0'
49
  testImplementation 'junit:junit:4.13.2'
50
  androidTestImplementation 'androidx.test.ext:junit:1.1.5'
51
+
52
+ // Add Robolectric and Mockito dependencies for unit testing.
53
+ testImplementation 'org.robolectric:robolectric:4.7.2'
54
+ testImplementation 'org.mockito:mockito-core:4.1.0'
55
  }
puppet/app/src/androidTest/java/com/ttt246/puppet/MyAccessibilityServiceTest.kt CHANGED
@@ -1,31 +0,0 @@
1
- package com.ttt246.puppet
2
-
3
- import android.content.pm.PackageManager
4
- import android.util.Log
5
- import androidx.test.ext.junit.rules.ActivityScenarioRule
6
- import androidx.test.ext.junit.runners.AndroidJUnit4
7
- import androidx.test.platform.app.InstrumentationRegistry
8
- import org.junit.Rule
9
- import org.junit.Test
10
- import org.junit.runner.RunWith
11
-
12
- @RunWith(AndroidJUnit4::class)
13
- class MyAccessibilityServiceTest {
14
- @get:Rule
15
- var rule: ActivityScenarioRule<ChatterAct> = ActivityScenarioRule(ChatterAct::class.java)
16
-
17
- private val context = InstrumentationRegistry.getInstrumentation().targetContext
18
-
19
- @Test
20
- fun testHandleEvent() {
21
- val myService = PuppetAS()
22
- val packageManager = context.packageManager
23
-
24
- val applications = packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
25
- for (applicationInfo in applications) {
26
- val packageName = applicationInfo.packageName
27
- val appName = packageManager.getApplicationLabel(applicationInfo).toString()
28
- Log.d("AppList", "App: $appName, Package: $packageName")
29
- }
30
- }
31
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
puppet/app/src/main/java/com/ttt246/puppet/ChatterAct.kt CHANGED
@@ -8,7 +8,6 @@ import android.provider.Settings
8
  import android.webkit.WebView
9
  import android.widget.Button
10
  import androidx.appcompat.app.AppCompatActivity
11
- import com.eclipsesource.v8.V8
12
 
13
  class ChatterAct : AppCompatActivity() {
14
  private lateinit var webView: WebView
 
8
  import android.webkit.WebView
9
  import android.widget.Button
10
  import androidx.appcompat.app.AppCompatActivity
 
11
 
12
  class ChatterAct : AppCompatActivity() {
13
  private lateinit var webView: WebView
puppet/app/src/main/java/com/ttt246/puppet/PuppetAS.kt CHANGED
@@ -20,7 +20,7 @@ import java.util.LinkedList
20
  import java.util.Queue
21
 
22
 
23
- class PuppetAS : AccessibilityService() {
24
  private fun getServerUrl(): String =
25
  PreferenceManager.getDefaultSharedPreferences(this).getString("SERVER_URL", "") ?: ""
26
 
@@ -42,27 +42,27 @@ class PuppetAS : AccessibilityService() {
42
  Thread {
43
  while (true) {
44
  val uid = getUUID()
45
- if (logs.isNotEmpty()) {
46
- try {
47
- heartbeat(uid, logs.joinToString())
48
- } catch (e: Exception) {
49
- Log.e("PuppetAS", "Error in sending POST request: ${e.message}")
50
- } finally {
51
- logs.clear()
52
  }
 
 
 
 
 
 
53
  }
54
- Thread.sleep((1000..3000).random().toLong())
55
  }
56
  }.start()
57
  }
58
 
59
- private fun heartbeat(uid: String, logMessage: String) {
60
  val serverUrl = getServerUrl()
61
  val url = URL("$serverUrl/send_event")
62
- val jsonObject = JSONObject().apply {
63
- put("uid", uid)
64
- put("event", logMessage)
65
- }
66
 
67
  val conn = url.openConnection() as HttpURLConnection
68
  conn.requestMethod = "POST"
@@ -101,7 +101,7 @@ class PuppetAS : AccessibilityService() {
101
  }
102
  }
103
 
104
- private fun processCommands(commands: List<String>) {
105
  commands.forEach { command ->
106
  when {
107
  isIntentCommand(command) -> executeIntentCommand(command)
@@ -111,15 +111,15 @@ class PuppetAS : AccessibilityService() {
111
  }
112
  }
113
 
114
- private fun isIntentCommand(command: String): Boolean {
115
  return command.startsWith("intent:")
116
  }
117
 
118
- private fun isAccCommand(command: String): Boolean {
119
  return command.startsWith("acc:")
120
  }
121
 
122
- private fun executeAccCommand(command: String) {
123
  val accCommand = command.removePrefix("acc:")
124
  Log.i("PuppetAS", "Executing Acc command: $accCommand")
125
 
@@ -136,8 +136,8 @@ class PuppetAS : AccessibilityService() {
136
  }
137
 
138
  accCommand.startsWith("TYPE") -> {
139
- if (accCommand == "TYPE FIRST") {
140
- val text = "default text" // or whatever text you want to input
141
  val arguments = Bundle()
142
  arguments.putCharSequence(
143
  AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text
@@ -145,10 +145,16 @@ class PuppetAS : AccessibilityService() {
145
  getFirstTypeableNode()?.performAction(
146
  AccessibilityNodeInfo.ACTION_SET_TEXT, arguments
147
  )
148
- } else {
149
- val id = accCommand.removePrefix("TYPE ").substringBefore("\"").trim()
150
- val text = accCommand.substringAfter("\"").removeSuffix("\"")
151
- typeInView(id, text)
 
 
 
 
 
 
152
  }
153
  }
154
  }
@@ -227,25 +233,14 @@ class PuppetAS : AccessibilityService() {
227
 
228
  private fun clickView(id: String) {
229
  val rootNode = rootInActiveWindow ?: return
230
- val nodes = rootNode.findAccessibilityNodeInfosByViewId(id)
231
- nodes.forEach {
232
- it.performAction(AccessibilityNodeInfo.ACTION_CLICK)
233
- }
234
- }
235
 
236
- private fun typeInView(id: String, text: String) {
237
- val rootNode = rootInActiveWindow ?: return
238
- val nodes = rootNode.findAccessibilityNodeInfosByViewId(id)
239
  nodes.forEach {
240
- val arguments = Bundle()
241
- arguments.putCharSequence(
242
- AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text
243
- )
244
- it.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
245
  }
246
  }
247
 
248
- private fun executeIntentCommand(command: String) {
249
  val intentCommand = command.removePrefix("intent:")
250
 
251
  Log.i("PuppetAS", "Executing Intent command: $intentCommand")
 
20
  import java.util.Queue
21
 
22
 
23
+ open class PuppetAS : AccessibilityService() {
24
  private fun getServerUrl(): String =
25
  PreferenceManager.getDefaultSharedPreferences(this).getString("SERVER_URL", "") ?: ""
26
 
 
42
  Thread {
43
  while (true) {
44
  val uid = getUUID()
45
+ try {
46
+ val logMessage = logs.joinToString()
47
+ val jsonObject = JSONObject().apply {
48
+ put("uid", uid)
49
+ put("event", logMessage)
 
 
50
  }
51
+ heartbeat(jsonObject)
52
+ } catch (e: Exception) {
53
+ Log.e("PuppetAS", "Error in sending POST request: ${e.message}")
54
+ } finally {
55
+ logs.clear()
56
+ Thread.sleep((1000..3000).random().toLong())
57
  }
 
58
  }
59
  }.start()
60
  }
61
 
62
+ private fun heartbeat(jsonObject: JSONObject) {
63
  val serverUrl = getServerUrl()
64
  val url = URL("$serverUrl/send_event")
65
+
 
 
 
66
 
67
  val conn = url.openConnection() as HttpURLConnection
68
  conn.requestMethod = "POST"
 
101
  }
102
  }
103
 
104
+ fun processCommands(commands: List<String>) {
105
  commands.forEach { command ->
106
  when {
107
  isIntentCommand(command) -> executeIntentCommand(command)
 
111
  }
112
  }
113
 
114
+ fun isIntentCommand(command: String): Boolean {
115
  return command.startsWith("intent:")
116
  }
117
 
118
+ fun isAccCommand(command: String): Boolean {
119
  return command.startsWith("acc:")
120
  }
121
 
122
+ fun executeAccCommand(command: String) {
123
  val accCommand = command.removePrefix("acc:")
124
  Log.i("PuppetAS", "Executing Acc command: $accCommand")
125
 
 
136
  }
137
 
138
  accCommand.startsWith("TYPE") -> {
139
+ if (accCommand.startsWith("TYPE FIRST ")) {
140
+ val text = accCommand.substringAfter("TYPE FIRST ")
141
  val arguments = Bundle()
142
  arguments.putCharSequence(
143
  AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text
 
145
  getFirstTypeableNode()?.performAction(
146
  AccessibilityNodeInfo.ACTION_SET_TEXT, arguments
147
  )
148
+ } else if (accCommand.startsWith("TYPE HERE")) {
149
+ val focusedNode: AccessibilityNodeInfo? = rootInActiveWindow.findFocus(AccessibilityNodeInfo.FOCUS_INPUT)
150
+ val text = accCommand.substringAfter("TYPE HERE ")
151
+ val arguments = Bundle()
152
+ arguments.putCharSequence(
153
+ AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text
154
+ )
155
+ focusedNode?.performAction(
156
+ AccessibilityNodeInfo.ACTION_SET_TEXT, arguments
157
+ )
158
  }
159
  }
160
  }
 
233
 
234
  private fun clickView(id: String) {
235
  val rootNode = rootInActiveWindow ?: return
236
+ val nodes = rootNode.findAccessibilityNodeInfosByText(id)
 
 
 
 
237
 
 
 
 
238
  nodes.forEach {
239
+ it.performAction(AccessibilityNodeInfo.ACTION_CLICK)
 
 
 
 
240
  }
241
  }
242
 
243
+ fun executeIntentCommand(command: String) {
244
  val intentCommand = command.removePrefix("intent:")
245
 
246
  Log.i("PuppetAS", "Executing Intent command: $intentCommand")
puppet/app/src/test/java/com/ttt246/puppet/PuppetASTest.kt ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package com.ttt246.puppet
2
+ import android.content.Context
3
+ import androidx.test.core.app.ApplicationProvider
4
+ import org.robolectric.RobolectricTestRunner
5
+ import org.robolectric.annotation.Config
6
+ import org.junit.runner.RunWith
7
+ import org.junit.Test
8
+ import org.junit.Before
9
+ import org.mockito.Mockito
10
+
11
+ class TestablePuppetAS : PuppetAS() {
12
+ fun attachBaseContextPublic(context: Context) {
13
+ attachBaseContext(context)
14
+ }
15
+ }
16
+
17
+
18
+ @RunWith(RobolectricTestRunner::class)
19
+ @Config(sdk = [Config.OLDEST_SDK])
20
+ class PuppetASTest {
21
+ private lateinit var puppetService: TestablePuppetAS
22
+
23
+ @Before
24
+ fun setUp() {
25
+ puppetService = Mockito.spy(TestablePuppetAS())
26
+ val context = ApplicationProvider.getApplicationContext<Context>()
27
+ puppetService.attachBaseContextPublic(context)
28
+ }
29
+
30
+ @Test
31
+ fun processCommands_executesIntentCommands() {
32
+ val command = "intent:test"
33
+ puppetService.processCommands(listOf(command))
34
+ Mockito.verify(puppetService).executeIntentCommand("intent:test")
35
+ }
36
+
37
+ @Test
38
+ fun processCommands_executesAccCommands() {
39
+ val command = "acc:UP"
40
+ puppetService.processCommands(listOf(command))
41
+
42
+ Mockito.verify(puppetService).executeAccCommand(command)
43
+ }
44
+ }
puppet/app/src/test/java/com/ttt246/puppet/SumTest.kt CHANGED
@@ -1,17 +0,0 @@
1
- package com.ttt246.puppet
2
-
3
-
4
- import org.junit.Assert.assertEquals
5
- import org.junit.Test
6
-
7
- /**
8
- * Example local unit test, which will execute on the development machine (host).
9
- *
10
- * See [testing documentation](http://d.android.com/tools/testing).
11
- */
12
- class SumTest {
13
- @Test
14
- fun addition_isCorrect() {
15
- assertEquals(4, 2 + 2)
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
puppet/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker ADDED
@@ -0,0 +1 @@
 
 
1
+ mock-maker-inline