Skip to content

Commit ec1b2c6

Browse files
Use fork instead of spawn for startTestRunner
In `karma-nativescript-launcher` we call startTestRunner through spawn. Communication between karma launcher and tns is through stdin. This is causing exception in buildMetadata step when gradle wrapper is used. For some reason it throws error in java code. So, replace the spawn with fork in the launcher. Modify `startTestRunner` to wait for message from parent process and send "ready" state to the parent. After that the parent (karma-nativescript-launcher) sends configuration data and the `startTestRunner` will execute the actions. Fixes #1199
1 parent c289ad6 commit ec1b2c6

File tree

1 file changed

+89
-74
lines changed

1 file changed

+89
-74
lines changed

lib/services/test-execution-service.ts

+89-74
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as constants from "../constants";
66
import * as path from 'path';
77
import Future = require('fibers/future');
88
import * as os from 'os';
9+
import * as fiberBootstrap from "../common/fiber-bootstrap";
910

1011
interface IKarmaConfigOptions {
1112
debugBrk: boolean;
@@ -37,81 +38,95 @@ class TestExecutionService implements ITestExecutionService {
3738
public startTestRunner(platform: string) : IFuture<void> {
3839
return (() => {
3940
this.$options.justlaunch = true;
41+
let blockingOperationFuture = new Future<void>();
42+
process.on('message', (launcherConfig: any) => {
43+
fiberBootstrap.run(() => {
44+
try {
45+
let platformData = this.$platformsData.getPlatformData(platform.toLowerCase());
46+
let projectDir = this.$projectData.projectDir;
47+
48+
let projectFilesPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME);
49+
50+
let configOptions: IKarmaConfigOptions = JSON.parse(launcherConfig);
51+
this.$options.debugBrk = configOptions.debugBrk;
52+
this.$options.debugTransport = configOptions.debugTransport;
53+
let configJs = this.generateConfig(configOptions);
54+
this.$fs.writeFile(path.join(projectDir, TestExecutionService.CONFIG_FILE_NAME), configJs).wait();
55+
56+
let socketIoJsUrl = `http://localhost:${this.$options.port}/socket.io/socket.io.js`;
57+
let socketIoJs = this.$httpClient.httpRequest(socketIoJsUrl).wait().body;
58+
this.$fs.writeFile(path.join(projectDir, TestExecutionService.SOCKETIO_JS_FILE_NAME), socketIoJs).wait();
59+
60+
this.$platformService.preparePlatform(platform).wait();
61+
this.detourEntryPoint(projectFilesPath).wait();
62+
63+
let watchGlob = path.join(projectDir, constants.APP_FOLDER_NAME);
64+
65+
let platformSpecificLiveSyncServices: IDictionary<any> = {
66+
android: (_device: Mobile.IDevice, $injector: IInjector): IPlatformSpecificLiveSyncService => {
67+
return $injector.resolve(this.$androidUsbLiveSyncServiceLocator.factory, {_device: _device});
68+
},
69+
ios: (_device: Mobile.IDevice, $injector: IInjector) => {
70+
return $injector.resolve(this.$iosUsbLiveSyncServiceLocator.factory, {_device: _device});
71+
}
72+
};
73+
74+
let notInstalledAppOnDeviceAction = (device: Mobile.IDevice): IFuture<void> => {
75+
return (() => {
76+
this.$platformService.installOnDevice(platform).wait();
77+
this.detourEntryPoint(projectFilesPath).wait();
78+
}).future<void>()();
79+
};
80+
81+
let notRunningiOSSimulatorAction = (): IFuture<void> => {
82+
return (() => {
83+
this.$platformService.deployOnEmulator(this.$devicePlatformsConstants.iOS.toLowerCase()).wait();
84+
this.detourEntryPoint(projectFilesPath).wait();
85+
}).future<void>()();
86+
};
87+
88+
let beforeBatchLiveSyncAction = (filePath: string): IFuture<string> => {
89+
return (() => {
90+
this.$platformService.preparePlatform(platform).wait();
91+
return path.join(projectFilesPath, path.relative(path.join(this.$projectData.projectDir, constants.APP_FOLDER_NAME), filePath));
92+
}).future<string>()();
93+
};
94+
95+
let localProjectRootPath = platform.toLowerCase() === "ios" ? platformData.appDestinationDirectoryPath : null;
96+
97+
let liveSyncData = {
98+
platform: platform,
99+
appIdentifier: this.$projectData.projectId,
100+
projectFilesPath: projectFilesPath,
101+
excludedProjectDirsAndFiles: constants.LIVESYNC_EXCLUDED_DIRECTORIES,
102+
watchGlob: watchGlob,
103+
platformSpecificLiveSyncServices: platformSpecificLiveSyncServices,
104+
notInstalledAppOnDeviceAction: notInstalledAppOnDeviceAction,
105+
notRunningiOSSimulatorAction: notRunningiOSSimulatorAction,
106+
localProjectRootPath: localProjectRootPath,
107+
beforeBatchLiveSyncAction: beforeBatchLiveSyncAction,
108+
shouldRestartApplication: (localToDevicePaths: Mobile.ILocalToDevicePathData[]) => Future.fromResult(!this.$options.debugBrk),
109+
canExecuteFastLiveSync: (filePath: string) => false,
110+
};
111+
112+
this.$usbLiveSyncServiceBase.sync(liveSyncData).wait();
113+
114+
if (this.$options.debugBrk) {
115+
this.$logger.info('Starting debugger...');
116+
let debugService: IDebugService = this.$injector.resolve(`${platform}DebugService`);
117+
debugService.debugStart().wait();
118+
}
119+
blockingOperationFuture.return();
120+
} catch(err) {
121+
// send the error to the real future
122+
blockingOperationFuture.throw(err);
123+
}
124+
});
125+
});
40126

41-
let platformData = this.$platformsData.getPlatformData(platform.toLowerCase());
42-
let projectDir = this.$projectData.projectDir;
43-
44-
let projectFilesPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME);
45-
46-
let configOptions: IKarmaConfigOptions = JSON.parse(this.$fs.readStdin().wait());
47-
this.$options.debugBrk = configOptions.debugBrk;
48-
this.$options.debugTransport = configOptions.debugTransport;
49-
let configJs = this.generateConfig(configOptions);
50-
this.$fs.writeFile(path.join(projectDir, TestExecutionService.CONFIG_FILE_NAME), configJs).wait();
51-
52-
let socketIoJsUrl = `http://localhost:${this.$options.port}/socket.io/socket.io.js`;
53-
let socketIoJs = this.$httpClient.httpRequest(socketIoJsUrl).wait().body;
54-
this.$fs.writeFile(path.join(projectDir, TestExecutionService.SOCKETIO_JS_FILE_NAME), socketIoJs).wait();
55-
56-
this.$platformService.preparePlatform(platform).wait();
57-
this.detourEntryPoint(projectFilesPath).wait();
58-
59-
let watchGlob = path.join(projectDir, constants.APP_FOLDER_NAME);
60-
61-
let platformSpecificLiveSyncServices: IDictionary<any> = {
62-
android: (_device: Mobile.IDevice, $injector: IInjector): IPlatformSpecificLiveSyncService => {
63-
return $injector.resolve(this.$androidUsbLiveSyncServiceLocator.factory, {_device: _device});
64-
},
65-
ios: (_device: Mobile.IDevice, $injector: IInjector) => {
66-
return $injector.resolve(this.$iosUsbLiveSyncServiceLocator.factory, {_device: _device});
67-
}
68-
};
69-
70-
let notInstalledAppOnDeviceAction = (device: Mobile.IDevice): IFuture<void> => {
71-
return (() => {
72-
this.$platformService.installOnDevice(platform).wait();
73-
this.detourEntryPoint(projectFilesPath).wait();
74-
}).future<void>()();
75-
};
76-
77-
let notRunningiOSSimulatorAction = (): IFuture<void> => {
78-
return (() => {
79-
this.$platformService.deployOnEmulator(this.$devicePlatformsConstants.iOS.toLowerCase()).wait();
80-
this.detourEntryPoint(projectFilesPath).wait();
81-
}).future<void>()();
82-
};
83-
84-
let beforeBatchLiveSyncAction = (filePath: string): IFuture<string> => {
85-
return (() => {
86-
this.$platformService.preparePlatform(platform).wait();
87-
return path.join(projectFilesPath, path.relative(path.join(this.$projectData.projectDir, constants.APP_FOLDER_NAME), filePath));
88-
}).future<string>()();
89-
};
90-
91-
let localProjectRootPath = platform.toLowerCase() === "ios" ? platformData.appDestinationDirectoryPath : null;
92-
93-
let liveSyncData = {
94-
platform: platform,
95-
appIdentifier: this.$projectData.projectId,
96-
projectFilesPath: projectFilesPath,
97-
excludedProjectDirsAndFiles: constants.LIVESYNC_EXCLUDED_DIRECTORIES,
98-
watchGlob: watchGlob,
99-
platformSpecificLiveSyncServices: platformSpecificLiveSyncServices,
100-
notInstalledAppOnDeviceAction: notInstalledAppOnDeviceAction,
101-
notRunningiOSSimulatorAction: notRunningiOSSimulatorAction,
102-
localProjectRootPath: localProjectRootPath,
103-
beforeBatchLiveSyncAction: beforeBatchLiveSyncAction,
104-
shouldRestartApplication: (localToDevicePaths: Mobile.ILocalToDevicePathData[]) => Future.fromResult(!this.$options.debugBrk),
105-
canExecuteFastLiveSync: (filePath: string) => false,
106-
};
107-
108-
this.$usbLiveSyncServiceBase.sync(liveSyncData).wait();
109-
110-
if (this.$options.debugBrk) {
111-
this.$logger.info('Starting debugger...');
112-
let debugService: IDebugService = this.$injector.resolve(`${platform}DebugService`);
113-
debugService.debugStart().wait();
114-
}
127+
// Tell the parent that we are ready to receive the data.
128+
process.send("ready");
129+
blockingOperationFuture.wait();
115130
}).future<void>()();
116131
}
117132

0 commit comments

Comments
 (0)