Path: blob/main/extensions/copilot/test/simulation/workbench/stores/baselineJSONProvider.ts
13399 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as fs from 'fs';6import * as mobx from 'mobx';7import * as path from 'path';8import { Disposable, toDisposable } from '../../../../src/util/vs/base/common/lifecycle';9import { IBaselineTestSummary, OLD_BASELINE_FILENAME, PRODUCED_BASELINE_FILENAME, SIMULATION_FOLDER_NAME } from '../../shared/sharedTypes';10import { REPO_ROOT, genericEquals } from '../utils/utils';11import { SimulationRunner } from './simulationRunner';1213export const BASELINE_PATH = path.join(REPO_ROOT, './test/simulation/baseline.json');1415export class BaselineJSONProvider extends Disposable {1617@mobx.observable18public workingTreeBaselineJSON: IBaselineTestSummary[] = [];1920/**21* Baseline produced by current run22*/23@mobx.observable24public baselineJSONProducedByRun: IBaselineTestSummary[] = [];2526/**27* Baseline snapshotted before current run28*/29@mobx.observable30public baselineJSONBeforeCurrentRun: IBaselineTestSummary[] = [];3132constructor(33private readonly _runner: SimulationRunner34) {35super();36mobx.makeObservable(this);3738// watch for working-tree baseline.json that's checked into git39const listener = () => this._updateWorkingTreeBaselineJSON();40fs.watchFile(BASELINE_PATH, listener);41this._register(toDisposable(() => fs.unwatchFile(BASELINE_PATH, listener)));4243this._updateWorkingTreeBaselineJSON();4445mobx.autorun(() => {46this._updateRunBaselines();47});48}4950private get oldBaselineJSONPath() {51return path.join(REPO_ROOT, SIMULATION_FOLDER_NAME, this._runner.selectedRun, OLD_BASELINE_FILENAME);52}5354private get baselineJSONProducedByRunPath() {55return path.join(REPO_ROOT, SIMULATION_FOLDER_NAME, this._runner.selectedRun, PRODUCED_BASELINE_FILENAME);56}5758private async _updateWorkingTreeBaselineJSON(): Promise<void> {59const newBaseline = await this._readBaselineJSON(BASELINE_PATH);60if (genericEquals(this.workingTreeBaselineJSON, newBaseline)) {61return;62}6364mobx.runInAction(() => {65this.workingTreeBaselineJSON = newBaseline;66});67}6869async updateRootBaselineJSON() {70await fs.promises.copyFile(this.baselineJSONProducedByRunPath, BASELINE_PATH);71this._updateWorkingTreeBaselineJSON();72}7374private async _updateRunBaselines(): Promise<void> {75if (this._runner.selectedRun === '') {76return;77}7879// TODO@ulugbekna: a baseline.old.json.txt is written only if `casUseBaseline` is true, so we need to make sure it doesn't throw here80const [bjBeforeCurrentRunR, bjProducedByRunR] = await Promise.allSettled([81this._readBaselineJSON(this.oldBaselineJSONPath),82this._readBaselineJSON(this.baselineJSONProducedByRunPath),83]);8485if (bjBeforeCurrentRunR.status === 'rejected') {86console.error(`Failed to read baseline.old.json.txt: ${bjBeforeCurrentRunR.reason}`);87return;88}8990if (bjProducedByRunR.status === 'rejected') {91console.error(`Failed to read baseline.produced.json.txt: ${bjProducedByRunR.reason}`);92return;93}9495const bjBeforeCurrentRun = bjBeforeCurrentRunR.value;96const bjProducedByRun = bjProducedByRunR.value;9798if (genericEquals(this.baselineJSONBeforeCurrentRun, bjBeforeCurrentRun) && genericEquals(this.baselineJSONProducedByRun, bjProducedByRun)) {99return;100}101102mobx.runInAction(() => {103this.baselineJSONBeforeCurrentRun = bjBeforeCurrentRun;104this.baselineJSONProducedByRun = bjProducedByRun;105});106}107108private async _readBaselineJSON(baselineJSONPath: string): Promise<IBaselineTestSummary[]> {109const contents = await fs.promises.readFile(baselineJSONPath, 'utf8');110const res = JSON.parse(contents) as IBaselineTestSummary[];111res.sort((a, b) => a.name.localeCompare(b.name));112return res;113}114}115116117