Skip to content

Commit

Permalink
fixup emulator-based tests
Browse files Browse the repository at this point in the history
  • Loading branch information
t184256 committed Jun 14, 2024
1 parent 87f1488 commit 93f4f7e
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 33 deletions.
43 changes: 21 additions & 22 deletions .github/workflows/emulator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ on:
- cron: 0 0 * * 1

jobs:
emulator:
emulate:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
api-level: [29]
way: [flakes, channel]
api-level: [28, 29, 30, 33, 34]
way: [bootstrap_channels]
#way: [bootstrap_flakes, test_channels_uiautomator, test_channels_shell]

steps:
- name: Checkout repository
Expand All @@ -27,6 +29,9 @@ jobs:
name: nix-on-droid
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"

- name: Build droidctl
run: nix build 'github:t184256/droidctl' --out-link droidctl

- name: Configure AVD cache
uses: actions/cache@v4
id: avd-cache
Expand All @@ -40,42 +45,36 @@ jobs:
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
target: default
api-level: ${{ matrix.api-level }}
arch: x86_64
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
disable-animations: true
script: echo "Generated AVD snapshot for caching."

- name: Test using channels api-level=${{ matrix.api-level }}
if: ${{ matrix.way == 'channel' }}
- name: Test way=${{ matrix.way}} api-level=${{ matrix.api-level }}
uses: reactivecircus/android-emulator-runner@v2
with:
target: default
api-level: ${{ matrix.api-level }}
arch: x86_64
script: |
pushd tests/emulator
nix run . -- run bootstrap-channel.py
nix run . -- run on-device-tests.py
popd
script: >
cd tests/emulator &&
nix run 'github:t184256/droidctl' -- run ${{ matrix.way }}.py
- name: Bootstrap using flakes api-level=${{ matrix.api-level }}
if: ${{ matrix.way == 'flakes' }}
uses: reactivecircus/android-emulator-runner@v2
- name: Upload screenshots
if: always()
uses: actions/upload-artifact@v4
with:
target: default
api-level: ${{ matrix.api-level }}
arch: x86_64
script: |
pushd tests/emulator
nix run . -- run bootstrap-flakes.py
popd
name: screenshots-${{ matrix.way }}-${{ matrix.api-level }}
path: tests/emulator/screenshots
if-no-files-found: warn # 'error' or 'ignore' are also available

# TODO: push to cachix from device
# - name: Push to cachix
# if: always() && github.event_name != 'pull_request'
# run: ...

# TODO: parametrize: channel vs flakes
# TODO: externally-driven test
# TODO: more API levels
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from common import wait_for, APK, BOOTSTRAP_URL
from common import screenshot, wait_for, APK, BOOTSTRAP_URL


def run(d):
Expand All @@ -10,19 +10,27 @@ def run(d):
d.ui(className='android.widget.EditText').set_text(BOOTSTRAP_URL)
d.ui(text='OK').click()

import time; time.sleep(30)
tv = d.ui(resourceId='com.termux.nix:id/terminal_view')
print(tv)
print(tv.info)
print(tv.info['contentDescription'])

wait_for(d, 'Welcome to Nix-on-Droid!')
wait_for(d, 'Do you want to set it up with flakes? (y/N)')
d.ui.press('enter')
wait_for(d, 'Setting up Nix-on-Droid with channels...')

wait_for(d, 'Installing and updating nix-channels...')
wait_for(d, 'unpacking channels...')
wait_for(d, 'Installing first Nix-on-Droid generation...', timeout=180)
wait_for(d, 'Installing first Nix-on-Droid generation...', timeout=600)
wait_for(d, 'Copying default Nix-on-Droid config...', timeout=180)
wait_for(d, 'Congratulations!')
wait_for(d, 'See config file for further information!')
wait_for(d, 'bash-5.25$')
wait_for(d, 'See config file for further information.')
wait_for(d, 'bash-5.2$')

