Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/test/electron-browser/resolveExternal.test.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import assert from 'assert';
6
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../base/test/common/utils.js';
7
import { NativeWindow } from '../../electron-browser/window.js';
8
import { ITunnelService, RemoteTunnel } from '../../../platform/tunnel/common/tunnel.js';
9
import { URI } from '../../../base/common/uri.js';
10
import { TestInstantiationService } from '../../../platform/instantiation/test/common/instantiationServiceMock.js';
11
import { IAddressProvider } from '../../../platform/remote/common/remoteAgentConnection.js';
12
import { workbenchInstantiationService } from './workbenchTestServices.js';
13
import { DisposableStore } from '../../../base/common/lifecycle.js';
14
15
type PortMap = Record<number, number>;
16
17
class TunnelMock implements Partial<ITunnelService> {
18
private assignedPorts: PortMap = {};
19
private expectedDispose = false;
20
21
reset(ports: PortMap) {
22
this.assignedPorts = ports;
23
}
24
25
expectDispose() {
26
this.expectedDispose = true;
27
}
28
29
getExistingTunnel(): Promise<string | RemoteTunnel | undefined> {
30
return Promise.resolve(undefined);
31
}
32
33
openTunnel(_addressProvider: IAddressProvider | undefined, _host: string | undefined, port: number): Promise<RemoteTunnel | string | undefined> | undefined {
34
if (!this.assignedPorts[port]) {
35
return Promise.reject(new Error('Unexpected tunnel request'));
36
}
37
const res: RemoteTunnel = {
38
localAddress: `localhost:${this.assignedPorts[port]}`,
39
tunnelRemoteHost: '4.3.2.1',
40
tunnelRemotePort: this.assignedPorts[port],
41
privacy: '',
42
dispose: () => {
43
assert(this.expectedDispose, 'Unexpected dispose');
44
this.expectedDispose = false;
45
return Promise.resolve();
46
}
47
};
48
delete this.assignedPorts[port];
49
return Promise.resolve(res);
50
}
51
52
validate() {
53
try {
54
assert(Object.keys(this.assignedPorts).length === 0, 'Expected tunnel to be used');
55
assert(!this.expectedDispose, 'Expected dispose to be called');
56
} finally {
57
this.expectedDispose = false;
58
}
59
}
60
}
61
62
class TestNativeWindow extends NativeWindow {
63
protected override create(): void { }
64
protected override registerListeners(): void { }
65
protected override enableMultiWindowAwareTimeout(): void { }
66
}
67
68
suite.skip('NativeWindow:resolveExternal', () => {
69
const disposables = new DisposableStore();
70
const tunnelMock = new TunnelMock();
71
let window: TestNativeWindow;
72
73
setup(() => {
74
const instantiationService: TestInstantiationService = <TestInstantiationService>workbenchInstantiationService(undefined, disposables);
75
instantiationService.stub(ITunnelService, tunnelMock);
76
window = disposables.add(instantiationService.createInstance(TestNativeWindow));
77
});
78
79
teardown(() => {
80
disposables.clear();
81
});
82
83
async function doTest(uri: string, ports: PortMap = {}, expectedUri?: string) {
84
tunnelMock.reset(ports);
85
const res = await window.resolveExternalUri(URI.parse(uri), {
86
allowTunneling: true,
87
openExternal: true
88
});
89
assert.strictEqual(!expectedUri, !res, `Expected URI ${expectedUri} but got ${res}`);
90
if (expectedUri && res) {
91
assert.strictEqual(res.resolved.toString(), URI.parse(expectedUri).toString());
92
}
93
tunnelMock.validate();
94
}
95
96
test('invalid', async () => {
97
await doTest('file:///foo.bar/baz');
98
await doTest('http://foo.bar/path');
99
});
100
test('simple', async () => {
101
await doTest('http://localhost:1234/path', { 1234: 1234 }, 'http://localhost:1234/path');
102
});
103
test('all interfaces', async () => {
104
await doTest('http://0.0.0.0:1234/path', { 1234: 1234 }, 'http://localhost:1234/path');
105
});
106
test('changed port', async () => {
107
await doTest('http://localhost:1234/path', { 1234: 1235 }, 'http://localhost:1235/path');
108
});
109
test('query', async () => {
110
await doTest('http://foo.bar/path?a=b&c=http%3a%2f%2flocalhost%3a4455', { 4455: 4455 }, 'http://foo.bar/path?a=b&c=http%3a%2f%2flocalhost%3a4455');
111
});
112
test('query with different port', async () => {
113
tunnelMock.expectDispose();
114
await doTest('http://foo.bar/path?a=b&c=http%3a%2f%2flocalhost%3a4455', { 4455: 4567 });
115
});
116
test('both url and query', async () => {
117
await doTest('http://localhost:1234/path?a=b&c=http%3a%2f%2flocalhost%3a4455',
118
{ 1234: 4321, 4455: 4455 },
119
'http://localhost:4321/path?a=b&c=http%3a%2f%2flocalhost%3a4455');
120
});
121
test('both url and query, query rejected', async () => {
122
tunnelMock.expectDispose();
123
await doTest('http://localhost:1234/path?a=b&c=http%3a%2f%2flocalhost%3a4455',
124
{ 1234: 4321, 4455: 5544 },
125
'http://localhost:4321/path?a=b&c=http%3a%2f%2flocalhost%3a4455');
126
});
127
128
ensureNoDisposablesAreLeakedInTestSuite();
129
});
130
131