Skip to content

Commit 5d6e86d

Browse files
committed
fix
1 parent fc5dc74 commit 5d6e86d

2 files changed

Lines changed: 101 additions & 137 deletions

File tree

llm/android/LlamaDemo/app/src/androidTest/java/com/example/executorchllamademo/UIWorkflowTest.kt

Lines changed: 95 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ import org.junit.runner.RunWith
2929
* Prerequisites:
3030
* - Push a .pte model file to /data/local/tmp/llama/
3131
* - Push a tokenizer file (.bin, .json, or .model) to /data/local/tmp/llama/
32-
*
33-
* Model filenames can be configured via instrumentation arguments:
34-
* - modelFile: name of the .pte file (default: stories110M.pte)
35-
* - tokenizerFile: name of the tokenizer file (default: tokenizer.model)
3632
*/
3733
@RunWith(AndroidJUnit4::class)
3834
@LargeTest
@@ -43,6 +39,7 @@ class UIWorkflowTest {
4339
private const val DEFAULT_TOKENIZER_FILE = "tokenizer.model"
4440
private const val TIMEOUT_MS = 5000L
4541
private const val LONG_TIMEOUT_MS = 60000L
42+
private const val PACKAGE_NAME = "com.example.executorchllamademo"
4643
}
4744

4845
private lateinit var device: UiDevice
@@ -53,13 +50,12 @@ class UIWorkflowTest {
5350
fun setUp() {
5451
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
5552

56-
// Read model filenames from instrumentation arguments
5753
val args = InstrumentationRegistry.getArguments()
5854
modelFile = args.getString("modelFile", DEFAULT_MODEL_FILE) ?: DEFAULT_MODEL_FILE
5955
tokenizerFile = args.getString("tokenizerFile", DEFAULT_TOKENIZER_FILE) ?: DEFAULT_TOKENIZER_FILE
6056
Log.i("UIWorkflowTest", "Using model: $modelFile, tokenizer: $tokenizerFile")
6157

62-
// Clear SharedPreferences before each test
58+
// Clear SharedPreferences
6359
val context = InstrumentationRegistry.getInstrumentation().targetContext
6460
val prefs = context.getSharedPreferences(
6561
context.getString(R.string.demo_pref_file_key),
@@ -68,112 +64,93 @@ class UIWorkflowTest {
6864
prefs.edit().clear().commit()
6965
}
7066

71-
/**
72-
* Tests the complete model loading workflow.
73-
*/
7467
@Test
7568
fun testModelLoadingWorkflow() {
7669
ActivityScenario.launch(MainActivity::class.java)
77-
Thread.sleep(1500)
78-
79-
// Dismiss the initial dialog
80-
dismissInitialDialog()
81-
82-
// Click settings button (find by content description)
83-
val settingsButton = device.findObject(UiSelector().descriptionContains("Settings"))
84-
if (settingsButton.exists()) {
85-
settingsButton.click()
86-
} else {
87-
// Try finding by the test tag approach - look for clickable elements
88-
device.findObject(UiSelector().clickable(true).instance(1))?.click()
89-
}
70+
device.wait(Until.hasObject(By.pkg(PACKAGE_NAME).depth(0)), TIMEOUT_MS)
9071
Thread.sleep(1000)
9172

92-
// Verify we're in settings - look for "Load Model" button
93-
val loadModelButton = device.wait(Until.findObject(By.textContains("Load Model")), TIMEOUT_MS)
94-
assertTrue("Load Model button should be visible", loadModelButton != null)
73+
// Dismiss initial dialog
74+
clickButton("OK")
75+
Thread.sleep(500)
9576

96-
// Click model selection
97-
val modelSection = device.findObject(UiSelector().textContains("Model").instance(0))
98-
if (modelSection.exists()) {
99-
// Find and click the file picker button near model text
100-
device.findObject(UiSelector().className("android.widget.Button").instance(0))?.click()
101-
?: device.findObject(UiSelector().clickable(true).instance(2))?.click()
102-
}
77+
// Click settings button (by content description)
78+
clickByDescription("Settings")
79+
Thread.sleep(1000)
80+
81+
// Wait for settings screen
82+
val loadModelVisible = device.wait(Until.hasObject(By.text("Load Model")), TIMEOUT_MS)
83+
assertTrue("Should navigate to settings screen", loadModelVisible)
84+
85+
// Verify model/tokenizer are not selected
86+
assertTrue("Should show no model selected",
87+
device.findObject(UiSelector().textContains("no model")).exists())
88+
assertTrue("Should show no tokenizer selected",
89+
device.findObject(UiSelector().textContains("no tokenizer")).exists())
90+
91+
// Click model select (by description)
92+
clickByDescription("Select Model")
10393
Thread.sleep(500)
10494

105-
// Select model file from dialog
106-
val modelFileItem = device.wait(Until.findObject(By.textContains(modelFile)), TIMEOUT_MS)
107-
modelFileItem?.click()
95+
// Select model file
96+
device.wait(Until.findObject(By.textContains(modelFile)), TIMEOUT_MS)?.click()
10897
Thread.sleep(500)
10998

110-
// Click tokenizer selection
111-
val tokenizerButton = device.findObject(UiSelector().clickable(true).instance(3))
112-
tokenizerButton?.click()
99+
// Click tokenizer select
100+
clickByDescription("Select Tokenizer")
113101
Thread.sleep(500)
114102

115-
// Select tokenizer file from dialog
116-
val tokenizerFileItem = device.wait(Until.findObject(By.textContains(tokenizerFile)), TIMEOUT_MS)
117-
tokenizerFileItem?.click()
103+
// Select tokenizer file
104+
device.wait(Until.findObject(By.textContains(tokenizerFile)), TIMEOUT_MS)?.click()
118105
Thread.sleep(500)
119106

120107
// Click Load Model button
121-
val loadButton = device.findObject(UiSelector().textContains("Load Model"))
122-
if (loadButton.exists() && loadButton.isEnabled) {
123-
loadButton.click()
124-
}
108+
device.findObject(UiSelector().text("Load Model"))?.click()
125109
Thread.sleep(500)
126110

127111
// Confirm dialog
128-
clickDialogButton("OK")
112+
clickButton("OK")
129113
}
130114

131-
/**
132-
* Tests sending a message and receiving a response.
133-
*/
134115
@Test
135116
fun testSendMessageAndReceiveResponse() {
136117
ActivityScenario.launch(MainActivity::class.java)
137-
Thread.sleep(1500)
118+
device.wait(Until.hasObject(By.pkg(PACKAGE_NAME).depth(0)), TIMEOUT_MS)
119+
Thread.sleep(1000)
120+
121+
clickButton("OK")
122+
Thread.sleep(500)
138123

139-
dismissInitialDialog()
140124
loadModel()
141125

142126
// Wait for model to load
143127
val modelLoaded = waitForText("Successfully loaded model", LONG_TIMEOUT_MS)
144128
assertTrue("Model should be loaded successfully", modelLoaded)
145129

146-
// Type message in input field
130+
// Find input field and type message
147131
val inputField = device.findObject(UiSelector().className("android.widget.EditText"))
148132
if (inputField.exists()) {
149133
inputField.setText("tell me a story")
134+
Thread.sleep(500)
150135
}
151-
Thread.sleep(500)
152136

153137
// Click send button
154-
val sendButton = device.findObject(UiSelector().descriptionContains("Send"))
155-
if (sendButton.exists()) {
156-
sendButton.click()
157-
} else {
158-
// Find clickable button near the input
159-
device.findObject(UiSelector().clickable(true).instance(4))?.click()
160-
}
161-
162-
// Wait for response
163-
Thread.sleep(10000) // Wait for generation
138+
clickByDescription("Send")
164139

140+
// Wait for response
141+
Thread.sleep(10000)
165142
Log.i("TEST", "testSendMessageAndReceiveResponse completed")
166143
}
167144

168-
/**
169-
* Tests stopping generation mid-way.
170-
*/
171145
@Test
172146
fun testStopGeneration() {
173147
ActivityScenario.launch(MainActivity::class.java)
174-
Thread.sleep(1500)
148+
device.wait(Until.hasObject(By.pkg(PACKAGE_NAME).depth(0)), TIMEOUT_MS)
149+
Thread.sleep(1000)
150+
151+
clickButton("OK")
152+
Thread.sleep(500)
175153

176-
dismissInitialDialog()
177154
loadModel()
178155

179156
val modelLoaded = waitForText("Successfully loaded model", LONG_TIMEOUT_MS)
@@ -183,142 +160,125 @@ class UIWorkflowTest {
183160
val inputField = device.findObject(UiSelector().className("android.widget.EditText"))
184161
if (inputField.exists()) {
185162
inputField.setText("Write a very long story about a brave knight")
163+
Thread.sleep(500)
186164
}
187-
Thread.sleep(500)
188165

189-
// Click send button
190-
device.findObject(UiSelector().descriptionContains("Send"))?.click()
191-
?: device.findObject(UiSelector().clickable(true).instance(4))?.click()
192-
193-
// Wait for generation to start
166+
// Send
167+
clickByDescription("Send")
194168
Thread.sleep(3000)
195169

196-
// Click stop button (same button, now shows stop)
197-
device.findObject(UiSelector().descriptionContains("Stop"))?.click()
198-
?: device.findObject(UiSelector().clickable(true).instance(4))?.click()
199-
170+
// Click stop
171+
clickByDescription("Stop")
200172
Thread.sleep(1000)
173+
201174
Log.i("STOP_TEST", "Stop generation test completed")
202175
}
203176

204-
/**
205-
* Tests empty prompt behavior.
206-
*/
207177
@Test
208178
fun testEmptyPromptSend() {
209179
ActivityScenario.launch(MainActivity::class.java)
210-
Thread.sleep(1500)
180+
device.wait(Until.hasObject(By.pkg(PACKAGE_NAME).depth(0)), TIMEOUT_MS)
181+
Thread.sleep(1000)
182+
183+
clickButton("OK")
184+
Thread.sleep(500)
211185

212-
dismissInitialDialog()
213186
loadModel()
214187

215188
val modelLoaded = waitForText("Successfully loaded model", LONG_TIMEOUT_MS)
216189
assertTrue("Model should be loaded successfully", modelLoaded)
217190

218-
// Verify send button exists
219-
val sendButton = device.findObject(UiSelector().descriptionContains("Send"))
220-
assertTrue("Send button should exist", sendButton.exists() ||
221-
device.findObject(UiSelector().clickable(true).instance(4)).exists())
222-
223-
// Type some text
191+
// Verify input field exists
224192
val inputField = device.findObject(UiSelector().className("android.widget.EditText"))
225-
if (inputField.exists()) {
226-
inputField.setText("hello")
227-
Thread.sleep(300)
228-
inputField.clearTextField()
229-
}
193+
assertTrue("Input field should exist", inputField.exists())
194+
195+
// Type and clear text
196+
inputField.setText("hello")
197+
Thread.sleep(300)
198+
inputField.clearTextField()
199+
Thread.sleep(300)
230200

231201
Log.i("TEST", "testEmptyPromptSend completed")
232202
}
233203

234-
/**
235-
* Tests file selection dialogs.
236-
*/
237204
@Test
238205
fun testFileSelectionDialogs() {
239206
ActivityScenario.launch(MainActivity::class.java)
240-
Thread.sleep(1500)
207+
device.wait(Until.hasObject(By.pkg(PACKAGE_NAME).depth(0)), TIMEOUT_MS)
208+
Thread.sleep(1000)
241209

242-
dismissInitialDialog()
210+
clickButton("OK")
211+
Thread.sleep(500)
243212

244213
// Go to settings
245-
device.findObject(UiSelector().descriptionContains("Settings"))?.click()
246-
?: device.findObject(UiSelector().clickable(true).instance(1))?.click()
214+
clickByDescription("Settings")
247215
Thread.sleep(1000)
248216

249-
// Click model selection to open dialog
250-
device.findObject(UiSelector().clickable(true).instance(2))?.click()
217+
// Click model selection
218+
clickByDescription("Select Model")
251219
Thread.sleep(500)
252220

253-
// Verify dialog appears
254-
val dialogTitle = device.wait(Until.findObject(By.textContains("Select model")), TIMEOUT_MS)
255-
assertTrue("Model selection dialog should appear", dialogTitle != null)
221+
// Verify model dialog appears
222+
val modelDialog = device.wait(Until.hasObject(By.textContains("Select model")), TIMEOUT_MS)
223+
assertTrue("Model selection dialog should appear", modelDialog)
256224

257-
// Dismiss dialog
258-
clickDialogButton("Cancel")
225+
// Dismiss
226+
clickButton("Cancel")
259227
Thread.sleep(500)
260228

261229
// Click tokenizer selection
262-
device.findObject(UiSelector().clickable(true).instance(3))?.click()
230+
clickByDescription("Select Tokenizer")
263231
Thread.sleep(500)
264232

265233
// Verify tokenizer dialog
266-
val tokenizerDialog = device.wait(Until.findObject(By.textContains("Select tokenizer")), TIMEOUT_MS)
267-
assertTrue("Tokenizer selection dialog should appear", tokenizerDialog != null)
234+
val tokenizerDialog = device.wait(Until.hasObject(By.textContains("Select tokenizer")), TIMEOUT_MS)
235+
assertTrue("Tokenizer selection dialog should appear", tokenizerDialog)
268236

269-
clickDialogButton("Cancel")
237+
clickButton("Cancel")
270238
}
271239

272240
// --- Helper Methods ---
273241

274-
private fun dismissInitialDialog() {
275-
Thread.sleep(500)
276-
clickDialogButton("OK")
277-
Thread.sleep(300)
242+
private fun clickButton(text: String) {
243+
device.findObject(UiSelector().text(text))?.click()
244+
?: device.findObject(UiSelector().textContains(text))?.click()
278245
}
279246

280-
private fun clickDialogButton(buttonText: String) {
281-
val button = device.findObject(UiSelector().text(buttonText))
282-
if (button.exists()) {
283-
button.click()
284-
} else {
285-
// Try case-insensitive
286-
device.findObject(UiSelector().textContains(buttonText))?.click()
287-
}
247+
private fun clickByDescription(description: String) {
248+
device.findObject(UiSelector().description(description))?.click()
249+
?: device.findObject(UiSelector().descriptionContains(description))?.click()
288250
}
289251

290252
private fun loadModel() {
291253
// Go to settings
292-
device.findObject(UiSelector().descriptionContains("Settings"))?.click()
293-
?: device.findObject(UiSelector().clickable(true).instance(1))?.click()
254+
clickByDescription("Settings")
294255
Thread.sleep(1000)
295256

296-
// Select model file
297-
device.findObject(UiSelector().clickable(true).instance(2))?.click()
257+
// Select model
258+
clickByDescription("Select Model")
298259
Thread.sleep(500)
299260
device.wait(Until.findObject(By.textContains(modelFile)), TIMEOUT_MS)?.click()
300261
Thread.sleep(500)
301262

302-
// Select tokenizer file
303-
device.findObject(UiSelector().clickable(true).instance(3))?.click()
263+
// Select tokenizer
264+
clickByDescription("Select Tokenizer")
304265
Thread.sleep(500)
305266
device.wait(Until.findObject(By.textContains(tokenizerFile)), TIMEOUT_MS)?.click()
306267
Thread.sleep(500)
307268

308-
// Click load model
309-
device.findObject(UiSelector().textContains("Load Model"))?.click()
269+
// Load model
270+
device.findObject(UiSelector().text("Load Model"))?.click()
310271
Thread.sleep(500)
311272

312273
// Confirm
313-
clickDialogButton("OK")
274+
clickButton("OK")
314275
Thread.sleep(500)
315276
}
316277

317278
private fun waitForText(text: String, timeoutMs: Long): Boolean {
318279
val startTime = System.currentTimeMillis()
319280
while (System.currentTimeMillis() - startTime < timeoutMs) {
320-
val element = device.findObject(UiSelector().textContains(text))
321-
if (element.exists()) {
281+
if (device.findObject(UiSelector().textContains(text)).exists()) {
322282
return true
323283
}
324284
Thread.sleep(500)

0 commit comments

Comments
 (0)