d('input text "echo smoke-test | base64"') # remove
d.ui.press('enter')
wait_for(d, 'c21va2UtdGVzdAo=')

screenshot(d, 'success-bootstrap-channels')
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ def run(d):

wait_for(d, 'Welcome to Nix-on-Droid!')
wait_for(d, 'Do you want to set it up with flakes? (y/N)')
d('input text y') # remove
d('input text y')
d.ui.press('enter')
wait_for(d, 'Setting up Nix-on-Droid with flakes...')

...
wait_for(d, 'Installing first Nix-on-Droid generation...', timeout=180)
wait_for(d, 'Installing flake from default template...')
wait_for(d, 'Overriding input urls / arch in flake...')
wait_for(d, 'Installing first Nix-on-Droid generation...', timeout=600)
wait_for(d, 'Copying default Nix-on-Droid config...', timeout=180)
wait_for(d, 'Congratulations!')
wait_for(d, 'See config file for further information!')
wait_for(d, 'bash-5.25$')
wait_for(d, 'See config file for further information.')
wait_for(d, 'bash-5.2$')

d('input text "echo smoke-test | base64"') # remove
d.ui.press('enter')
Expand Down
15 changes: 13 additions & 2 deletions tests/emulator/common.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import os
import sys
import time

SERVER = 'https://nix-on-droid.unboiled.info'
APK = f'{SERVER}/com.termux.nix_188035-x86_64.apk'
BOOTSTRAP_URL = f'{SERVER}/testing'
BOOTSTRAP_URL = f'{SERVER}/bootstrap-testing'


def wait_for(d, on_screen_text, timeout=30, critical=True):
def screenshot(d, suffix=''):
os.makedirs('screenshots', exist_ok=True)
fname_base = f'screenshots/{time.time()}-{suffix}'
d.ui.screenshot(f'{fname_base}.png')
with open(f'{fname_base}.xml', 'w') as f:
f.write(d.ui.dump_hierarchy())
print(f'screenshotted: {fname_base}.{{png,xml}}')


def wait_for(d, on_screen_text, timeout=90, critical=True):
start = time.time()
last_displayed_time = None
while (elapsed := time.time() - start) < timeout:
Expand All @@ -19,5 +29,6 @@ def wait_for(d, on_screen_text, timeout=30, critical=True):
return
time.sleep(.75)
print(f'NOT FOUND: {on_screen_text} after {timeout}s')
screenshot(d, suffix='error')
if critical:
sys.exit(1)
File renamed without changes.
37 changes: 37 additions & 0 deletions tests/emulator/test_channels_shell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import bootstrap_channels
import subprocess

from common import wait_for

TD = '/data/data/com.termux.nix/files/usr/home/.cache/nix-on-droid-self-test'


def run(d):
bootstrap_channels.run(d)

d('input text "exit"') # remove
d.ui.press('enter')

nod = d.app('com.termux.nix')
nod.launch()

wait_for(d, 'bash-5.2$')

# run tests in a way that'd display progress in CI
user = d.su('stat -c %U /data/data/com.termux.nix').output.strip()
# WARNING: assumes `su 0` style `su` that doesn't support -c from now on
print(f'{user=}')
for cmd in [
'id',
f'mkdir -p {TD}',
f'touch {TD}/confirmation-granted',
('/data/data/com.termux.nix/files/usr/bin/login echo test'),
('/data/data/com.termux.nix/files/usr/bin/login id'),
('cd /data/data/com.termux.nix/files/home; '
'pwd; '
'id; '
'/data/data/com.termux.nix/files/usr/bin/login '
' nix-on-droid on-device-test')
]:
subprocess.run(['adb', 'shell', 'su', '0', 'su', user,
'sh', '-c', cmd])
7 changes: 7 additions & 0 deletions tests/emulator/test_channels_uiautomator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import bootstrap_channels
import on_device_tests


def run(d):
bootstrap_channels.run(d)
on_device_tests.run(d)

0 comments on commit 93f4f7e

Please sign in to comment.