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

Add more options and optimization for our tests #1

Merged
merged 7 commits into from
Feb 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ jobs:
api-level: 23
- target: google_apis
api-level: 29
include:
- os: macos-11.0
api-level: 30
target: google_apis
# include:
# - os: macos-11.0
# api-level: 30
# target: google_apis
- os: macos-latest
api-level: 24
target: playstore
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,16 @@ jobs:
| `target` | Optional | `default` | Target of the system image - `default`, `google_apis` or `playstore`. |
| `arch` | Optional | `x86` | CPU architecture of the system image - `x86` or `x86_64`. Note that `x86_64` image is only available for API 21+. |
| `profile` | Optional | N/A | Hardware profile used for creating the AVD - e.g. `Nexus 6`. For a list of all profiles available, run `avdmanager list` and refer to the results under "Available Android Virtual Devices". |
| `cores` | Optional | N/A | Number of cores to use for the emulator (`hw.cpu.ncore` in config.ini). |
| `sdcard-path-or-size` | Optional | N/A | Path to the SD card image for this AVD or the size of a new SD card image to create for this AVD, in KB or MB, denoted with K or M. - e.g. `path/to/sdcard`, or `1000M`. |
| `avd-name` | Optional | `test` | Custom AVD name used for creating the Android Virtual Device. |
| `emulator-options` | Optional | See below | Command-line options used when launching the emulator (replacing all default options) - e.g. `-no-window -no-snapshot -camera-back emulated`. |
| `disable-animations` | Optional | `true` | Whether to disable animations - `true` or `false`. |
| `disable-spellchecker` | Optional | `false` | Whether to disable spellchecker - `true` or `false`. |
| `disable-autofill` | Optional | `false` | Whether to disable autofill - `true` or `false`. |
| `longpress-timeout` | Optional | 500 | Longpress timeout in milliseconds. |
| `enable-hw-keyboard` | Optional | `false` | Whether to enable the hw keyboard and disable soft keyboard - `true` or `false`. |
| `enable-logcat` | Optional | `false` | Whether to read and save logcat output to `artifacts/logcat.log` |
| `emulator-build` | Optional | N/A | Build number of a specific version of the emulator binary to use e.g. `6061023` for emulator v29.3.0.0. |
| `working-directory` | Optional | `./` | A custom working directory - e.g. `./android` if your root Gradle project is under the `./android` sub-directory within your repository. |
| `ndk` | Optional | N/A | Version of NDK to install - e.g. `21.0.6113669` |
Expand Down
107 changes: 107 additions & 0 deletions __tests__/input-validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,113 @@ describe('disable-animations validator tests', () => {
});
});

describe('disable-spellchecker validator tests', () => {
it('Throws if disable-spellchecker is not a boolean', () => {
const func = () => {
validator.checkDisableSpellchecker('yes');
};
expect(func).toThrowError(`Input for input.disable-spellchecker should be either 'true' or 'false'.`);
});

it('Validates successfully if disable-spellchecker is either true or false', () => {
const func1 = () => {
validator.checkDisableSpellchecker('true');
};
expect(func1).not.toThrow();

const func2 = () => {
validator.checkDisableSpellchecker('false');
};
expect(func2).not.toThrow();
});
});

describe('disable-autofill validator tests', () => {
it('Throws if disable-autofill is not a boolean', () => {
const func = () => {
validator.checkDisableAutofill('yes');
};
expect(func).toThrowError(`Input for input.disable-autofill should be either 'true' or 'false'.`);
});

it('Validates successfully if disable-autofill is either true or false', () => {
const func1 = () => {
validator.checkDisableAutofill('true');
};
expect(func1).not.toThrow();

const func2 = () => {
validator.checkDisableAutofill('false');
};
expect(func2).not.toThrow();
});
});

describe('enable-hw-keyboard validator tests', () => {
it('Throws if enable-hw-keyboard is not a boolean', () => {
const func = () => {
validator.checkEnableHwKeyboard('yes');
};
expect(func).toThrowError(`Input for input.enable-hw-keyboard should be either 'true' or 'false'.`);
});

it('Validates successfully if enable-hw-keyboard is either true or false', () => {
const func1 = () => {
validator.checkEnableHwKeyboard('true');
};
expect(func1).not.toThrow();

const func2 = () => {
validator.checkEnableHwKeyboard('false');
};
expect(func2).not.toThrow();
});
});

describe('enable-logcat validator tests', () => {
it('Throws if enable-logcat is not a boolean', () => {
const func = () => {
validator.checkEnableLogcat('yes');
};
expect(func).toThrowError(`Input for input.enable-logcat should be either 'true' or 'false'.`);
});

it('Validates successfully if enable-logcat is either true or false', () => {
const func1 = () => {
validator.checkEnableLogcat('true');
};
expect(func1).not.toThrow();

const func2 = () => {
validator.checkEnableLogcat('false');
};
expect(func2).not.toThrow();
});
});

describe('longpress-timeout validator tests', () => {
it('Throws if longpress-timeout is not a number', () => {
const func = () => {
validator.checkLongPressTimeout('abc123');
};
expect(func).toThrowError(`Unexpected longpress-timeout: 'abc123'.`);
});

it('Throws if longpress-timeout is not an integer', () => {
const func = () => {
validator.checkLongPressTimeout('123.123');
};
expect(func).toThrowError(`Unexpected longpress-timeout: '123.123'.`);
});

it('Validates successfully with valid longpress-timeout', () => {
const func = () => {
validator.checkLongPressTimeout('6061023');
};
expect(func).not.toThrow();
});
});

describe('emulator-build validator tests', () => {
it('Throws if emulator-build is not a number', () => {
const func = () => {
Expand Down
17 changes: 17 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ inputs:
default: 'x86'
profile:
description: 'hardware profile used for creating the AVD - e.g. `Nexus 6`'
cores:
description: 'the number of cores to use for the emulator'
sdcard-path-or-size:
description: 'path to the SD card image for this AVD or the size of a new SD card image to create for this AVD, in KB or MB, denoted with K or M. - e.g. `path/to/sdcard`, or `1000M`'
avd-name:
Expand All @@ -27,6 +29,21 @@ inputs:
disable-animations:
description: 'whether to disable animations - true or false'
default: 'true'
disable-spellchecker:
description: Whether to disable spellchecker - `true` or `false`.
default: 'false'
disable-autofill:
description: Whether to disable autofill - `true` or `false`.
default: 'false'
longpress-timeout:
description: Longpress timeout in milliseconds.
default: 500
enable-hw-keyboard:
description: Enable hw keyboard and disable soft keyboard - `true` or `false`.
default: 'false'
enable-logcat:
description: Enable reading and saving logcat output to `artifacts/logcat.log`.
default: 'false'
emulator-build:
description: 'build number of a specific version of the emulator binary to use - e.g. `6061023` for emulator v29.3.0.0'
working-directory:
Expand Down
46 changes: 45 additions & 1 deletion lib/emulator-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.killEmulator = exports.launchEmulator = void 0;
const exec = __importStar(require("@actions/exec"));
const EMULATOR_BOOT_TIMEOUT_SECONDS = 600;
let ENABLE_LOGCAT = false;
/**
* Creates and launches a new AVD instance with the specified configurations.
*/
function launchEmulator(apiLevel, target, arch, profile, sdcardPathOrSize, avdName, emulatorOptions, disableAnimations) {
function launchEmulator(apiLevel, target, arch, profile, cores, sdcardPathOrSize, avdName, emulatorOptions, disableAnimations, disableSpellChecker, disableAutofill, longPressTimeout, enableHwKeyboard, enableLogcat) {
return __awaiter(this, void 0, void 0, function* () {
// create a new AVD
const profileOption = profile.trim() !== '' ? `--device '${profile}'` : '';
const sdcardPathOrSizeOption = sdcardPathOrSize.trim() !== '' ? `--sdcard '${sdcardPathOrSize}'` : '';
console.log(`Creating AVD.`);
yield exec.exec(`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${apiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`);
if (cores) {
yield exec.exec(`sh -c \\"printf 'hw.cpu.ncore=${cores}\n' >> ~/.android/avd/"${avdName}".avd"/config.ini`);
}
if (enableHwKeyboard) {
yield exec.exec(`sh -c \\"printf 'hw.keyboard=yes\n' >> ~/.android/avd/"${avdName}".avd"/config.ini`);
}
// start emulator
console.log('Starting emulator.');
// turn off hardware acceleration on Linux
Expand All @@ -66,6 +73,22 @@ function launchEmulator(apiLevel, target, arch, profile, sdcardPathOrSize, avdNa
yield exec.exec(`adb shell settings put global transition_animation_scale 0.0`);
yield exec.exec(`adb shell settings put global animator_duration_scale 0.0`);
}
if (disableSpellChecker) {
yield exec.exec(`adb shell settings put secure spell_checker_enabled 0`);
}
if (disableAutofill) {
yield exec.exec(`adb shell settings put secure autofill_service null`);
}
if (longPressTimeout) {
yield exec.exec(`adb shell settings put secure long_press_timeout ${longPressTimeout}`);
}
if (enableHwKeyboard) {
yield exec.exec(`adb shell settings put secure show_ime_with_hard_keyboard 0`);
}
if (enableLogcat) {
ENABLE_LOGCAT = enableLogcat;
yield startLogcat();
}
});
}
exports.launchEmulator = launchEmulator;
Expand All @@ -75,6 +98,9 @@ exports.launchEmulator = launchEmulator;
function killEmulator() {
return __awaiter(this, void 0, void 0, function* () {
try {
if (ENABLE_LOGCAT) {
yield stopLogcat();
}
yield exec.exec(`adb -s emulator-5554 emu kill`);
}
catch (error) {
Expand Down Expand Up @@ -124,3 +150,21 @@ function waitForDevice() {
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function startLogcat() {
return __awaiter(this, void 0, void 0, function* () {
console.log('Starting logcat read process');
yield exec.exec(`mkdir -p artifacts`);
try {
yield exec.exec(`sh -c \\"adb logcat -v time > artifacts/logcat.log &"`);
}
catch (error) {
console.log(error.message);
}
});
}
function stopLogcat() {
return __awaiter(this, void 0, void 0, function* () {
console.log('Stopping logcat read process');
yield exec.exec(`sh -c "jobs -p | xargs kill"`);
});
}
37 changes: 35 additions & 2 deletions lib/input-validator.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkEmulatorBuild = exports.checkDisableAnimations = exports.checkArch = exports.checkTarget = exports.checkApiLevel = exports.VALID_ARCHS = exports.VALID_TARGETS = exports.MIN_API_LEVEL = void 0;
exports.checkEmulatorBuild = exports.checkLongPressTimeout = exports.checkEnableLogcat = exports.checkEnableHwKeyboard = exports.checkDisableAutofill = exports.checkDisableSpellchecker = exports.checkDisableAnimations = exports.checkArch = exports.checkTarget = exports.checkApiLevel = exports.VALID_ARCHS = exports.VALID_TARGETS = exports.MIN_API_LEVEL = void 0;
exports.MIN_API_LEVEL = 15;
exports.VALID_TARGETS = ['default', 'google_apis', 'google_apis_playstore'];
exports.VALID_ARCHS = ['x86', 'x86_64'];
Expand All @@ -26,14 +26,47 @@ function checkArch(arch) {
}
exports.checkArch = checkArch;
function checkDisableAnimations(disableAnimations) {
if (disableAnimations !== 'true' && disableAnimations !== 'false') {
if (!isValidBoolean(disableAnimations)) {
throw new Error(`Input for input.disable-animations should be either 'true' or 'false'.`);
}
}
exports.checkDisableAnimations = checkDisableAnimations;
function checkDisableSpellchecker(disableSpellchecker) {
if (!isValidBoolean(disableSpellchecker)) {
throw new Error(`Input for input.disable-spellchecker should be either 'true' or 'false'.`);
}
}
exports.checkDisableSpellchecker = checkDisableSpellchecker;
function checkDisableAutofill(disableAutofill) {
if (!isValidBoolean(disableAutofill)) {
throw new Error(`Input for input.disable-autofill should be either 'true' or 'false'.`);
}
}
exports.checkDisableAutofill = checkDisableAutofill;
function checkEnableHwKeyboard(enableHwKeyboard) {
if (!isValidBoolean(enableHwKeyboard)) {
throw new Error(`Input for input.enable-hw-keyboard should be either 'true' or 'false'.`);
}
}
exports.checkEnableHwKeyboard = checkEnableHwKeyboard;
function checkEnableLogcat(enableLogcat) {
if (!isValidBoolean(enableLogcat)) {
throw new Error(`Input for input.enable-logcat should be either 'true' or 'false'.`);
}
}
exports.checkEnableLogcat = checkEnableLogcat;
function checkLongPressTimeout(timeout) {
if (isNaN(Number(timeout)) || !Number.isInteger(Number(timeout))) {
throw new Error(`Unexpected longpress-timeout: '${timeout}'.`);
}
}
exports.checkLongPressTimeout = checkLongPressTimeout;
function checkEmulatorBuild(emulatorBuild) {
if (isNaN(Number(emulatorBuild)) || !Number.isInteger(Number(emulatorBuild))) {
throw new Error(`Unexpected emulator build: '${emulatorBuild}'.`);
}
}
exports.checkEmulatorBuild = checkEmulatorBuild;
function isValidBoolean(value) {
return value === 'true' || value === 'false';
}
30 changes: 29 additions & 1 deletion lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ function run() {
// Hardware profile used for creating the AVD
const profile = core.getInput('profile');
console.log(`Hardware profile: ${profile}`);
// Number of cores to use for emulator
const cores = core.getInput('cores');
console.log(`Cores: ${cores}`);
// SD card path or size used for creating the AVD
const sdcardPathOrSize = core.getInput('sdcard-path-or-size');
console.log(`SD card path or size: ${sdcardPathOrSize}`);
Expand All @@ -77,6 +80,31 @@ function run() {
input_validator_1.checkDisableAnimations(disableAnimationsInput);
const disableAnimations = disableAnimationsInput === 'true';
console.log(`disable animations: ${disableAnimations}`);
// disable ime
const enableHwKeyboardInput = core.getInput('enable-hw-keyboard');
input_validator_1.checkEnableHwKeyboard(enableHwKeyboardInput);
const enableHwKeyboard = enableHwKeyboardInput === 'true';
console.log(`enable hw keyboard: ${enableHwKeyboard}`);
// enable logcat
const enableLogcatInput = core.getInput('enable-logcat');
input_validator_1.checkEnableLogcat(enableLogcatInput);
const enableLogcat = enableLogcatInput === 'true';
console.log(`enable logcat: ${enableLogcat}`);
// disable spellchecker
const disableSpellcheckerInput = core.getInput('disable-spellchecker');
input_validator_1.checkDisableSpellchecker(disableSpellcheckerInput);
const disableSpellchecker = disableSpellcheckerInput === 'true';
console.log(`disable spellchecker: ${disableSpellchecker}`);
// disable autofill
const disableAutofillInput = core.getInput('disable-autofill');
input_validator_1.checkDisableAutofill(disableAutofillInput);
const disableAutofill = disableAutofillInput === 'true';
console.log(`disable autofill: ${disableAutofill}`);
// update longpress timeout
const longPressTimeoutInput = core.getInput('longpress-timeout');
input_validator_1.checkLongPressTimeout(longPressTimeoutInput);
const longPressTimeout = Number(longPressTimeoutInput);
console.log(`update longpress-timeout: ${longPressTimeoutInput}`);
// emulator build
const emulatorBuildInput = core.getInput('emulator-build');
if (emulatorBuildInput) {
Expand Down Expand Up @@ -112,7 +140,7 @@ function run() {
// install SDK
yield sdk_installer_1.installAndroidSdk(apiLevel, target, arch, emulatorBuild, ndkVersion, cmakeVersion);
// launch an emulator
yield emulator_manager_1.launchEmulator(apiLevel, target, arch, profile, sdcardPathOrSize, avdName, emulatorOptions, disableAnimations);
yield emulator_manager_1.launchEmulator(apiLevel, target, arch, profile, cores, sdcardPathOrSize, avdName, emulatorOptions, disableAnimations, disableSpellchecker, disableAutofill, longPressTimeout, enableHwKeyboard, enableLogcat);
// execute the custom script
try {
// move to custom working directory if set
Expand Down
Loading