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

Introduce apks support #367

Merged
merged 13 commits into from
Oct 19, 2018
Merged

Conversation

mykola-mokhnach
Copy link
Contributor

This PR continues what was started by @KazuCocoa in #366

the main idea behind the current implementation is to introduce .apks format support without making additional changes in the depending driver modules (aka it should simply work).

lib/helpers.js Outdated
async function unzipFile (zipPath) {
log.debug(`Unzipping ${zipPath}`);
async function unzipFile (zipPath, dstRoot = null) {
dstRoot = dstRoot || path.dirname(zipPath);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be done in the default parameter

async function unzipFile (zipPath, dstRoot = path.dirname(zipPath)) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it ok to use other arguments in default value calculation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as long as they are later in the argument list. So

function a (b = c, c) {
  console.log(b, c);
}

would fail if you called a(undefined, 1), with a reference error, because c would not have been defined when b is initialized to it.

But, for every situation, the follow is fine:

function a (b, c = b) {
  console.log(b, c);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, fixed

@mykola-mokhnach
Copy link
Contributor Author

@KazuCocoa Would you like to run some tests on this PR?

Mykola Mokhnach added 2 commits October 16, 2018 21:07
Copy link
Member

@KazuCocoa KazuCocoa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Of course. I'll take a look & test

`the current API level ${apiLevel} does not support applications ` +
`permissions customization`);
} else {
additionalArgs.push('-g');
}
}

if (appPath.endsWith(APKS_EXTENSION)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍
The installation depends on device environment. Configuring device env, including language preference, is called in first step in startAndroidSession. The bundle-install command doesn't install unused languages resources.
https://github.com/appium/appium-android-driver/blob/2bac1672019be24c74fec7b4b5e4301558bfcb66/lib/driver.js#L234

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in theory we could additionally install these language resources manually or change the setup flow sequence. Which way does look more convenient to you?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KazuCocoa I've changed the way we install apks. Now it is much more customizable.

lib/helpers.js Outdated
* @returns {string} The calculated hash as hexadecimal string
* @throws {Error} If hash calculation fails
*/
async function fileHash (filePath, algorithm = 'sha1') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels like this should be in appium-support?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

into which submodule of appium-support it would be better to put it? util or fs?

additionalArgs.push('-g');
}
}
options = Object.assign({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object.assign mutates, dunno if that changes how you'd want to use it here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here we just assign the default values to options. The argument dictionary itself is not mutated, but a new copy is created

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh right, only the target is mutated and in this case it's an object literal

*
* @param {string} apks - The full path to the .apks file
* @param {string|Array<String>} dstPath - The relative path to the destination file,
* which is going to be extract3ed, where each path component is an array item
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extracted

Copy link
Member

@KazuCocoa KazuCocoa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Looks good to me. I'll install real apks after my work.

await this.execBundletool(args, `Cannot extract the application bundle at '${apks}'`);
const installArgs = buildInstallArgs(await this.getApiLevel(), options);
const apksToInstall = (await fs.readdir(tmpRoot))
.filter((name) => name.endsWith('.apk'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nits]
Is it better to define .apk const like APKS_EXTENSION?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense

.filter((name) => name.endsWith('.apk'))
.map((name) => path.resolve(tmpRoot, name));
log.debug(`Got the following apk files to install: ${JSON.stringify(apksToInstall)}`);
const output = await this.adbExec(['install-multiple', ...installArgs, ...apksToInstall], {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the install apks has unsuitable architecture, installing apks fail. (adb install failed before. It happen if users use ML related libraries, for example.)

base-vi.apk 11K
base-x86.apk 483K
base-x86_64.apk 453K
base-xhdpi.apk 2.4M

What about add considering abis?
=> ah, we use '--device-spec', specPath,. nice 👍

Copy link
Contributor Author

@mykola-mokhnach mykola-mokhnach Oct 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep. also this strategy allows to alter the actual spec set if, for example, we need to install more locales, by just modifying the spec json

*/
methods.initBundletool = async function () {
try {
const bundletoolPath = await fs.which('bundletool.jar');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should export the path to 'bundletool.jar', right? 👀

Copy link
Contributor Author

@mykola-mokhnach mykola-mokhnach Oct 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. bundletool.jar binary should be in any of folders enumerated in system PATH

@KazuCocoa
Copy link
Member

I've implemented https://github.com/KazuCocoa/AppBundleSample/blob/master/test.rb and run it to make sure the behaviour. Then, I noticed below three points.

  1. If a test app(only english resource) already has been installed, it remains. Then, 2nd test scenario failed since 2nd scenario would like to run tests against Japanese resource
    • https://github.com/KazuCocoa/AppBundleSample/blob/master/test.rb
      1. Can we make sure the installed apk's resource and try re-install if we need?
      2. Or use standalones/standalone-xxxhdpi.apk?
      3. (Or we'll guide full reset for .apks at first?)
        • If we can do 1st or 2nd way, it's better, I think. 3 is reasonable so far, I also think since buildtools also isn't 1.x yet.
  2. We need to relax APP_EXTENSION for configureApp to allow .apks extension. We need to extend configureApp to allow multiple extension.
  3. https://github.com/appium/appium-adb/pull/367/files#r226311748

@mykola-mokhnach
Copy link
Contributor Author

@KazuCocoa

Regarding p1 I will try to do some internal testing and check on what can be done there.
Btw, does it help if fullReset is enabled?

For p2 should be an easy fix.

Many thanks for help on this

@KazuCocoa
Copy link
Member

Btw, does it help if fullReset is enabled?

Yes, but it's the final way, I believe.
If we can't do anything to identify when Appium must re-install an apk, it's helpful. But if we enable fullReset everytime, below case happens. (Your heavy improvement for creating session doesn't work this case.)

  1. Create a session with English resource
  2. Create a session with English resource as another test case <= We don't need to re-install, but re-install happens if we enable fullReset

@mykola-mokhnach
Copy link
Contributor Author

I would just assume this is the main purpose of bundling, that we only install the necessary resources. So it would be logically to assume we need to reinstall the app in order to get the new locale from the bundle (real users would also have to do the same in case of apks). Also, sometimes full reset might be even faster than soft reset, since it does not require to set permissions on the package (these are set during installation)

@KazuCocoa
Copy link
Member

sometimes full reset might be even faster than soft reset, since it does not require to set permissions on the package (these are set during installation)

ah, it's reasonable to enable fullReset for .apks. I agree with the trying fullReset way.

@appium appium deleted a comment from KazuCocoa Oct 19, 2018
@mykola-mokhnach
Copy link
Contributor Author

@KazuCocoa Are you fine with merging this PR in the current state or you'd like to add something?

@KazuCocoa
Copy link
Member

KazuCocoa commented Oct 19, 2018

Let me run the test again once with fullRest cap

Copy link
Member

@KazuCocoa KazuCocoa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worked perfectly 👍 Thanks!

@mykola-mokhnach mykola-mokhnach merged commit 9fa581d into appium:master Oct 19, 2018
@mykola-mokhnach mykola-mokhnach deleted the apks_support branch October 20, 2018 07:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants