@@ -9,10 +9,12 @@ import { injectable } from 'inversify';
99import * as os from 'os' ;
1010import * as path from 'path' ;
1111import { Readable , Writable } from 'stream' ;
12+ import * as TypeMoq from 'typemoq' ;
1213import * as uuid from 'uuid/v4' ;
1314import { Disposable , Uri } from 'vscode' ;
1415import { CancellationToken , CancellationTokenSource } from 'vscode-jsonrpc' ;
1516
17+ import { IApplicationShell } from '../../client/common/application/types' ;
1618import { Cancellation , CancellationError } from '../../client/common/cancellation' ;
1719import { EXTENSION_ROOT_DIR } from '../../client/common/constants' ;
1820import { traceError , traceInfo } from '../../client/common/logger' ;
@@ -59,8 +61,6 @@ suite('DataScience notebook tests', () => {
5961 setup ( ( ) => {
6062 ioc = new DataScienceIocContainer ( ) ;
6163 ioc . registerDataScienceTypes ( ) ;
62- jupyterExecution = ioc . serviceManager . get < IJupyterExecution > ( IJupyterExecution ) ;
63- processFactory = ioc . serviceManager . get < IProcessServiceFactory > ( IProcessServiceFactory ) ;
6464 } ) ;
6565
6666 teardown ( async ( ) => {
@@ -199,8 +199,14 @@ suite('DataScience notebook tests', () => {
199199 } ) ;
200200 }
201201
202- function runTest ( name : string , func : ( ) => Promise < void > , _notebookProc ?: ChildProcess ) {
202+ function runTest ( name : string , func : ( ) => Promise < void > , _notebookProc ?: ChildProcess , rebindFunc ?: ( ) => void ) {
203203 test ( name , async ( ) => {
204+ // Give tests a chance to rebind IOC services before we fetch jupyterExecution and processFactory
205+ if ( rebindFunc ) {
206+ rebindFunc ( ) ;
207+ }
208+ jupyterExecution = ioc . serviceManager . get < IJupyterExecution > ( IJupyterExecution ) ;
209+ processFactory = ioc . serviceManager . get < IProcessServiceFactory > ( IProcessServiceFactory ) ;
204210 console . log ( `Starting test ${ name } ...` ) ;
205211 if ( await jupyterExecution . isNotebookSupported ( ) ) {
206212 return func ( ) ;
@@ -282,6 +288,53 @@ suite('DataScience notebook tests', () => {
282288 }
283289 } ) ;
284290
291+ // Connect to a server that doesn't have a token or password, customers use this and we regressed it once
292+ runTest ( 'Remote No Auth' , async ( ) => {
293+ const python = await getNotebookCapableInterpreter ( ioc , processFactory ) ;
294+ const procService = await processFactory . create ( ) ;
295+
296+ if ( procService && python ) {
297+ const connectionFound = createDeferred ( ) ;
298+ const configFile = path . join ( EXTENSION_ROOT_DIR , 'src' , 'test' , 'datascience' , 'serverConfigFiles' , 'remoteNoAuth.py' ) ;
299+ const exeResult = procService . execObservable ( python . path , [ '-m' , 'jupyter' , 'notebook' , `--config=${ configFile } ` ] , { env : process . env , throwOnStdErr : false } ) ;
300+ disposables . push ( exeResult ) ;
301+
302+ exeResult . out . subscribe ( ( output : Output < string > ) => {
303+ traceInfo ( `remote jupyter output: ${ output . out } ` ) ;
304+ const connectionURL = getIPConnectionInfo ( output . out ) ;
305+ if ( connectionURL ) {
306+ connectionFound . resolve ( connectionURL ) ;
307+ }
308+ } ) ;
309+
310+ const connString = await connectionFound . promise ;
311+ const uri = connString as string ;
312+
313+ // We have a connection string here, so try to connect jupyterExecution to the notebook server
314+ const server = await jupyterExecution . connectToNotebookServer ( { uri, useDefaultConfig : true , purpose : '' } ) ;
315+ const notebook = server ? await server . createNotebook ( Uri . parse ( Identifiers . InteractiveWindowIdentity ) ) : undefined ;
316+ if ( ! notebook ) {
317+ assert . fail ( 'Failed to connect to remote password server' ) ;
318+ } else {
319+ await verifySimple ( notebook , `a=1${ os . EOL } a` , 1 ) ;
320+ }
321+ // Have to dispose here otherwise the process may exit before hand and mess up cleanup.
322+ await server ! . dispose ( ) ;
323+ }
324+ } , undefined , ( ) => {
325+ const dummyDisposable = {
326+ dispose : ( ) => { return ; }
327+ } ;
328+ const appShell = TypeMoq . Mock . ofType < IApplicationShell > ( ) ;
329+ appShell . setup ( a => a . showErrorMessage ( TypeMoq . It . isAnyString ( ) ) ) . returns ( ( e ) => { throw e ; } ) ;
330+ appShell . setup ( a => a . showInformationMessage ( TypeMoq . It . isAny ( ) , TypeMoq . It . isAny ( ) ) ) . returns ( ( ) => Promise . resolve ( '' ) ) ;
331+ appShell . setup ( a => a . showInformationMessage ( TypeMoq . It . isAny ( ) , TypeMoq . It . isAny ( ) , TypeMoq . It . isAny ( ) ) ) . returns ( ( _a1 : string , a2 : string , _a3 : string ) => Promise . resolve ( a2 ) ) ;
332+ appShell . setup ( a => a . showInformationMessage ( TypeMoq . It . isAny ( ) , TypeMoq . It . isAny ( ) , TypeMoq . It . isAny ( ) , TypeMoq . It . isAny ( ) ) ) . returns ( ( _a1 : string , a2 : string , _a3 : string , _a4 : string ) => Promise . resolve ( a2 ) ) ;
333+ appShell . setup ( a => a . showInputBox ( TypeMoq . It . isAny ( ) ) ) . returns ( ( ) => Promise . resolve ( '' ) ) ;
334+ appShell . setup ( a => a . setStatusBarMessage ( TypeMoq . It . isAny ( ) ) ) . returns ( ( ) => dummyDisposable ) ;
335+ ioc . serviceManager . rebindInstance < IApplicationShell > ( IApplicationShell , appShell . object ) ;
336+ } ) ;
337+
285338 runTest ( 'Remote Password' , async ( ) => {
286339 const python = await getNotebookCapableInterpreter ( ioc , processFactory ) ;
287340 const procService = await processFactory . create ( ) ;
@@ -368,6 +421,8 @@ suite('DataScience notebook tests', () => {
368421 } ) ;
369422
370423 test ( 'Not installed' , async ( ) => {
424+ jupyterExecution = ioc . serviceManager . get < IJupyterExecution > ( IJupyterExecution ) ;
425+ processFactory = ioc . serviceManager . get < IProcessServiceFactory > ( IProcessServiceFactory ) ;
371426 // Rewire our data we use to search for processes
372427 class EmptyInterpreterService implements IInterpreterService {
373428 public get hasInterpreters ( ) : Promise < boolean > {
@@ -1001,6 +1056,8 @@ plt.show()`,
10011056 } ) ;
10021057
10031058 test ( 'Notebook launch failure' , async function ( ) {
1059+ jupyterExecution = ioc . serviceManager . get < IJupyterExecution > ( IJupyterExecution ) ;
1060+ processFactory = ioc . serviceManager . get < IProcessServiceFactory > ( IProcessServiceFactory ) ;
10041061 if ( ! ioc . mockJupyter ) {
10051062 // tslint:disable-next-line: no-invalid-this
10061063 this . skip ( ) ;
0 commit comments