@@ -10,22 +10,32 @@ import * as sinon from 'sinon';
1010import { captureScreenShot , createEventHandler , IExtensionTestApi , waitForCondition } from '../common.node' ;
1111import { executeSilently } from '../../kernels/helpers' ;
1212import { getPlainTextOrStreamOutput } from '../../kernels/kernel' ;
13- import { TestNotebookDocument } from '../datascience/notebook/executionHelper' ;
13+ import { TestNotebookDocument , createKernelController } from '../datascience/notebook/executionHelper' ;
1414import { IKernelProvider , LocalKernelConnectionMetadata } from '../../kernels/types' ;
1515import { KernelConnectionMetadata } from '../../api' ;
1616import { IControllerRegistration } from '../../notebooks/controllers/types' ;
17+ import { getKernelsApi } from '../../standalone/api/kernels' ;
18+ import { JVSC_EXTENSION_ID } from '../../platform/common/constants' ;
19+ import { Kernels } from '../../api' ;
20+ import {
21+ waitForExecutionCompletedSuccessfully ,
22+ waitForTextOutput ,
23+ getDefaultKernelConnection
24+ } from '../datascience/notebook/helper.node' ;
1725
1826suite ( '3rd Party Kernel Service API @kernelCore' , function ( ) {
1927 let api : IExtensionTestApi ;
2028 const disposables : IDisposable [ ] = [ ] ;
2129 this . timeout ( 120_000 ) ;
2230 let notebook : TestNotebookDocument ;
31+ let kernels : Kernels ;
2332 suiteSetup ( async function ( ) {
2433 logger . info ( 'Suite Setup 3rd Party Kernel Service API' ) ;
2534 this . timeout ( 120_000 ) ;
2635 try {
2736 api = await initialize ( ) ;
2837 await startJupyterServer ( ) ;
38+ kernels = await Promise . resolve ( getKernelsApi ( JVSC_EXTENSION_ID ) ) ;
2939 sinon . restore ( ) ;
3040 notebook = new TestNotebookDocument ( ) ;
3141 logger . info ( 'Suite Setup (completed)' ) ;
@@ -130,4 +140,51 @@ suite('3rd Party Kernel Service API @kernelCore', function () {
130140 assert . isNotOk ( kernelInfo ?. kernel ) ;
131141 assert . isTrue ( kernelInfo ?. isDisposed , 'Not disposed' ) ;
132142 } ) ;
143+
144+ test ( 'Can shutdown a kernel correctly via API' , async function ( ) {
145+ // Create a separate notebook for this test to avoid conflicts
146+ const shutdownNotebook = new TestNotebookDocument ( ) ;
147+
148+ // Create a simple test cell that we can execute
149+ const cell = await shutdownNotebook . appendCodeCell ( 'print("Hello from kernel")' ) ;
150+
151+ // Get a Python kernel for this test
152+ const kernelProvider = api . serviceContainer . get < IKernelProvider > ( IKernelProvider ) ;
153+ const metadata = await getDefaultKernelConnection ( ) ;
154+ const controller = createKernelController ( ) ;
155+ const kernel = kernelProvider . getOrCreate ( shutdownNotebook , {
156+ metadata,
157+ resourceUri : shutdownNotebook . uri ,
158+ controller
159+ } ) ;
160+ await kernel . start ( ) ;
161+
162+ // Get kernel execution service
163+ const kernelExecution = kernelProvider . getKernelExecution ( kernel ) ;
164+
165+ // First, start the kernel by executing a cell
166+ logger . info ( 'Step 1: Execute cell to ensure kernel is started' ) ;
167+ await Promise . all ( [
168+ kernelExecution . executeCell ( cell ) ,
169+ waitForExecutionCompletedSuccessfully ( cell ) ,
170+ waitForTextOutput ( cell , 'Hello from kernel' , 0 , false )
171+ ] ) ;
172+
173+ // Verify kernel is running
174+ assert . isFalse ( kernel . disposed , 'Kernel should not be disposed before shutdown' ) ;
175+
176+ // Get the API kernel instance (must execute code first for API to return kernel)
177+ const apiKernel = await kernels . getKernel ( shutdownNotebook . uri ) ;
178+ assert . isDefined ( apiKernel , 'Should get kernel via API after code execution' ) ;
179+
180+ // Now shutdown the kernel via API
181+ logger . info ( 'Step 2: Shutdown kernel via API' ) ;
182+ await apiKernel ! . shutdown ( ) ;
183+
184+ // After shutdown, the kernel should be disposed
185+ await waitForCondition ( async ( ) => kernel . disposed , 30_000 , 'Kernel should be disposed after API shutdown' ) ;
186+
187+ logger . info ( 'Step 3: Verify kernel is disposed' ) ;
188+ assert . isTrue ( kernel . disposed , 'Kernel should be disposed after API shutdown' ) ;
189+ } ) ;
133190} ) ;
0 commit comments