Path: blob/main/extensions/copilot/test/simulation/workbench/stores/testRun.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 { INLINE_STATE_TAG, InterceptedRequest, ISerializedFileEdit, ISerializedNesUserEditsHistory, IWorkspaceState, IWrittenFile, NES_LOG_CONTEXT_TAG, NES_USER_EDITS_HISTORY_TAG, NEXT_EDIT_SUGGESTION_TAG, OutputAnnotation, REQUESTS_TAG } from '../../shared/sharedTypes';9import { ObservablePromise } from '../utils/utils';10import { EvaluationError } from './amlResults';11import { InitialWorkspaceState, InteractionWorkspaceState, WorkspaceState } from './simulationWorkspaceState';121314export class TestRun {1516@mobx.observable17public errorsOnlyInBefore: EvaluationError[] | undefined = undefined;1819@mobx.observable20public errorsOnlyInAfter: any[] | undefined = undefined;2122@mobx.observable23public stdout: string | undefined = undefined;2425@mobx.observable26public stderr: string | undefined = undefined;2728@mobx.observable29public pass: boolean;3031@mobx.observable32public error: string | undefined;3334@mobx.observable35public generatedTestCaseCount: number | undefined = undefined;3637@mobx.observable38public generatedAssertCount: number | undefined = undefined;3940@mobx.observable41public expectedDiff: string | undefined = undefined;4243@mobx.computed44public get hasInlineState(): boolean {45return this.writtenFiles.some(f => f.tag === INLINE_STATE_TAG);46}4748@mobx.computed49public get nextEditSuggestion(): ObservablePromise<ISerializedFileEdit | undefined> {50return new ObservablePromise(this._getNextEditSuggestion(), undefined);51}5253@mobx.computed54public get nesUserEditsHistory(): ObservablePromise<ISerializedNesUserEditsHistory | undefined> {55return new ObservablePromise(this._getNesUserEditsHistory(), undefined);56}5758@mobx.computed59public get nesLogContext(): ObservablePromise<string | undefined> {60return new ObservablePromise(this._getNesLogContext(), undefined);61}6263@mobx.computed64public get inlineChatWorkspaceStates(): ObservablePromise<WorkspaceState[]> {65return new ObservablePromise(this._getInlineState(), []);66}6768@mobx.computed69public get requests(): ObservablePromise<InterceptedRequest[]> {70return new ObservablePromise(this._getInterceptedRequests(), []);71}7273constructor(74public readonly runNumber: number,75pass: boolean, // this is mutable because it may be set later/lazily76public readonly explicitScore: number | undefined,77error: string | undefined,78public readonly duration: number,79public readonly writtenFilesBaseDir: string,80public readonly writtenFiles: IWrittenFile[],81public readonly averageRequestDuration: number | undefined,82public readonly requestCount: number | undefined,83public readonly hasCacheMiss: boolean | undefined,84public readonly annotations: OutputAnnotation[] = [],85) {86this.pass = pass;87this.error = error;88mobx.makeObservable(this);89}9091private _inlineStatePromise: Promise<WorkspaceState[]> | undefined;92private async _getInlineState(): Promise<WorkspaceState[]> {93if (!this._inlineStatePromise) {94this._inlineStatePromise = this._doGetInlineState();95}96return this._inlineStatePromise;97}9899private async _doGetInlineState(): Promise<WorkspaceState[]> {100const contents = await this.getWrittenFileByTag(INLINE_STATE_TAG);101if (!contents) {102return [];103}104const result = JSON.parse(contents) as IWorkspaceState[];105return result.map((el) => {106if (el.kind === 'initial') {107return new InitialWorkspaceState(el, this.writtenFilesBaseDir);108}109return new InteractionWorkspaceState(el, this.writtenFilesBaseDir);110});111}112113private _nextEditSuggestionPromise: Promise<ISerializedFileEdit | undefined> | undefined;114private _getNextEditSuggestion(): Promise<ISerializedFileEdit | undefined> {115if (!this._nextEditSuggestionPromise) {116this._nextEditSuggestionPromise = this._doGetNextEditSuggestion();117}118return this._nextEditSuggestionPromise;119}120121private async _doGetNextEditSuggestion(): Promise<ISerializedFileEdit | undefined> {122const contents = await this.getWrittenFileByTag(NEXT_EDIT_SUGGESTION_TAG);123if (!contents) {124return undefined;125}126return JSON.parse(contents) as ISerializedFileEdit;127}128129private _nesUserEditsHistoryPromise: Promise<ISerializedNesUserEditsHistory | undefined> | undefined = undefined;130private _getNesUserEditsHistory(): Promise<ISerializedNesUserEditsHistory | undefined> {131if (this._nesUserEditsHistoryPromise === undefined) {132this._nesUserEditsHistoryPromise = this._doGetNesUserEditsHistory();133}134return this._nesUserEditsHistoryPromise;135}136137private async _doGetNesUserEditsHistory(): Promise<ISerializedNesUserEditsHistory | undefined> {138const contents = await this.getWrittenFileByTag(NES_USER_EDITS_HISTORY_TAG);139if (!contents) {140return undefined;141}142return JSON.parse(contents) as ISerializedNesUserEditsHistory;143}144145private _nesLogContext: Promise<string | undefined> | undefined = undefined;146private _getNesLogContext(): Promise<string | undefined> {147if (this._nesLogContext === undefined) {148this._nesLogContext = this._doGetNesLogContext();149}150return this._nesLogContext;151}152153private async _doGetNesLogContext(): Promise<string | undefined> {154const contents = await this.getWrittenFileByTag(NES_LOG_CONTEXT_TAG);155if (!contents) {156return undefined;157}158return JSON.parse(contents);159}160161private _interceptedRequestsPromise: Promise<InterceptedRequest[]> | undefined;162private async _getInterceptedRequests(): Promise<InterceptedRequest[]> {163if (!this._interceptedRequestsPromise) {164this._interceptedRequestsPromise = this._doGetInterceptedRequests();165}166return this._interceptedRequestsPromise;167}168169private async _doGetInterceptedRequests(): Promise<InterceptedRequest[]> {170const contents = await this.getWrittenFileByTag(REQUESTS_TAG);171if (!contents) {172return [];173}174const result = JSON.parse(contents);175if (Array.isArray(result)) {176return result.map(InterceptedRequest.fromJSON);177}178return [];179}180181private async getWrittenFileByTag(tag: string): Promise<string | undefined> {182const writtenFile = this.writtenFiles.find(f => f.tag === tag);183if (!writtenFile) {184return undefined;185}186const contents = await fs.promises.readFile(path.join(this.writtenFilesBaseDir, writtenFile.relativePath), 'utf8');187return contents;188}189}190191192