test/gopls: print gopls traces when test fails
This is done by stubbing vscode.window.createOutputChannel with
a fake output channel that dumps buffered output when the
test fails.
Change-Id: I5fb1dff2e27ecb203f276ee1b82b1b6f7237ece4
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/233518
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/test/gopls/extension.test.ts b/test/gopls/extension.test.ts
index 7f5104c..2816e2e 100644
--- a/test/gopls/extension.test.ts
+++ b/test/gopls/extension.test.ts
@@ -6,9 +6,34 @@
import cp = require('child_process');
import * as fs from 'fs-extra';
import * as path from 'path';
+import sinon = require('sinon');
import * as vscode from 'vscode';
import { extensionId } from '../../src/const';
+// FakeOutputChannel is a fake output channel used to buffer
+// the output of the tested language client in an in-memory
+// string array until cleared.
+class FakeOutputChannel implements vscode.OutputChannel {
+ public name = 'FakeOutputChannel';
+ public show = sinon.fake(); // no-empty
+ public hide = sinon.fake(); // no-empty
+ public dispose = sinon.fake(); // no-empty
+
+ private buf = [] as string[];
+
+ public append = (v: string) => this.enqueue(v);
+ public appendLine = (v: string) => this.enqueue(v);
+ public clear = () => { this.buf = []; };
+ public toString = () => {
+ return this.buf.join('\n');
+ }
+
+ private enqueue = (v: string) => {
+ if (this.buf.length > 1024) { this.buf.shift(); }
+ this.buf.push(v.trim());
+ }
+}
+
// Env is a collection of test related variables
// that define the test environment such as vscode workspace.
class Env {
@@ -28,6 +53,8 @@
public extension: vscode.Extension<any>;
+ private fakeOutputChannel: FakeOutputChannel;
+
constructor(projectDir: string) {
if (!projectDir) {
assert.fail('project directory cannot be determined');
@@ -35,6 +62,7 @@
this.workspaceDir = path.resolve(projectDir, 'test/gopls/testfixtures/src/workspace');
this.fixturesRoot = path.resolve(projectDir, 'test/fixtures');
this.extension = vscode.extensions.getExtension(extensionId);
+ this.fakeOutputChannel = new FakeOutputChannel();
// Ensure the vscode extension host is configured as expected.
const workspaceFolder = path.resolve(vscode.workspace.workspaceFolders[0].uri.fsPath);
@@ -43,7 +71,18 @@
}
}
+ public flushTrace(print: boolean) {
+ if (print) {
+ console.log(this.fakeOutputChannel.toString());
+ this.fakeOutputChannel.clear();
+ }
+ }
+
public async setup() {
+ // stub the language server's output channel to intercept the trace.
+ sinon.stub(vscode.window, 'createOutputChannel')
+ .callThrough().withArgs('gopls (server)').returns(this.fakeOutputChannel);
+
await this.reset();
await this.extension.activate();
await sleep(2000); // allow the language server to start.
@@ -52,6 +91,10 @@
// but couldn't make it working yet.
}
+ public teardown() {
+ sinon.restore();
+ }
+
public async reset(fixtureDirName?: string) { // name of the fixtures subdirectory to use.
try {
// clean everything except the .gitignore file
@@ -97,6 +140,13 @@
});
suiteTeardown(async () => { await env.reset(); });
+ this.afterEach(function () {
+ // Note: this shouldn't use () => {...}. Arrow functions do not have 'this'.
+ // I don't know why but this.currentTest.state does not have the expected value when
+ // used with teardown.
+ env.flushTrace(this.currentTest.state === 'failed');
+ });
+
test('HoverProvider', async () => {
await env.reset('gogetdocTestData');
const { uri, doc } = await env.openDoc('test.go');