// Licensed to Cloudera, Inc. under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. Cloudera, Inc. licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import { CancellablePromise } from '../../../api/cancellablePromise'; import { AuthRequest, Session, SessionProperty } from './api'; import * as ExecutionApi from './api'; import * as ApiUtils from '../../../api/utils'; import sessionManager from './sessionManager'; describe('sessionManager.ts', () => { let spy: jest.SpyInstance< Promise, [ { type: string; properties?: SessionProperty[] | undefined; silenceErrors?: boolean | undefined; } ] >; beforeEach(() => { // sessionManager is a singleton so we need to clear out sessions between tests sessionManager.knownSessionPromises = {}; const sessionCount: { [key: string]: number } = {}; const getSessionCount = (type: string) => { if (!sessionCount[type]) { sessionCount[type] = 0; } return sessionCount[type]++; }; spy = jest.spyOn(ExecutionApi, 'createSession').mockImplementation( async (options: { type: string; properties?: SessionProperty[]; silenceErrors?: boolean; }): Promise => Promise.resolve({ session_id: options.type + '_' + getSessionCount(options.type), type: options.type, properties: options.properties || [], reuse_session: true, id: 0 }) ); }); afterEach(() => { sessionManager.knownSessionPromises = {}; spy.mockClear(); }); it('should create detached sessions', async () => { const mockProperties: unknown[] = [{ key: 'someKey', value: ['someValue'] }]; const sessionDetails = { type: 'impala', properties: mockProperties as SessionProperty[] }; expect((await sessionManager.getAllSessions()).length).toEqual(0); const session = await sessionManager.createDetachedSession(sessionDetails); expect(session.session_id).toEqual('impala_0'); expect(session.properties.length).toEqual(1); expect(session.properties[0].key).toEqual((mockProperties[0] as SessionProperty).key); expect(session.properties[0].value).toEqual((mockProperties[0] as SessionProperty).value); expect((await sessionManager.getAllSessions()).length).toEqual(0); expect(sessionManager.hasSession('impala')).toBeFalsy(); expect(ExecutionApi.createSession).toHaveBeenCalledWith(sessionDetails); }); it('should keep one sessions instance per type', async () => { expect((await sessionManager.getAllSessions()).length).toEqual(0); let session = await sessionManager.getSession({ type: 'impala' }); expect(session.session_id).toEqual('impala_0'); session = await sessionManager.getSession({ type: 'impala' }); expect(session.session_id).toEqual('impala_0'); expect((await sessionManager.getAllSessions()).length).toEqual(1); expect(sessionManager.hasSession('impala')).toBeTruthy(); expect(ExecutionApi.createSession).toHaveBeenCalledTimes(1); }); it('should keep track of multiple instance per type', async () => { expect((await sessionManager.getAllSessions()).length).toEqual(0); let session = await sessionManager.getSession({ type: 'impala' }); expect(session.session_id).toEqual('impala_0'); session = await sessionManager.getSession({ type: 'hive' }); expect(session.session_id).toEqual('hive_0'); expect((await sessionManager.getAllSessions()).length).toEqual(2); expect(sessionManager.hasSession('impala')).toBeTruthy(); expect(sessionManager.hasSession('hive')).toBeTruthy(); expect(ExecutionApi.createSession).toHaveBeenCalledTimes(2); }); it('should stop tracking sessions when closed', async () => { expect((await sessionManager.getAllSessions()).length).toEqual(0); // Create a session const session = await sessionManager.getSession({ type: 'impala' }); expect(session.session_id).toEqual('impala_0'); expect(sessionManager.hasSession('impala')).toBeTruthy(); //(url, data, options) => { // expect(JSON.parse(data.session).session_id).toEqual(session.session_id); // expect(options.silenceErrors).toBeTruthy(); // expect(url).toEqual(CLOSE_SESSION_API); // return new $.Deferred().resolve().promise(); // } // Close the session const postSpy = jest .spyOn(ApiUtils, 'post') .mockImplementation( ( url: string, data: unknown, options?: { dataType?: string; silenceErrors?: boolean; ignoreSuccessErrors?: boolean } ): CancellablePromise => { expect(JSON.parse((data as { session: string }).session).session_id).toEqual( session.session_id ); expect(options && options.silenceErrors).toBeTruthy(); expect(url).toContain('/close_session'); return new CancellablePromise(resolve => { resolve(); }); } ); await sessionManager.closeSession(session); expect(sessionManager.hasSession('impala')).toBeFalsy(); expect(ExecutionApi.createSession).toHaveBeenCalledTimes(1); expect(ApiUtils.post).toHaveBeenCalledTimes(1); postSpy.mockClear(); }); it('should be able to restart sessions', async () => { expect((await sessionManager.getAllSessions()).length).toEqual(0); // Create a session let session = await sessionManager.getSession({ type: 'impala' }); expect(session.session_id).toEqual('impala_0'); expect(sessionManager.hasSession('impala')).toBeTruthy(); // Restart the session const postSpy = jest.spyOn(ApiUtils, 'post').mockImplementation( (): CancellablePromise => new CancellablePromise(resolve => { resolve(); }) ); session = await sessionManager.restartSession(session); expect(session.session_id).toEqual('impala_1'); expect(sessionManager.hasSession('impala')).toBeTruthy(); expect(ExecutionApi.createSession).toHaveBeenCalledTimes(2); expect(ApiUtils.post).toHaveBeenCalledTimes(1); postSpy.mockClear(); }); });