// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 import { LogService } from "./log-service"; import { ApiActions } from "services/api/api-actions"; import axios from "axios"; import { WebDAVRequestConfig } from "common/webdav"; import { LogEventType } from "models/log"; describe("LogService", () => { let apiWebdavClient: any; const axiosInstance = axios.create(); const actions: ApiActions = { progressFn: (id: string, working: boolean) => {}, errorFn: (id: string, message: string) => {} }; beforeEach(() => { apiWebdavClient = { delete: jest.fn(), upload: jest.fn(), mkdir: jest.fn(), get: jest.fn(), propfind: jest.fn(), } as any; }); it("lists log files using propfind on live logs api endpoint", async () => { const logService = new LogService(axiosInstance, apiWebdavClient, actions); // given const containerRequest = {uuid: 'zzzzz-xvhdp-000000000000000', containerUuid: 'zzzzz-dz642-000000000000000'}; const xmlData = ` /arvados/v1/container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}/ Tue, 15 Aug 2023 12:54:37 GMT HTTP/1.1 200 OK /arvados/v1/container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}/stdout.txt stdout.txt 15 text/plain; charset=utf-8 "177b8fb161ff9f58f" Tue, 15 Aug 2023 12:54:37 GMT HTTP/1.1 200 OK /arvados/v1/container_requests/${containerRequest.uuid}/wrongpath.txt wrongpath.txt 15 text/plain; charset=utf-8 "177b8fb161ff9f58f" Tue, 15 Aug 2023 12:54:37 GMT HTTP/1.1 200 OK `; const xmlDoc = (new DOMParser()).parseFromString(xmlData, "text/xml"); apiWebdavClient.propfind = jest.fn().mockReturnValue(Promise.resolve({responseXML: xmlDoc})); // when const logs = await logService.listLogFiles(containerRequest); // then expect(apiWebdavClient.propfind).toHaveBeenCalledWith(`container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}`); expect(logs.length).toEqual(1); expect(logs[0]).toHaveProperty('name', 'stdout.txt'); expect(logs[0]).toHaveProperty('type', 'file'); }); it("requests log file contents with correct range request", async () => { const logService = new LogService(axiosInstance, apiWebdavClient, actions); // given const containerRequest = {uuid: 'zzzzz-xvhdp-000000000000000', containerUuid: 'zzzzz-dz642-000000000000000'}; const fileRecord = {name: `stdout.txt`}; const fileContents = `Line 1\nLine 2\nLine 3`; apiWebdavClient.get = jest.fn().mockImplementation((path: string, options: WebDAVRequestConfig) => { const matches = /bytes=([0-9]+)-([0-9]+)/.exec(options.headers?.Range || ''); if (matches?.length === 3) { return Promise.resolve({responseText: fileContents.substring(Number(matches[1]), Number(matches[2]) + 1)}) } return Promise.reject(); }); // when let result = await logService.getLogFileContents(containerRequest, fileRecord, 0, 3); // then expect(apiWebdavClient.get).toHaveBeenCalledWith( `container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}/${fileRecord.name}`, {headers: {Range: `bytes=0-3`}} ); expect(result.logType).toEqual(LogEventType.STDOUT); expect(result.contents).toEqual(['Line']); // when result = await logService.getLogFileContents(containerRequest, fileRecord, 0, 10); // then expect(apiWebdavClient.get).toHaveBeenCalledWith( `container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}/${fileRecord.name}`, {headers: {Range: `bytes=0-10`}} ); expect(result.logType).toEqual(LogEventType.STDOUT); expect(result.contents).toEqual(['Line 1', 'Line']); // when result = await logService.getLogFileContents(containerRequest, fileRecord, 6, 14); // then expect(apiWebdavClient.get).toHaveBeenCalledWith( `container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}/${fileRecord.name}`, {headers: {Range: `bytes=6-14`}} ); expect(result.logType).toEqual(LogEventType.STDOUT); expect(result.contents).toEqual(['', 'Line 2', 'L']); }); });