Skip to content

Commit 62b9056

Browse files
authored
fix: uninstall installed uia2 servers if they were greater than on-going session (#796)
* fix: uninstall installed uia2 servers if they were greater than on-going session * extract some condition check and add tests * add docstring * tweak the condtion and add docstring * modify tests * use be.true/false
1 parent 0464741 commit 62b9056

File tree

2 files changed

+208
-18
lines changed

2 files changed

+208
-18
lines changed

lib/uiautomator2.js

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,51 @@ class UiAutomator2Server {
9797
return resultInfo;
9898
}
9999

100+
/**
101+
* @typedef {Object} PackageInfo
102+
* @property {import('appium-adb/build/lib/tools/apk-utils').InstallState} installState
103+
* @property {string} appPath
104+
* @property {string} appId
105+
*/
106+
107+
/**
108+
* Checks if server components must be installed from the device under test
109+
* in scope of the current driver session.
110+
*
111+
* For example, if one of servers on the device under test was newer than servers current UIA2 driver wants to
112+
* use for the session, the UIA2 driver should uninstall the installed ones in order to avoid
113+
* version mismatch between the UIA2 drier and servers on the device under test.
114+
* Also, if the device under test has missing servers, current UIA2 driver should uninstall all
115+
* servers once in order to install proper servers freshly.
116+
*
117+
* @param {PackageInfo[]} packagesInfo
118+
* @returns {boolean} true if any of components is already installed and the other is not installed
119+
* or the installed one has a newer version.
120+
*/
121+
shouldUninstallServerPackages(packagesInfo = []) {
122+
const isAnyComponentInstalled = packagesInfo.some(
123+
({installState}) => installState !== this.adb.APP_INSTALL_STATE.NOT_INSTALLED);
124+
const isAnyComponentNotInstalledOrNewer = packagesInfo.some(({installState}) => [
125+
this.adb.APP_INSTALL_STATE.NOT_INSTALLED,
126+
this.adb.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED,
127+
].includes(installState));
128+
return isAnyComponentInstalled && isAnyComponentNotInstalledOrNewer;
129+
}
130+
131+
/**
132+
* Checks if server components should be installed on the device under test in scope of the current driver session.
133+
*
134+
* @param {PackageInfo[]} packagesInfo
135+
* @returns {boolean} true if any of components is not installed or older than currently installed in order to
136+
* install or upgrade the servers on the device under test.
137+
*/
138+
shouldInstallServerPackages(packagesInfo = []) {
139+
return packagesInfo.some(({installState}) => [
140+
this.adb.APP_INSTALL_STATE.NOT_INSTALLED,
141+
this.adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED,
142+
].includes(installState));
143+
}
144+
100145
/**
101146
* Installs the apks on to the device or emulator.
102147
*
@@ -116,15 +161,10 @@ class UiAutomator2Server {
116161
);
117162

118163
this.log.debug(`Server packages status: ${JSON.stringify(packagesInfo)}`);
119-
// Enforce server packages reinstall if any of the packages is not installed, while the other is
120-
const shouldUninstallServerPackages = (packagesInfo.some(({installState}) => installState === this.adb.APP_INSTALL_STATE.NOT_INSTALLED)
121-
&& !packagesInfo.every(({installState}) => installState === this.adb.APP_INSTALL_STATE.NOT_INSTALLED));
164+
const shouldUninstallServerPackages = this.shouldUninstallServerPackages(packagesInfo);
122165
// Install must always follow uninstall. Also, perform the install if
123166
// any of server packages is not installed or is outdated
124-
const shouldInstallServerPackages = shouldUninstallServerPackages || packagesInfo.some(({installState}) => [
125-
this.adb.APP_INSTALL_STATE.NOT_INSTALLED,
126-
this.adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED,
127-
].includes(installState));
167+
const shouldInstallServerPackages = shouldUninstallServerPackages || this.shouldInstallServerPackages(packagesInfo);
128168
this.log.info(`Server packages are ${shouldInstallServerPackages ? '' : 'not '}going to be (re)installed`);
129169
if (shouldInstallServerPackages && shouldUninstallServerPackages) {
130170
this.log.info('Full packages reinstall is going to be performed');

test/unit/uiautomator2-specs.js

Lines changed: 161 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,169 @@ chai.should();
1212
chai.use(chaiAsPromised);
1313

1414
describe('UiAutomator2', function () {
15+
let uiautomator2;
1516
const adb = new ADB();
17+
const serverApk = {
18+
'appPath': 'path/to/appium-uiautomator2-server.apk',
19+
'appId': 'io.appium.uiautomator2.server'
20+
};
21+
const serverTestApk = {
22+
'appPath': 'path/to/appium-uiautomator2-server-test.apk',
23+
'appId': 'io.appium.uiautomator2.server.test'
24+
};
25+
const defaultUIA2ServerOptions = {
26+
tmpDir: 'tmp',
27+
systemPort: 4724,
28+
host: 'localhost',
29+
devicePort: 6790,
30+
disableWindowAnimation: false
31+
};
32+
33+
describe('shouldUninstallServerPackages', function () {
34+
beforeEach(function () {
35+
uiautomator2 = new UiAutomator2Server(log, {
36+
adb, ...defaultUIA2ServerOptions
37+
});
38+
});
39+
it('with newer servers are installed', function () {
40+
uiautomator2.shouldUninstallServerPackages([
41+
{
42+
'installState': adb.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED,
43+
...serverApk
44+
},
45+
{
46+
'installState': adb.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED,
47+
...serverTestApk
48+
}
49+
]).should.be.true;
50+
}),
51+
it('with newer server is installed but the other could be old one', function () {
52+
// Then, enforce to uninstall all apks
53+
uiautomator2.shouldUninstallServerPackages([
54+
{
55+
'installState': adb.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED,
56+
...serverApk
57+
},
58+
{
59+
'installState': adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED,
60+
...serverTestApk
61+
}
62+
]).should.be.true;
63+
}),
64+
it('with newer server is installed', function () {
65+
uiautomator2.shouldUninstallServerPackages([
66+
{
67+
'installState': adb.APP_INSTALL_STATE.SAME_VERSION_INSTALLED,
68+
...serverApk
69+
},
70+
{
71+
'installState': adb.APP_INSTALL_STATE.SAME_VERSION_INSTALLED,
72+
...serverTestApk
73+
}
74+
]).should.be.false;
75+
}),
76+
it('with older servers are installed', function () {
77+
// then, installing newer serves are sufficient.
78+
uiautomator2.shouldUninstallServerPackages([
79+
{
80+
'installState': adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED,
81+
...serverApk
82+
},
83+
{
84+
'installState': adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED,
85+
...serverTestApk
86+
}
87+
]).should.be.false;
88+
}),
89+
it('with no server are installed', function () {
90+
uiautomator2.shouldUninstallServerPackages([
91+
{
92+
'installState': adb.APP_INSTALL_STATE.NOT_INSTALLED,
93+
...serverApk
94+
},
95+
{
96+
'installState': adb.APP_INSTALL_STATE.NOT_INSTALLED,
97+
...serverTestApk
98+
}
99+
]).should.be.false;
100+
});
101+
});
102+
103+
describe('shouldInstallServerPackages', function () {
104+
beforeEach(function () {
105+
uiautomator2 = new UiAutomator2Server(log, {
106+
adb, ...defaultUIA2ServerOptions
107+
});
108+
});
109+
it('with newer servers are installed', function () {
110+
uiautomator2.shouldInstallServerPackages([
111+
{
112+
'installState': adb.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED,
113+
...serverApk
114+
},
115+
{
116+
'installState': adb.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED,
117+
...serverTestApk
118+
}
119+
// since installation may fail
120+
]).should.be.false;
121+
}),
122+
it('with newer server is installed but the other could be old one', function () {
123+
// Then, enforce to uninstall all apks
124+
uiautomator2.shouldInstallServerPackages([
125+
{
126+
'installState': adb.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED,
127+
...serverApk
128+
},
129+
{
130+
'installState': adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED,
131+
...serverTestApk
132+
}
133+
]).should.be.true;
134+
}),
135+
it('with newer server is installed', function () {
136+
uiautomator2.shouldInstallServerPackages([
137+
{
138+
'installState': adb.APP_INSTALL_STATE.SAME_VERSION_INSTALLED,
139+
...serverApk
140+
},
141+
{
142+
'installState': adb.APP_INSTALL_STATE.SAME_VERSION_INSTALLED,
143+
...serverTestApk
144+
}
145+
]).should.be.false;
146+
}),
147+
it('with older servers are installed', function () {
148+
// then, installing newer serves are sufficient.
149+
uiautomator2.shouldInstallServerPackages([
150+
{
151+
'installState': adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED,
152+
...serverApk
153+
},
154+
{
155+
'installState': adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED,
156+
...serverTestApk
157+
}
158+
]).should.be.true;
159+
}),
160+
it('with no server are installed', function () {
161+
uiautomator2.shouldInstallServerPackages([
162+
{
163+
'installState': adb.APP_INSTALL_STATE.NOT_INSTALLED,
164+
...serverApk
165+
},
166+
{
167+
'installState': adb.APP_INSTALL_STATE.NOT_INSTALLED,
168+
...serverTestApk
169+
}
170+
]).should.be.true;
171+
});
172+
});
173+
16174
describe('installServerApk', withMocks({adb, helpers}, (mocks) => {
17-
let uiautomator2;
18175
beforeEach(function () {
19176
uiautomator2 = new UiAutomator2Server(log, {
20-
adb,
21-
tmpDir: 'tmp',
22-
systemPort: 4724,
23-
host: 'localhost',
24-
devicePort: 6790,
25-
disableWindowAnimation: false,
26-
disableSuppressAccessibilityService: false
177+
adb, ...defaultUIA2ServerOptions
27178
});
28179
});
29180
afterEach(function () {
@@ -35,7 +186,7 @@ describe('UiAutomator2', function () {
35186

36187
// SERVER_PACKAGE_ID
37188
mocks.adb.expects('getApplicationInstallState').once()
38-
.returns(adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED);
189+
.returns(adb.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED);
39190

40191
// SERVER_PACKAGE_ID and SERVER_TEST_PACKAGE_ID
41192
mocks.adb.expects('checkApkCert').twice().returns(true);
@@ -58,7 +209,7 @@ describe('UiAutomator2', function () {
58209

59210
// SERVER_PACKAGE_ID
60211
mocks.adb.expects('getApplicationInstallState').once()
61-
.returns(adb.APP_INSTALL_STATE.NEWER_VERSION_INSTALLED);
212+
.returns(adb.APP_INSTALL_STATE.OLDER_VERSION_INSTALLED);
62213

63214
// SERVER_PACKAGE_ID and SERVER_TEST_PACKAGE_ID
64215
mocks.adb.expects('checkApkCert').twice().returns(true);
@@ -147,7 +298,6 @@ describe('UiAutomator2', function () {
147298
await uiautomator2.installServerApk();
148299
});
149300

150-
151301
it('a server is installed but server.test is not', async function () {
152302
mocks.helpers.expects('isWriteable').never();
153303

0 commit comments

Comments
 (0)