Skip to content

Commit e2805e7

Browse files
Merge pull request #3786 from NativeScript/vladimirov/fix-test-command
fix: Test command runs tests twice and often fails on Android
2 parents 40ecfdf + ed3c140 commit e2805e7

10 files changed

+1100
-1085
lines changed

lib/constants.ts

-7
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,6 @@ class ItunesConnectApplicationTypesClass implements IiTunesConnectApplicationTyp
9898
}
9999

100100
export const ItunesConnectApplicationTypes = new ItunesConnectApplicationTypesClass();
101-
export class LiveSyncPaths {
102-
static SYNC_DIR_NAME = "sync";
103-
static REMOVEDSYNC_DIR_NAME = "removedsync";
104-
static FULLSYNC_DIR_NAME = "fullsync";
105-
static IOS_DEVICE_PROJECT_ROOT_PATH = "Library/Application Support/LiveSync";
106-
static IOS_DEVICE_SYNC_ZIP_PATH = "Library/Application Support/LiveSync/sync.zip";
107-
}
108101
export const ANGULAR_NAME = "angular";
109102
export const TYPESCRIPT_NAME = "typescript";
110103
export const BUILD_OUTPUT_EVENT_NAME = "buildOutput";

lib/device-path-provider.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { fromWindowsRelativePathToUnix } from "./common/helpers";
2-
import { APP_FOLDER_NAME, LiveSyncPaths } from "./constants";
2+
import { APP_FOLDER_NAME } from "./constants";
3+
import { LiveSyncPaths } from "./common/constants";
34
import { AndroidDeviceLiveSyncService } from "./services/livesync/android-device-livesync-service";
45
import * as path from "path";
56

