mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-04-19 12:57:17 +00:00
fix: flaky compiler test
- The gRPC core client provider requires an initialized config service when processing the error message received during the `InitRequest` - Additional logging in the config service. - The tests log into the console. Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
parent
658f117e93
commit
f5621db85d
@ -136,8 +136,10 @@ export class ConfigServiceImpl
|
||||
}
|
||||
|
||||
private async initConfig(): Promise<void> {
|
||||
this.logger.info('>>> Initializing CLI configuration...');
|
||||
try {
|
||||
const cliConfig = await this.loadCliConfig();
|
||||
this.logger.info('Loaded the CLI configuration.');
|
||||
this.cliConfig = cliConfig;
|
||||
const [config] = await Promise.all([
|
||||
this.mapCliConfigToAppConfig(this.cliConfig),
|
||||
@ -153,10 +155,16 @@ export class ConfigServiceImpl
|
||||
}),
|
||||
]);
|
||||
this.config.config = config;
|
||||
this.logger.info(
|
||||
`Mapped the CLI configuration: ${JSON.stringify(this.config.config)}`
|
||||
);
|
||||
this.logger.info('Validating the CLI configuration...');
|
||||
await this.validateCliConfig(this.cliConfig);
|
||||
delete this.config.messages;
|
||||
this.logger.info('The CLI config is valid.');
|
||||
if (config) {
|
||||
this.ready.resolve();
|
||||
this.logger.info('<<< Initialized the CLI configuration.');
|
||||
return;
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
@ -173,18 +181,35 @@ export class ConfigServiceImpl
|
||||
): Promise<DefaultCliConfig> {
|
||||
const cliConfigFileUri = await this.getCliConfigFileUri();
|
||||
const cliConfigPath = FileUri.fsPath(cliConfigFileUri);
|
||||
this.logger.info(`Loading CLI configuration from ${cliConfigPath}...`);
|
||||
try {
|
||||
const content = await fs.readFile(cliConfigPath, {
|
||||
encoding: 'utf8',
|
||||
});
|
||||
const model = (yaml.safeLoad(content) || {}) as DefaultCliConfig;
|
||||
this.logger.info(`Loaded CLI configuration: ${JSON.stringify(model)}`);
|
||||
if (model.directories.data && model.directories.user) {
|
||||
this.logger.info(
|
||||
"'directories.data' and 'directories.user' are set in the CLI configuration model."
|
||||
);
|
||||
return model;
|
||||
}
|
||||
// The CLI can run with partial (missing `port`, `directories`), the IDE2 cannot.
|
||||
// We merge the default CLI config with the partial user's config.
|
||||
this.logger.info(
|
||||
"Loading fallback CLI configuration to get 'directories.data' and 'directories.user'"
|
||||
);
|
||||
const fallbackModel = await this.getFallbackCliConfig();
|
||||
return deepmerge(fallbackModel, model) as DefaultCliConfig;
|
||||
this.logger.info(
|
||||
`Loaded fallback CLI configuration: ${JSON.stringify(fallbackModel)}`
|
||||
);
|
||||
const mergedModel = deepmerge(fallbackModel, model) as DefaultCliConfig;
|
||||
this.logger.info(
|
||||
`Merged CLI configuration with the fallback: ${JSON.stringify(
|
||||
mergedModel
|
||||
)}`
|
||||
);
|
||||
return mergedModel;
|
||||
} catch (error) {
|
||||
if (ErrnoException.isENOENT(error)) {
|
||||
if (initializeIfAbsent) {
|
||||
|
@ -254,8 +254,8 @@ export class CoreClientProvider {
|
||||
}
|
||||
})
|
||||
.on('error', reject)
|
||||
.on('end', () => {
|
||||
const error = this.evaluateErrorStatus(errors);
|
||||
.on('end', async () => {
|
||||
const error = await this.evaluateErrorStatus(errors);
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
@ -265,7 +265,10 @@ export class CoreClientProvider {
|
||||
});
|
||||
}
|
||||
|
||||
private evaluateErrorStatus(status: RpcStatus[]): Error | undefined {
|
||||
private async evaluateErrorStatus(
|
||||
status: RpcStatus[]
|
||||
): Promise<Error | undefined> {
|
||||
await this.configService.getConfiguration(); // to ensure the CLI config service has been initialized.
|
||||
const { cliConfiguration } = this.configService;
|
||||
if (!cliConfiguration) {
|
||||
// If the CLI config is not available, do not even try to guess what went wrong.
|
||||
|
@ -7,7 +7,8 @@ import {
|
||||
import { bindContributionProvider } from '@theia/core/lib/common/contribution-provider';
|
||||
import { Disposable } from '@theia/core/lib/common/disposable';
|
||||
import { EnvVariablesServer as TheiaEnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import { ILogger } from '@theia/core/lib/common/logger';
|
||||
import { ILogger, Loggable } from '@theia/core/lib/common/logger';
|
||||
import { LogLevel } from '@theia/core/lib/common/logger-protocol';
|
||||
import { isWindows } from '@theia/core/lib/common/os';
|
||||
import { waitForEvent } from '@theia/core/lib/common/promise-util';
|
||||
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
|
||||
@ -66,7 +67,7 @@ describe('core-service-impl', () => {
|
||||
let toDispose: Disposable[];
|
||||
|
||||
before(() => {
|
||||
BackendApplicationConfigProvider.set({ configDirName: 'testArduinoIDE' });
|
||||
BackendApplicationConfigProvider.set({ configDirName: '.testArduinoIDE' });
|
||||
});
|
||||
|
||||
beforeEach(async function () {
|
||||
@ -175,10 +176,11 @@ function createContainer(): Container {
|
||||
);
|
||||
bind(EnvVariablesServer).toSelf().inSingletonScope();
|
||||
bind(TheiaEnvVariablesServer).toService(EnvVariablesServer);
|
||||
bind(ArduinoDaemonImpl).toSelf().inSingletonScope();
|
||||
bind(ArduinoDaemon).toService(ArduinoDaemonImpl);
|
||||
bind(MockLogger).toSelf().inSingletonScope();
|
||||
bind(ILogger).toService(MockLogger);
|
||||
bind(SilentArduinoDaemon).toSelf().inSingletonScope();
|
||||
bind(ArduinoDaemon).toService(SilentArduinoDaemon);
|
||||
bind(ArduinoDaemonImpl).toService(SilentArduinoDaemon);
|
||||
bind(ConsoleLogger).toSelf().inSingletonScope();
|
||||
bind(ILogger).toService(ConsoleLogger);
|
||||
bind(TestNotificationServiceServer).toSelf().inSingletonScope();
|
||||
bind(NotificationServiceServer).toService(TestNotificationServiceServer);
|
||||
bind(ConfigServiceImpl).toSelf().inSingletonScope();
|
||||
@ -312,3 +314,88 @@ class TestCommandRegistry extends CommandRegistry {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@injectable()
|
||||
class ConsoleLogger extends MockLogger {
|
||||
override log(
|
||||
logLevel: number,
|
||||
arg2: string | Loggable | Error,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
...params: any[]
|
||||
): Promise<void> {
|
||||
if (arg2 instanceof Error) {
|
||||
return this.error(String(arg2), params);
|
||||
}
|
||||
switch (logLevel) {
|
||||
case LogLevel.INFO:
|
||||
return this.info(arg2, params);
|
||||
case LogLevel.WARN:
|
||||
return this.warn(arg2, params);
|
||||
case LogLevel.TRACE:
|
||||
return this.trace(arg2, params);
|
||||
case LogLevel.ERROR:
|
||||
return this.error(arg2, params);
|
||||
case LogLevel.FATAL:
|
||||
return this.fatal(arg2, params);
|
||||
default:
|
||||
return this.info(arg2, params);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
override async info(arg: string | Loggable, ...params: any[]): Promise<void> {
|
||||
if (params.length) {
|
||||
console.info(arg, ...params);
|
||||
} else {
|
||||
console.info(arg);
|
||||
}
|
||||
}
|
||||
|
||||
override async trace(
|
||||
arg: string | Loggable,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
...params: any[]
|
||||
): Promise<void> {
|
||||
if (params.length) {
|
||||
console.trace(arg, ...params);
|
||||
} else {
|
||||
console.trace(arg);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
override async warn(arg: string | Loggable, ...params: any[]): Promise<void> {
|
||||
if (params.length) {
|
||||
console.warn(arg, ...params);
|
||||
} else {
|
||||
console.warn(arg);
|
||||
}
|
||||
}
|
||||
|
||||
override async error(
|
||||
arg: string | Loggable,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
...params: any[]
|
||||
): Promise<void> {
|
||||
if (params.length) {
|
||||
console.error(arg, ...params);
|
||||
} else {
|
||||
console.error(arg);
|
||||
}
|
||||
}
|
||||
|
||||
override async fatal(
|
||||
arg: string | Loggable,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
...params: any[]
|
||||
): Promise<void> {
|
||||
return this.error(arg, params);
|
||||
}
|
||||
}
|
||||
|
||||
@injectable()
|
||||
class SilentArduinoDaemon extends ArduinoDaemonImpl {
|
||||
protected override onData(): void {
|
||||
// NOOP
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user