@@ -23,7 +24,7 @@ export class DevicePathProvider implements IDevicePathProvider {
2324
projectRoot = path.join(projectRoot, APP_FOLDER_NAME);
2425
}
2526
} else if (this.$mobileHelper.isAndroidPlatform(device.deviceInfo.platform)) {
26-
projectRoot = `/data/local/tmp/${options.appIdentifier}`;
27+
projectRoot = `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${options.appIdentifier}`;
2728
if (!options.getDirname) {
2829
const deviceLiveSyncService = this.$injector.resolve<AndroidDeviceLiveSyncService>(AndroidDeviceLiveSyncService, { device });
2930
const hashService = deviceLiveSyncService.getDeviceHashService(options.appIdentifier);

lib/services/android-debug-service.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { sleep } from "../common/helpers";
22
import { DebugServiceBase } from "./debug-service-base";
3+
import { LiveSyncPaths } from "../common/constants";
34

45
export class AndroidDebugService extends DebugServiceBase implements IPlatformDebugService {
56
private _packageName: string;
@@ -158,22 +159,23 @@ export class AndroidDebugService extends DebugServiceBase implements IPlatformDe
158159
await this.device.applicationManager.stopApplication(appData);
159160

160161
if (debugOptions.debugBrk) {
161-
await this.device.adb.executeShellCommand([`cat /dev/null > /data/local/tmp/${appData.appId}-debugbreak`]);
162+
await this.device.adb.executeShellCommand([`cat /dev/null > ${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${appData.appId}-debugbreak`]);
162163
}
163164

164-
await this.device.adb.executeShellCommand([`cat /dev/null > /data/local/tmp/${appData.appId}-debugger-started`]);
165+
await this.device.adb.executeShellCommand([`cat /dev/null > ${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${appData.appId}-debugger-started`]);
165166

166167
await this.device.applicationManager.startApplication(appData);
167168

168169
await this.waitForDebugger(appData.appId);
169170
}
170171

171172
private async waitForDebugger(packageName: String): Promise<void> {
172-
const waitText: string = `0 /data/local/tmp/${packageName}-debugger-started`;
173+
const debuggerStartedFilePath = `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${packageName}-debugger-started`;
174+
const waitText: string = `0 ${debuggerStartedFilePath}`;
173175
let maxWait = 12;
174176
let debuggerStarted: boolean = false;
175177
while (maxWait > 0 && !debuggerStarted) {
176-
const forwardsResult = await this.device.adb.executeShellCommand(["ls", "-s", `/data/local/tmp/${packageName}-debugger-started`]);
178+
const forwardsResult = await this.device.adb.executeShellCommand(["ls", "-s", debuggerStartedFilePath]);
177179

178180
maxWait--;
179181

lib/services/android-project-service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as semver from "semver";
55
import * as projectServiceBaseLib from "./platform-project-service-base";
66
import { DeviceAndroidDebugBridge } from "../common/mobile/android/device-android-debug-bridge";
77
import { attachAwaitDetach, isRecommendedAarFile } from "../common/helpers";
8-
import { Configurations } from "../common/constants";
8+
import { Configurations, LiveSyncPaths } from "../common/constants";
99
import { SpawnOptions } from "child_process";
1010

1111
export class AndroidProjectService extends projectServiceBaseLib.PlatformProjectServiceBase implements IPlatformProjectService {
@@ -631,7 +631,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
631631

632632
public async cleanDeviceTempFolder(deviceIdentifier: string, projectData: IProjectData): Promise<void> {
633633
const adb = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
634-
const deviceRootPath = `/data/local/tmp/${projectData.projectId}`;
634+
const deviceRootPath = `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${projectData.projectId}`;
635635
await adb.executeShellCommand(["rm", "-rf", deviceRootPath]);
636636
}
637637

lib/services/livesync/android-device-livesync-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { DeviceAndroidDebugBridge } from "../../common/mobile/android/device-and
22
import { AndroidDeviceHashService } from "../../common/mobile/android/android-device-hash-service";
33
import { DeviceLiveSyncServiceBase } from "./device-livesync-service-base";
44
import * as helpers from "../../common/helpers";
5-
import { LiveSyncPaths } from "../../constants";
5+
import { LiveSyncPaths } from "../../common/constants";
66
import { cache } from "../../common/decorators";
77
import * as path from "path";
88
import * as net from "net";

lib/services/livesync/android-device-livesync-sockets-service.ts

+26-13
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import { DeviceAndroidDebugBridge } from "../../common/mobile/android/device-and
22
import { AndroidDeviceHashService } from "../../common/mobile/android/android-device-hash-service";
33
import { DeviceLiveSyncServiceBase } from "./device-livesync-service-base";
44
import { APP_FOLDER_NAME } from "../../constants";
5+
import { LiveSyncPaths } from "../../common/constants";
56
import { AndroidLivesyncTool } from "./android-livesync-tool";
67
import * as path from "path";
8+
import * as temp from "temp";
79

810
export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBase implements IAndroidNativeScriptDeviceLiveSyncService, INativeScriptDeviceLiveSyncService {
911
private livesyncTool: IAndroidLivesyncTool;
@@ -17,54 +19,65 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa
1719
private $logger: ILogger,
1820
protected device: Mobile.IAndroidDevice,
1921
private $options: ICommonOptions,
20-
private $processService: IProcessService) {
22+
private $processService: IProcessService,
23+
private $fs: IFileSystem) {
2124
super($platformsData, device);
2225
this.livesyncTool = this.$injector.resolve(AndroidLivesyncTool);
2326
}
2427

2528
public async beforeLiveSyncAction(deviceAppData: Mobile.IDeviceAppData): Promise<void> {
2629
const platformData = this.$platformsData.getPlatformData(deviceAppData.platform, this.data);
2730
const projectFilesPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME);
31+
const pathToLiveSyncFile = temp.path({ prefix: "livesync" });
32+
this.$fs.writeFile(pathToLiveSyncFile, "");
33+
await this.device.fileSystem.putFile(pathToLiveSyncFile, this.getPathToLiveSyncFileOnDevice(deviceAppData.appIdentifier), deviceAppData.appIdentifier);
2834
await this.device.applicationManager.startApplication({ appId: deviceAppData.appIdentifier, projectName: this.data.projectName });
2935
await this.connectLivesyncTool(projectFilesPath, this.data.projectId);
3036
}
3137

38+
private getPathToLiveSyncFileOnDevice(appIdentifier: string): string {
39+
return `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${appIdentifier}-livesync-in-progress`;
40+
}
41+
3242
public async finalizeSync(liveSyncInfo: ILiveSyncResultInfo) {
3343
await this.doSync(liveSyncInfo);
3444
}
3545

36-
private async doSync(liveSyncInfo: ILiveSyncResultInfo, {doRefresh = false}: {doRefresh?: boolean} = {}): Promise<IAndroidLivesyncSyncOperationResult> {
46+
private async doSync(liveSyncInfo: ILiveSyncResultInfo, { doRefresh = false }: { doRefresh?: boolean } = {}): Promise<IAndroidLivesyncSyncOperationResult> {
3747
const operationId = this.livesyncTool.generateOperationIdentifier();
3848

39-
let result = {operationId, didRefresh: true };
49+
let result = { operationId, didRefresh: true };
4050

4151
if (liveSyncInfo.modifiedFilesData.length) {
4252

4353
const doSyncPromise = this.livesyncTool.sendDoSyncOperation(doRefresh, null, operationId);
4454

45-
const syncInterval : NodeJS.Timer = setInterval(() => {
55+
const syncInterval: NodeJS.Timer = setInterval(() => {
4656
if (this.livesyncTool.isOperationInProgress(operationId)) {
4757
this.$logger.info("Sync operation in progress...");
4858
}
4959
}, AndroidDeviceSocketsLiveSyncService.STATUS_UPDATE_INTERVAL);
5060

51-
const clearSyncInterval = () => {
61+
const actionOnEnd = async () => {
5262
clearInterval(syncInterval);
63+
await this.device.fileSystem.deleteFile(this.getPathToLiveSyncFileOnDevice(liveSyncInfo.deviceAppData.appIdentifier), liveSyncInfo.deviceAppData.appIdentifier);
5364
};
5465

55-
this.$processService.attachToProcessExitSignals(this, clearSyncInterval);
56-
doSyncPromise.then(clearSyncInterval, clearSyncInterval);
66+
this.$processService.attachToProcessExitSignals(this, actionOnEnd);
67+
doSyncPromise.then(actionOnEnd, actionOnEnd);
5768

5869
result = await doSyncPromise;
5970
}
6071

72+
await this.device.fileSystem.deleteFile(this.getPathToLiveSyncFileOnDevice(liveSyncInfo.deviceAppData.appIdentifier), liveSyncInfo.deviceAppData.appIdentifier);
73+
6174
return result;
6275
}
6376

6477
public async refreshApplication(projectData: IProjectData, liveSyncInfo: ILiveSyncResultInfo) {
6578
const canExecuteFastSync = !liveSyncInfo.isFullSync && this.canExecuteFastSyncForPaths(liveSyncInfo.modifiedFilesData, projectData, this.device.deviceInfo.platform);
6679

67-
const syncOperationResult = await this.doSync(liveSyncInfo, {doRefresh: canExecuteFastSync});
80+
const syncOperationResult = await this.doSync(liveSyncInfo, { doRefresh: canExecuteFastSync });
6881

6982
this.livesyncTool.end();
7083

@@ -96,28 +109,28 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa
96109
}
97110

98111
private async _transferDirectory(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[], projectFilesPath: string): Promise<Mobile.ILocalToDevicePathData[]> {
99-
let transferredLocalToDevicePaths : Mobile.ILocalToDevicePathData[];
112+
let transferredLocalToDevicePaths: Mobile.ILocalToDevicePathData[];
100113
const deviceHashService = this.getDeviceHashService(deviceAppData.appIdentifier);
101114
const currentShasums: IStringDictionary = await deviceHashService.generateHashesFromLocalToDevicePaths(localToDevicePaths);
102115
const oldShasums = await deviceHashService.getShasumsFromDevice();
103116

104117
if (this.$options.force || !oldShasums) {
105118
await this.livesyncTool.sendDirectory(projectFilesPath);
106119
await deviceHashService.uploadHashFileToDevice(currentShasums);
107-
transferredLocalToDevicePaths = localToDevicePaths;
120+
transferredLocalToDevicePaths = localToDevicePaths;
108121
} else {
109122
const changedShasums = deviceHashService.getChangedShasums(oldShasums, currentShasums);
110123
const changedFiles = _.keys(changedShasums);
111124
if (changedFiles.length) {
112125
await this.livesyncTool.sendFiles(changedFiles);
113126
await deviceHashService.uploadHashFileToDevice(currentShasums);
114-
transferredLocalToDevicePaths = localToDevicePaths.filter(localToDevicePathData => changedFiles.indexOf(localToDevicePathData.getLocalPath()) >= 0);
127+
transferredLocalToDevicePaths = localToDevicePaths.filter(localToDevicePathData => changedFiles.indexOf(localToDevicePathData.getLocalPath()) >= 0);
115128
} else {
116-
transferredLocalToDevicePaths = [];
129+
transferredLocalToDevicePaths = [];
117130
}
118131
}
119132

120-
return transferredLocalToDevicePaths ;
133+
return transferredLocalToDevicePaths;
121134
}
122135

123136
private async connectLivesyncTool(projectFilesPath: string, appIdentifier: string) {

lib/services/livesync/android-livesync-tool.ts

+1
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool {
346346
socket.removeListener("close", tryConnectAfterTimeout);
347347
socket.removeListener("error", tryConnectAfterTimeout);
348348
isConnected = true;
349+
clearTimeout(connectionTimer);
349350
resolve({ socket, data });
350351
});
351352
socket.on("close", tryConnectAfterTimeout);

0 commit comments

Comments
 (0)