From 5ee7bad25cb8565183c17feff18e1b8b83abb6d4 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Fri, 27 Nov 2020 23:10:23 +0100 Subject: [PATCH 01/27] add benchmark tests add more env variables add oidc auth flow add playbooks for better test reusability add more api endpoints update rollup config for test file transpilation update test folder structure split api package into smaller chunks --- tests/k6/README.md | 10 ++- tests/k6/package.json | 3 +- tests/k6/rollup.config.js | 5 +- tests/k6/src/lib/api.ts | 28 ------- tests/k6/src/lib/api/api.ts | 12 +++ tests/k6/src/lib/api/dav.ts | 45 ++++++++++ tests/k6/src/lib/api/index.ts | 3 + tests/k6/src/lib/api/users.ts | 17 ++++ tests/k6/src/lib/auth.ts | 87 ++++++++++++++++++++ tests/k6/src/lib/defaults.ts | 16 +++- tests/k6/src/lib/index.ts | 7 +- tests/k6/src/lib/playbook/dav.ts | 70 ++++++++++++++++ tests/k6/src/lib/playbook/index.ts | 1 + tests/k6/src/lib/types.ts | 14 ++++ tests/k6/src/lib/utils.ts | 7 +- tests/k6/src/test-issue-162.ts | 27 ------ tests/k6/src/test/benchmark/file-download.ts | 53 ++++++++++++ tests/k6/src/test/benchmark/file-upload.ts | 44 ++++++++++ tests/k6/src/test/issue/github/ocis/162.ts | 10 +++ tests/k6/yarn.lock | 19 +++++ 20 files changed, 411 insertions(+), 67 deletions(-) delete mode 100644 tests/k6/src/lib/api.ts create mode 100644 tests/k6/src/lib/api/api.ts create mode 100644 tests/k6/src/lib/api/dav.ts create mode 100644 tests/k6/src/lib/api/index.ts create mode 100644 tests/k6/src/lib/api/users.ts create mode 100644 tests/k6/src/lib/auth.ts create mode 100644 tests/k6/src/lib/playbook/dav.ts create mode 100644 tests/k6/src/lib/playbook/index.ts delete mode 100644 tests/k6/src/test-issue-162.ts create mode 100644 tests/k6/src/test/benchmark/file-download.ts create mode 100644 tests/k6/src/test/benchmark/file-upload.ts create mode 100644 tests/k6/src/test/issue/github/ocis/162.ts diff --git a/tests/k6/README.md b/tests/k6/README.md index d45473698..60635ae7d 100644 --- a/tests/k6/README.md +++ b/tests/k6/README.md @@ -11,5 +11,13 @@ $ yarn build ## How to run ```console -k6 run ./dist/TESTNAME.js +k6 run ./dist/test/NAME_OF_TEST.js +``` + +## Environment variables +```console +$ OC_OCIS_HOST=URL k6 run ... +$ OC_OIDC_HOST=URL k6 run ... +$ OC_OIDC=BOOL k6 run ... +$ OC_TEST_FILE=STRING k6 run ... ``` \ No newline at end of file diff --git a/tests/k6/package.json b/tests/k6/package.json index d2ff6c66a..fd7836fa2 100644 --- a/tests/k6/package.json +++ b/tests/k6/package.json @@ -44,6 +44,7 @@ "typescript": "^3.8.3" }, "dependencies": { - "lodash": "^4.17.20" + "lodash": "^4.17.20", + "query-string": "^6.13.7" } } diff --git a/tests/k6/rollup.config.js b/tests/k6/rollup.config.js index 3f78f0a1d..bc87e1023 100644 --- a/tests/k6/rollup.config.js +++ b/tests/k6/rollup.config.js @@ -4,7 +4,6 @@ import resolve from '@rollup/plugin-node-resolve' import babel from 'rollup-plugin-babel' import { terser } from 'rollup-plugin-terser' import multiInput from 'rollup-plugin-multi-input'; -import path from 'path'; import utils from '@rollup/pluginutils'; import pkg from './package.json'; @@ -12,7 +11,7 @@ const extensions = ['.js', '.ts']; export default [ { - input: ['src/test-*.ts'], + input: ['src/test/**/*.ts'], external: utils.createFilter([ 'k6/**', ...Object.keys(pkg.devDependencies), @@ -27,7 +26,7 @@ export default [ ], plugins: [ multiInput({ - transformOutputPath: (output, input) => path.basename(output), + transformOutputPath: (output, input) => `tests/${output.split('/').join('-')}`, }), json(), resolve( diff --git a/tests/k6/src/lib/api.ts b/tests/k6/src/lib/api.ts deleted file mode 100644 index 61dfede2e..000000000 --- a/tests/k6/src/lib/api.ts +++ /dev/null @@ -1,28 +0,0 @@ -import encoding from 'k6/encoding'; -import {bytes} from "k6"; -import http, {RefinedResponse, ResponseType} from "k6/http"; -import * as defaults from "./defaults"; -import * as types from "./types"; - -export const uploadFile = (account: types.Account, data: bytes, name: string): RefinedResponse => { - return http.put( - `https://${defaults.host.name}/remote.php/dav/files/${account.login}/${name}`, - data as any, - { - headers: { - Authorization: `Basic ${encoding.b64encode(`${account.login}:${account.password}`)}`, - } - } - ); -} - -export const userInfo = (account: any): RefinedResponse => { - return http.get( - `https://${defaults.host.name}/ocs/v1.php/cloud/users/${account.login}`, - { - headers: { - Authorization: `Basic ${encoding.b64encode(`${account.login}:${account.password}`)}`, - }, - } - ); -} \ No newline at end of file diff --git a/tests/k6/src/lib/api/api.ts b/tests/k6/src/lib/api/api.ts new file mode 100644 index 000000000..8b9f3e344 --- /dev/null +++ b/tests/k6/src/lib/api/api.ts @@ -0,0 +1,12 @@ +import encoding from 'k6/encoding'; +import * as types from "../types"; + +export const headersDefault = ({credential}: { credential: types.Account | types.Token }): { [key: string]: string } => { + const isOIDCGuard = (credential as types.Token).tokenType !== undefined; + const authOIDC = credential as types.Token; + const authBasic = credential as types.Account; + + return { + Authorization: isOIDCGuard ? `${authOIDC.tokenType} ${authOIDC.accessToken}` : `Basic ${encoding.b64encode(`${authBasic.login}:${authBasic.password}`)}`, + } +} \ No newline at end of file diff --git a/tests/k6/src/lib/api/dav.ts b/tests/k6/src/lib/api/dav.ts new file mode 100644 index 000000000..77d03e8c9 --- /dev/null +++ b/tests/k6/src/lib/api/dav.ts @@ -0,0 +1,45 @@ +import http, {RefinedResponse, ResponseType} from "k6/http"; +import * as api from './api' +import * as defaults from "../defaults"; +import * as types from "../types"; + +export const fileUpload = ( + {credential, userName, asset}: { credential: types.Account | types.Token; userName: string; asset: types.Asset } +): RefinedResponse => { + return http.put( + `${defaults.OC_OCIS_HOST}/remote.php/dav/files/${userName}/${asset.fileName}`, + asset.bytes as any, + { + headers: { + ...api.headersDefault({credential}) + } + } + ); +} + +export const fileDownload = ( + {credential, userName, fileName}: { credential: types.Account | types.Token; userName: string; fileName: string } +): RefinedResponse => { + return http.get( + `${defaults.OC_OCIS_HOST}/remote.php/dav/files/${userName}/${fileName}`, + { + headers: { + ...api.headersDefault({credential}) + } + } + ); +} + +export const fileDelete = ( + {credential, userName, fileName}: { credential: types.Account | types.Token; userName: string; fileName: string } +): RefinedResponse => { + return http.del( + `${defaults.OC_OCIS_HOST}/remote.php/dav/files/${userName}/${fileName}`, + {}, + { + headers: { + ...api.headersDefault({credential}) + } + } + ); +} \ No newline at end of file diff --git a/tests/k6/src/lib/api/index.ts b/tests/k6/src/lib/api/index.ts new file mode 100644 index 000000000..52cba2cff --- /dev/null +++ b/tests/k6/src/lib/api/index.ts @@ -0,0 +1,3 @@ +export * as api from './api' +export * as dav from './dav' +export * as users from './users' \ No newline at end of file diff --git a/tests/k6/src/lib/api/users.ts b/tests/k6/src/lib/api/users.ts new file mode 100644 index 000000000..c15e36a51 --- /dev/null +++ b/tests/k6/src/lib/api/users.ts @@ -0,0 +1,17 @@ +import http, {RefinedResponse, ResponseType} from "k6/http"; +import * as api from './api' +import * as defaults from "../defaults"; +import * as types from "../types"; + +export const userInfo = ( + {credential, userName}: { credential: types.Account | types.Token; userName: string; } +): RefinedResponse => { + return http.get( + `${defaults.OC_OCIS_HOST}/ocs/v1.php/cloud/users/${userName}`, + { + headers: { + ...api.headersDefault({credential}) + }, + } + ); +} \ No newline at end of file diff --git a/tests/k6/src/lib/auth.ts b/tests/k6/src/lib/auth.ts new file mode 100644 index 000000000..73e784bf7 --- /dev/null +++ b/tests/k6/src/lib/auth.ts @@ -0,0 +1,87 @@ +import * as defaults from "./defaults"; +import http from "k6/http"; +import queryString from "query-string"; +import * as types from "./types"; +import {fail} from 'k6'; +import {get} from 'lodash' + +export const oidc = (account: types.Account): types.Token => { + const redirectUri = `${defaults.OC_OIDC_HOST}/oidc-callback.html`; + + const logonUri = `${defaults.OC_OIDC_HOST}/signin/v1/identifier/_/logon`; + const logonResponse = http.post( + logonUri, + JSON.stringify( + { + params: [account.login, account.password, '1'], + hello: { + scope: 'openid profile email', + client_id: 'phoenix', + redirect_uri: redirectUri, + flow: 'oidc' + }, + 'state': 'vp42cf' + }, + ), + { + headers: { + 'Kopano-Konnect-XSRF': '1', + Referer: defaults.OC_OIDC_HOST, + 'Content-Type': 'application/json', + }, + }, + ); + const authorizeURI = get(logonResponse.json(), 'hello.continue_uri'); + + if (logonResponse.status != 200 || !authorizeURI) { + fail(logonUri); + } + + const authorizeUri = `${authorizeURI}?${ + queryString.stringify( + { + client_id: 'phoenix', + prompt: 'none', + redirect_uri: redirectUri, + response_mode: 'query', + response_type: 'code', + scope: 'openid profile email', + }, + ) + }`; + const authorizeResponse = http.get( + authorizeUri, + { + redirects: 0, + }, + ) + const authCode = get(queryString.parseUrl(authorizeResponse.headers.Location), 'query.code') + + if (authorizeResponse.status != 302 || !authCode) { + fail(authorizeURI); + } + + const tokenUrl = `${defaults.OC_OIDC_HOST}/konnect/v1/token`; + const tokenResponse = http.post( + tokenUrl, + { + client_id: 'phoenix', + code: authCode, + redirect_uri: redirectUri, + grant_type: 'authorization_code' + } + ) + + const token = { + accessToken: get(tokenResponse.json(), 'access_token'), + tokenType: get(tokenResponse.json(), 'token_type'), + idToken: get(tokenResponse.json(), 'id_token'), + expiresIn: get(tokenResponse.json(), 'expires_in'), + } + + if (tokenResponse.status != 200 || !token.accessToken || !token.tokenType || !token.idToken || !token.expiresIn) { + fail(authorizeURI); + } + + return token +} \ No newline at end of file diff --git a/tests/k6/src/lib/defaults.ts b/tests/k6/src/lib/defaults.ts index 1fac440ef..04746a834 100644 --- a/tests/k6/src/lib/defaults.ts +++ b/tests/k6/src/lib/defaults.ts @@ -1,10 +1,18 @@ import * as types from './types'; +import {Options} from "k6/options"; -export const host = { - name: __ENV.OC_HOST_NAME || 'localhost:9200' +const ocTestFile = '../_files/' + (__ENV.OC_TEST_FILE || 'kb_50.jpg').split('/').pop() +export const OC_OCIS_HOST = __ENV.OC_OCIS_HOST || 'https://localhost:9200' +export const OC_OIDC_HOST = __ENV.OC_OIDC_HOST || OC_OCIS_HOST +export const OC_OIDC = __ENV.OC_OIDC === 'true' || false +export const OC_TEST_FILE = { + fileName: ocTestFile, + bytes: open(ocTestFile, 'b'), } - -export const accounts: { [key: string]: types.Account; } = { +export const k6OptionsDefault: Options = { + insecureSkipTLSVerify: true, +}; +export const knownAccounts: { [key: string]: types.Account; } = { einstein: { login: 'einstein', password: 'relativity', diff --git a/tests/k6/src/lib/index.ts b/tests/k6/src/lib/index.ts index 7a9f89677..fe9d94422 100644 --- a/tests/k6/src/lib/index.ts +++ b/tests/k6/src/lib/index.ts @@ -1,3 +1,6 @@ -export * as defaults from './defaults' export * as api from './api' -export * as utils from './utils' \ No newline at end of file +export * as playbook from './playbook' +export * as auth from './auth' +export * as defaults from './defaults' +export * as types from './types' +export * as utils from './utils' diff --git a/tests/k6/src/lib/playbook/dav.ts b/tests/k6/src/lib/playbook/dav.ts new file mode 100644 index 000000000..089710847 --- /dev/null +++ b/tests/k6/src/lib/playbook/dav.ts @@ -0,0 +1,70 @@ +import {Gauge, Trend} from "k6/metrics"; +import * as api from "../api"; +import * as utils from "../utils"; +import {bytes, check} from "k6"; +import * as types from "../types"; + +export const fileUpload = () => { + const fileUploadTrend = new Trend('occ_file_upload_trend', true); + const fileUploadErrorRate = new Gauge('occ_file_upload_error_rate'); + + return ({credential, userName, asset}: { credential: types.Account | types.Token; userName: string; asset: types.Asset }): string => { + const fileName = `upload-${userName}-${__VU}-${__ITER}.${utils.extension(asset.fileName)}`; + const uploadResponse = api.dav.fileUpload({ + credential: credential as any, + asset: { + fileName, + bytes: asset.bytes, + }, + userName, + }); + + check(uploadResponse, { + 'file upload status is 201': () => uploadResponse.status === 201, + }) || fileUploadErrorRate.add(1); + + fileUploadTrend.add(uploadResponse.timings.duration) + + return fileName + } +}; + +export const fileDelete = () => { + const fileDeleteTrend = new Trend('occ_file_delete_trend', true); + const fileDeleteErrorRate = new Gauge('occ_file_delete_error_rate'); + + return ({credential, userName, fileName}: { credential: types.Account | types.Token, userName: string; fileName: string }) => { + const deleteResponse = api.dav.fileDelete({ + credential: credential as any, + fileName, + userName, + }); + + check(deleteResponse, { + 'file delete status is 204': () => deleteResponse.status === 204, + }) || fileDeleteErrorRate.add(1); + + fileDeleteTrend.add(deleteResponse.timings.duration) + } +}; + +export const fileDownload = () => { + const fileDownloadTrend = new Trend('occ_file_download_trend', true); + const fileDownloadErrorRate = new Gauge('occ_file_download_error_rate'); + + return ({credential, userName, fileName}: { credential: types.Account | types.Token, userName: string; fileName: string }): bytes => { + const downloadResponse = api.dav.fileDownload({ + credential: credential as any, + fileName, + userName, + }); + + check(downloadResponse, { + 'file download status is 200': () => downloadResponse.status === 200, + }) || fileDownloadErrorRate.add(1); + + fileDownloadTrend.add(downloadResponse.timings.duration) + + return downloadResponse.body as bytes + } +}; diff --git a/tests/k6/src/lib/playbook/index.ts b/tests/k6/src/lib/playbook/index.ts new file mode 100644 index 000000000..3d7e48162 --- /dev/null +++ b/tests/k6/src/lib/playbook/index.ts @@ -0,0 +1 @@ +export * as dav from './dav' \ No newline at end of file diff --git a/tests/k6/src/lib/types.ts b/tests/k6/src/lib/types.ts index 0a7783824..76567b290 100644 --- a/tests/k6/src/lib/types.ts +++ b/tests/k6/src/lib/types.ts @@ -1,3 +1,17 @@ +import {bytes} from "k6"; + +export interface Asset { + bytes: bytes; + fileName: string; +} + +export interface Token { + accessToken: string; + tokenType: string; + idToken: string; + expiresIn: string; +} + export interface Account { login: string password: string diff --git a/tests/k6/src/lib/utils.ts b/tests/k6/src/lib/utils.ts index 00dc81e94..54f9dcb35 100644 --- a/tests/k6/src/lib/utils.ts +++ b/tests/k6/src/lib/utils.ts @@ -1,3 +1,8 @@ export const randomString = (): string => { return Math.random().toString(36).slice(2) -} \ No newline at end of file +} + +export const extension = (p: string): string | undefined => { + return (p.split('/').pop())!.split('.').pop() +} + diff --git a/tests/k6/src/test-issue-162.ts b/tests/k6/src/test-issue-162.ts deleted file mode 100644 index c09f1c1ce..000000000 --- a/tests/k6/src/test-issue-162.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {sleep, check} from 'k6'; -import {Options} from "k6/options"; -import {defaults, api} from "./lib"; - -const files = { - 'kb_50.jpg': open('./_files/kb_50.jpg', 'b'), -} - -export let options: Options = { - insecureSkipTLSVerify: true, - iterations: 100, - vus: 100, -}; - -export default () => { - const res = api.uploadFile( - defaults.accounts.einstein, - files['kb_50.jpg'], - `kb_50-${__VU}-${__ITER}.jpg`, - ); - - check(res, { - 'status is 204': () => res.status === 204, - }); - - sleep(1); -}; \ No newline at end of file diff --git a/tests/k6/src/test/benchmark/file-download.ts b/tests/k6/src/test/benchmark/file-download.ts new file mode 100644 index 000000000..1506516dd --- /dev/null +++ b/tests/k6/src/test/benchmark/file-download.ts @@ -0,0 +1,53 @@ +import {defaults, playbook} from '../../lib' +import {Options} from 'k6/options'; +import {sleep} from "k6"; +import * as auth from "../../lib/auth"; +import * as types from "../../lib/types"; + +interface dataI { + credential: types.Account | types.Token; +} + +export const options: Options = { + ...defaults.k6OptionsDefault, + iterations: 1, + vus: 1, +}; +const account = defaults.knownAccounts.einstein; +const playbooks = { + fileUpload: playbook.dav.fileUpload(), + fileDownload: playbook.dav.fileDownload(), + fileDelete: playbook.dav.fileDelete(), +} +export const setup = (): dataI => { + return { + credential: defaults.OC_OIDC ? auth.oidc(account) : account, + } +} +export default (data: dataI) => { + const credential = data.credential; + const userName = account.login; + const fileName = playbooks.fileUpload({ + credential, + userName, + asset: defaults.OC_TEST_FILE + }); + + sleep(1) + + playbooks.fileDownload({ + credential, + userName, + fileName, + }); + + sleep(1) + + playbooks.fileDelete({ + credential, + userName, + fileName, + }); + + sleep(1) +}; \ No newline at end of file diff --git a/tests/k6/src/test/benchmark/file-upload.ts b/tests/k6/src/test/benchmark/file-upload.ts new file mode 100644 index 000000000..23fa5f9d3 --- /dev/null +++ b/tests/k6/src/test/benchmark/file-upload.ts @@ -0,0 +1,44 @@ +import {defaults, playbook} from '../../lib' +import {Options} from 'k6/options'; +import {sleep} from "k6"; +import * as auth from "../../lib/auth"; +import * as types from "../../lib/types"; + +interface dataI { + credential: types.Account | types.Token; +} + +export const options: Options = { + ...defaults.k6OptionsDefault, + iterations: 1, + vus: 1, +}; +const account = defaults.knownAccounts.einstein; +const playbooks = { + fileUpload: playbook.dav.fileUpload(), + fileDelete: playbook.dav.fileDelete(), +} +export const setup = (): dataI => { + return { + credential: defaults.OC_OIDC ? auth.oidc(account) : account, + } +} +export default (data: dataI) => { + const credential = data.credential; + const userName = account.login; + const fileName = playbooks.fileUpload({ + credential, + userName, + asset: defaults.OC_TEST_FILE + }); + + sleep(1) + + playbooks.fileDelete({ + credential, + userName, + fileName, + }); + + sleep(1) +}; \ No newline at end of file diff --git a/tests/k6/src/test/issue/github/ocis/162.ts b/tests/k6/src/test/issue/github/ocis/162.ts new file mode 100644 index 000000000..ec574f947 --- /dev/null +++ b/tests/k6/src/test/issue/github/ocis/162.ts @@ -0,0 +1,10 @@ +import {Options} from 'k6/options'; +import * as uploadFilesBenchmark from '../../../benchmark/file-upload' + +export const options: Options = { + ...uploadFilesBenchmark.options, + iterations: 200, + vus: 50, +}; +export const {setup} = uploadFilesBenchmark; +export default uploadFilesBenchmark.default; \ No newline at end of file diff --git a/tests/k6/yarn.lock b/tests/k6/yarn.lock index a58223d9f..1197148b1 100644 --- a/tests/k6/yarn.lock +++ b/tests/k6/yarn.lock @@ -4850,6 +4850,15 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +query-string@^6.13.7: + version "6.13.7" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.7.tgz#af53802ff6ed56f3345f92d40a056f93681026ee" + integrity sha512-CsGs8ZYb39zu0WLkeOhe0NMePqgYdAuCqxOYKDR5LVCytDZYMGx3Bb+xypvQvPHVPijRXB0HZNFllCzHRe4gEA== + dependencies: + decode-uri-component "^0.2.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + quick-lru@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" @@ -5528,6 +5537,11 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -5582,6 +5596,11 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= + string-argv@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" From 1558b2a4729288ba49cf7b159966e9dc7b69b23e Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Sun, 29 Nov 2020 22:21:40 +0100 Subject: [PATCH 02/27] ability to set username and password from env rename OC_OCIS_HOST to OC_HOST to make it more clear that the oc10 api is backward compatible --- tests/k6/src/lib/api/dav.ts | 6 +++--- tests/k6/src/lib/api/users.ts | 2 +- tests/k6/src/lib/defaults.ts | 6 ++++-- tests/k6/src/lib/utils.ts | 14 ++++++++++++++ tests/k6/src/test/benchmark/file-download.ts | 3 ++- tests/k6/src/test/benchmark/file-upload.ts | 3 ++- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/tests/k6/src/lib/api/dav.ts b/tests/k6/src/lib/api/dav.ts index 77d03e8c9..1d0b58b52 100644 --- a/tests/k6/src/lib/api/dav.ts +++ b/tests/k6/src/lib/api/dav.ts @@ -7,7 +7,7 @@ export const fileUpload = ( {credential, userName, asset}: { credential: types.Account | types.Token; userName: string; asset: types.Asset } ): RefinedResponse => { return http.put( - `${defaults.OC_OCIS_HOST}/remote.php/dav/files/${userName}/${asset.fileName}`, + `${defaults.OC_HOST}/remote.php/dav/files/${userName}/${asset.fileName}`, asset.bytes as any, { headers: { @@ -21,7 +21,7 @@ export const fileDownload = ( {credential, userName, fileName}: { credential: types.Account | types.Token; userName: string; fileName: string } ): RefinedResponse => { return http.get( - `${defaults.OC_OCIS_HOST}/remote.php/dav/files/${userName}/${fileName}`, + `${defaults.OC_HOST}/remote.php/dav/files/${userName}/${fileName}`, { headers: { ...api.headersDefault({credential}) @@ -34,7 +34,7 @@ export const fileDelete = ( {credential, userName, fileName}: { credential: types.Account | types.Token; userName: string; fileName: string } ): RefinedResponse => { return http.del( - `${defaults.OC_OCIS_HOST}/remote.php/dav/files/${userName}/${fileName}`, + `${defaults.OC_HOST}/remote.php/dav/files/${userName}/${fileName}`, {}, { headers: { diff --git a/tests/k6/src/lib/api/users.ts b/tests/k6/src/lib/api/users.ts index c15e36a51..b6dd38df0 100644 --- a/tests/k6/src/lib/api/users.ts +++ b/tests/k6/src/lib/api/users.ts @@ -7,7 +7,7 @@ export const userInfo = ( {credential, userName}: { credential: types.Account | types.Token; userName: string; } ): RefinedResponse => { return http.get( - `${defaults.OC_OCIS_HOST}/ocs/v1.php/cloud/users/${userName}`, + `${defaults.OC_HOST}/ocs/v1.php/cloud/users/${userName}`, { headers: { ...api.headersDefault({credential}) diff --git a/tests/k6/src/lib/defaults.ts b/tests/k6/src/lib/defaults.ts index 04746a834..094456a43 100644 --- a/tests/k6/src/lib/defaults.ts +++ b/tests/k6/src/lib/defaults.ts @@ -2,8 +2,10 @@ import * as types from './types'; import {Options} from "k6/options"; const ocTestFile = '../_files/' + (__ENV.OC_TEST_FILE || 'kb_50.jpg').split('/').pop() -export const OC_OCIS_HOST = __ENV.OC_OCIS_HOST || 'https://localhost:9200' -export const OC_OIDC_HOST = __ENV.OC_OIDC_HOST || OC_OCIS_HOST +export const OC_HOST = __ENV.OC_HOST || 'https://localhost:9200' +export const OC_LOGIN = __ENV.OC_LOGIN +export const OC_PASSWORD = __ENV.OC_PASSWORD +export const OC_OIDC_HOST = __ENV.OC_OIDC_HOST || OC_HOST export const OC_OIDC = __ENV.OC_OIDC === 'true' || false export const OC_TEST_FILE = { fileName: ocTestFile, diff --git a/tests/k6/src/lib/utils.ts b/tests/k6/src/lib/utils.ts index 54f9dcb35..36da0281d 100644 --- a/tests/k6/src/lib/utils.ts +++ b/tests/k6/src/lib/utils.ts @@ -1,3 +1,6 @@ +import * as types from "./types"; +import * as defaults from "./defaults"; + export const randomString = (): string => { return Math.random().toString(36).slice(2) } @@ -6,3 +9,14 @@ export const extension = (p: string): string | undefined => { return (p.split('/').pop())!.split('.').pop() } +export const getAccount = (key: string): types.Account => { + if (defaults.OC_LOGIN && defaults.OC_PASSWORD) { + return { + login: defaults.OC_LOGIN, + password: defaults.OC_PASSWORD, + } + } + + return defaults.knownAccounts[key]; +} + diff --git a/tests/k6/src/test/benchmark/file-download.ts b/tests/k6/src/test/benchmark/file-download.ts index 1506516dd..21ef37de7 100644 --- a/tests/k6/src/test/benchmark/file-download.ts +++ b/tests/k6/src/test/benchmark/file-download.ts @@ -3,6 +3,7 @@ import {Options} from 'k6/options'; import {sleep} from "k6"; import * as auth from "../../lib/auth"; import * as types from "../../lib/types"; +import * as utils from "../../lib/utils"; interface dataI { credential: types.Account | types.Token; @@ -13,7 +14,7 @@ export const options: Options = { iterations: 1, vus: 1, }; -const account = defaults.knownAccounts.einstein; +const account = utils.getAccount('einstein'); const playbooks = { fileUpload: playbook.dav.fileUpload(), fileDownload: playbook.dav.fileDownload(), diff --git a/tests/k6/src/test/benchmark/file-upload.ts b/tests/k6/src/test/benchmark/file-upload.ts index 23fa5f9d3..062c14c95 100644 --- a/tests/k6/src/test/benchmark/file-upload.ts +++ b/tests/k6/src/test/benchmark/file-upload.ts @@ -3,6 +3,7 @@ import {Options} from 'k6/options'; import {sleep} from "k6"; import * as auth from "../../lib/auth"; import * as types from "../../lib/types"; +import * as utils from "../../lib/utils"; interface dataI { credential: types.Account | types.Token; @@ -13,7 +14,7 @@ export const options: Options = { iterations: 1, vus: 1, }; -const account = defaults.knownAccounts.einstein; +const account = utils.getAccount('einstein'); const playbooks = { fileUpload: playbook.dav.fileUpload(), fileDelete: playbook.dav.fileDelete(), From 599b2a6c29895b71b393146d0d01dcaaea9a852b Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Mon, 30 Nov 2020 02:33:48 +0100 Subject: [PATCH 03/27] add auth provider factory add oidc cache and respect token lifetime simplify account retrieval --- tests/k6/src/lib/api/api.ts | 2 +- tests/k6/src/lib/api/dav.ts | 6 +- tests/k6/src/lib/api/users.ts | 2 +- tests/k6/src/lib/auth.ts | 208 +++++++++++++------ tests/k6/src/lib/defaults.ts | 38 +++- tests/k6/src/lib/playbook/dav.ts | 6 +- tests/k6/src/lib/types.ts | 8 +- tests/k6/src/lib/utils.ts | 14 -- tests/k6/src/test/benchmark/file-download.ts | 29 +-- tests/k6/src/test/benchmark/file-upload.ts | 26 +-- tests/k6/src/test/issue/github/ocis/162.ts | 1 - 11 files changed, 200 insertions(+), 140 deletions(-) diff --git a/tests/k6/src/lib/api/api.ts b/tests/k6/src/lib/api/api.ts index 8b9f3e344..b6bf237b6 100644 --- a/tests/k6/src/lib/api/api.ts +++ b/tests/k6/src/lib/api/api.ts @@ -1,7 +1,7 @@ import encoding from 'k6/encoding'; import * as types from "../types"; -export const headersDefault = ({credential}: { credential: types.Account | types.Token }): { [key: string]: string } => { +export const headersDefault = ({credential}: { credential: types.Credential }): { [key: string]: string } => { const isOIDCGuard = (credential as types.Token).tokenType !== undefined; const authOIDC = credential as types.Token; const authBasic = credential as types.Account; diff --git a/tests/k6/src/lib/api/dav.ts b/tests/k6/src/lib/api/dav.ts index 1d0b58b52..2d7407cff 100644 --- a/tests/k6/src/lib/api/dav.ts +++ b/tests/k6/src/lib/api/dav.ts @@ -4,7 +4,7 @@ import * as defaults from "../defaults"; import * as types from "../types"; export const fileUpload = ( - {credential, userName, asset}: { credential: types.Account | types.Token; userName: string; asset: types.Asset } + {credential, userName, asset}: { credential: types.Credential; userName: string; asset: types.Asset } ): RefinedResponse => { return http.put( `${defaults.OC_HOST}/remote.php/dav/files/${userName}/${asset.fileName}`, @@ -18,7 +18,7 @@ export const fileUpload = ( } export const fileDownload = ( - {credential, userName, fileName}: { credential: types.Account | types.Token; userName: string; fileName: string } + {credential, userName, fileName}: { credential: types.Credential; userName: string; fileName: string } ): RefinedResponse => { return http.get( `${defaults.OC_HOST}/remote.php/dav/files/${userName}/${fileName}`, @@ -31,7 +31,7 @@ export const fileDownload = ( } export const fileDelete = ( - {credential, userName, fileName}: { credential: types.Account | types.Token; userName: string; fileName: string } + {credential, userName, fileName}: { credential: types.Credential; userName: string; fileName: string } ): RefinedResponse => { return http.del( `${defaults.OC_HOST}/remote.php/dav/files/${userName}/${fileName}`, diff --git a/tests/k6/src/lib/api/users.ts b/tests/k6/src/lib/api/users.ts index b6dd38df0..84f3a7e8e 100644 --- a/tests/k6/src/lib/api/users.ts +++ b/tests/k6/src/lib/api/users.ts @@ -4,7 +4,7 @@ import * as defaults from "../defaults"; import * as types from "../types"; export const userInfo = ( - {credential, userName}: { credential: types.Account | types.Token; userName: string; } + {credential, userName}: { credential: types.Credential; userName: string; } ): RefinedResponse => { return http.get( `${defaults.OC_HOST}/ocs/v1.php/cloud/users/${userName}`, diff --git a/tests/k6/src/lib/auth.ts b/tests/k6/src/lib/auth.ts index 73e784bf7..13dc3602f 100644 --- a/tests/k6/src/lib/auth.ts +++ b/tests/k6/src/lib/auth.ts @@ -5,83 +5,159 @@ import * as types from "./types"; import {fail} from 'k6'; import {get} from 'lodash' -export const oidc = (account: types.Account): types.Token => { - const redirectUri = `${defaults.OC_OIDC_HOST}/oidc-callback.html`; - const logonUri = `${defaults.OC_OIDC_HOST}/signin/v1/identifier/_/logon`; - const logonResponse = http.post( - logonUri, - JSON.stringify( - { - params: [account.login, account.password, '1'], - hello: { - scope: 'openid profile email', - client_id: 'phoenix', - redirect_uri: redirectUri, - flow: 'oidc' - }, - 'state': 'vp42cf' - }, - ), - { - headers: { - 'Kopano-Konnect-XSRF': '1', - Referer: defaults.OC_OIDC_HOST, - 'Content-Type': 'application/json', - }, - }, - ); - const authorizeURI = get(logonResponse.json(), 'hello.continue_uri'); +export default class Factory { + private provider!: types.AuthProvider; + public account!: types.Account; - if (logonResponse.status != 200 || !authorizeURI) { - fail(logonUri); + constructor(account: types.Account) { + this.account = account; + + if (defaults.OC_OIDC) { + this.provider = new OIDCProvider(account); + } + + if (!defaults.OC_OIDC) { + this.provider = new AccountProvider(account); + } } - const authorizeUri = `${authorizeURI}?${ - queryString.stringify( + public get credential(): types.Credential { + return this.provider.credential + } +} + +class AccountProvider implements types.AuthProvider { + private account: types.Account; + + constructor(account: types.Account) { + this.account = account; + } + + public get credential(): types.Account { + return this.account; + } +} + +class OIDCProvider implements types.AuthProvider { + private account: types.Account; + private redirectUri = `${defaults.OC_OIDC_HOST}/oidc-callback.html`; + private logonUri = `${defaults.OC_OIDC_HOST}/signin/v1/identifier/_/logon`; + private tokenUrl = `${defaults.OC_OIDC_HOST}/konnect/v1/token`; + private cache!: { + validTo: Date; + token: types.Token; + } + + constructor(account: types.Account) { + this.account = account; + } + + public get credential(): types.Token { + if (!this.cache || this.cache.validTo <= new Date()) { + const continueURI = this.getContinueURI(); + const code = this.getCode(continueURI); + const token = this.getToken(code); + + this.cache = { + validTo: ((): Date => { + const offset = 5; + const d = new Date(); + + d.setSeconds(d.getSeconds() + token.expiresIn - offset) + + return d + })(), + token, + } + } + + return this.cache.token; + } + + private getContinueURI(): string { + const logonResponse = http.post( + this.logonUri, + JSON.stringify( + { + params: [this.account.login, this.account.password, '1'], + hello: { + scope: 'openid profile email', + client_id: 'phoenix', + redirect_uri: this.redirectUri, + flow: 'oidc' + }, + 'state': 'vp42cf' + }, + ), { - client_id: 'phoenix', - prompt: 'none', - redirect_uri: redirectUri, - response_mode: 'query', - response_type: 'code', - scope: 'openid profile email', + headers: { + 'Kopano-Konnect-XSRF': '1', + Referer: defaults.OC_OIDC_HOST, + 'Content-Type': 'application/json', + }, + }, + ); + const continueURI = get(logonResponse.json(), 'hello.continue_uri'); + + if (logonResponse.status != 200 || !continueURI) { + fail(this.logonUri); + } + + return continueURI; + } + + private getCode(continueURI: string): string { + const authorizeUri = `${continueURI}?${ + queryString.stringify( + { + client_id: 'phoenix', + prompt: 'none', + redirect_uri: this.redirectUri, + response_mode: 'query', + response_type: 'code', + scope: 'openid profile email', + }, + ) + }`; + const authorizeResponse = http.get( + authorizeUri, + { + redirects: 0, }, ) - }`; - const authorizeResponse = http.get( - authorizeUri, - { - redirects: 0, - }, - ) - const authCode = get(queryString.parseUrl(authorizeResponse.headers.Location), 'query.code') - if (authorizeResponse.status != 302 || !authCode) { - fail(authorizeURI); - } + const code = get(queryString.parseUrl(authorizeResponse.headers.Location), 'query.code') - const tokenUrl = `${defaults.OC_OIDC_HOST}/konnect/v1/token`; - const tokenResponse = http.post( - tokenUrl, - { - client_id: 'phoenix', - code: authCode, - redirect_uri: redirectUri, - grant_type: 'authorization_code' + if (authorizeResponse.status != 302 || !code) { + fail(continueURI); } - ) - const token = { - accessToken: get(tokenResponse.json(), 'access_token'), - tokenType: get(tokenResponse.json(), 'token_type'), - idToken: get(tokenResponse.json(), 'id_token'), - expiresIn: get(tokenResponse.json(), 'expires_in'), + return code } - if (tokenResponse.status != 200 || !token.accessToken || !token.tokenType || !token.idToken || !token.expiresIn) { - fail(authorizeURI); - } + private getToken(code: string): types.Token { + const tokenResponse = http.post( + this.tokenUrl, + { + client_id: 'phoenix', + code, + redirect_uri: this.redirectUri, + grant_type: 'authorization_code' + } + ) - return token -} \ No newline at end of file + const token = { + accessToken: get(tokenResponse.json(), 'access_token'), + tokenType: get(tokenResponse.json(), 'token_type'), + idToken: get(tokenResponse.json(), 'id_token'), + expiresIn: get(tokenResponse.json(), 'expires_in'), + } + + if (tokenResponse.status != 200 || !token.accessToken || !token.tokenType || !token.idToken || !token.expiresIn) { + fail(this.tokenUrl); + } + + return token; + } +} diff --git a/tests/k6/src/lib/defaults.ts b/tests/k6/src/lib/defaults.ts index 094456a43..3798b1dcf 100644 --- a/tests/k6/src/lib/defaults.ts +++ b/tests/k6/src/lib/defaults.ts @@ -11,16 +11,32 @@ export const OC_TEST_FILE = { fileName: ocTestFile, bytes: open(ocTestFile, 'b'), } -export const k6OptionsDefault: Options = { +export const K6_OPTION_DEFAULTS: Options = { insecureSkipTLSVerify: true, }; -export const knownAccounts: { [key: string]: types.Account; } = { - einstein: { - login: 'einstein', - password: 'relativity', - }, - richard: { - login: 'richard', - password: 'superfluidity', - }, -} \ No newline at end of file + +export class ACCOUNTS { + public static readonly EINSTEIN = 'einstein'; + public static readonly RICHARD = 'richard'; + private static readonly list: { [key: string]: types.Account; } = { + einstein: { + login: 'einstein', + password: 'relativity', + }, + richard: { + login: 'richard', + password: 'superfluidity', + }, + } + + public static for(key: string): types.Account { + if (OC_LOGIN && OC_PASSWORD) { + return { + login: OC_LOGIN, + password: OC_PASSWORD, + } + } + + return this.list[key]; + } +} diff --git a/tests/k6/src/lib/playbook/dav.ts b/tests/k6/src/lib/playbook/dav.ts index 089710847..36c677541 100644 --- a/tests/k6/src/lib/playbook/dav.ts +++ b/tests/k6/src/lib/playbook/dav.ts @@ -8,7 +8,7 @@ export const fileUpload = () => { const fileUploadTrend = new Trend('occ_file_upload_trend', true); const fileUploadErrorRate = new Gauge('occ_file_upload_error_rate'); - return ({credential, userName, asset}: { credential: types.Account | types.Token; userName: string; asset: types.Asset }): string => { + return ({credential, userName, asset}: { credential: types.Credential; userName: string; asset: types.Asset }): string => { const fileName = `upload-${userName}-${__VU}-${__ITER}.${utils.extension(asset.fileName)}`; const uploadResponse = api.dav.fileUpload({ credential: credential as any, @@ -33,7 +33,7 @@ export const fileDelete = () => { const fileDeleteTrend = new Trend('occ_file_delete_trend', true); const fileDeleteErrorRate = new Gauge('occ_file_delete_error_rate'); - return ({credential, userName, fileName}: { credential: types.Account | types.Token, userName: string; fileName: string }) => { + return ({credential, userName, fileName}: { credential: types.Credential, userName: string; fileName: string }) => { const deleteResponse = api.dav.fileDelete({ credential: credential as any, fileName, @@ -52,7 +52,7 @@ export const fileDownload = () => { const fileDownloadTrend = new Trend('occ_file_download_trend', true); const fileDownloadErrorRate = new Gauge('occ_file_download_error_rate'); - return ({credential, userName, fileName}: { credential: types.Account | types.Token, userName: string; fileName: string }): bytes => { + return ({credential, userName, fileName}: { credential: types.Credential, userName: string; fileName: string }): bytes => { const downloadResponse = api.dav.fileDownload({ credential: credential as any, fileName, diff --git a/tests/k6/src/lib/types.ts b/tests/k6/src/lib/types.ts index 76567b290..159be1087 100644 --- a/tests/k6/src/lib/types.ts +++ b/tests/k6/src/lib/types.ts @@ -9,10 +9,16 @@ export interface Token { accessToken: string; tokenType: string; idToken: string; - expiresIn: string; + expiresIn: number; } export interface Account { login: string password: string +} + +export type Credential = Token | Account + +export interface AuthProvider { + credential: Credential } \ No newline at end of file diff --git a/tests/k6/src/lib/utils.ts b/tests/k6/src/lib/utils.ts index 36da0281d..54f9dcb35 100644 --- a/tests/k6/src/lib/utils.ts +++ b/tests/k6/src/lib/utils.ts @@ -1,6 +1,3 @@ -import * as types from "./types"; -import * as defaults from "./defaults"; - export const randomString = (): string => { return Math.random().toString(36).slice(2) } @@ -9,14 +6,3 @@ export const extension = (p: string): string | undefined => { return (p.split('/').pop())!.split('.').pop() } -export const getAccount = (key: string): types.Account => { - if (defaults.OC_LOGIN && defaults.OC_PASSWORD) { - return { - login: defaults.OC_LOGIN, - password: defaults.OC_PASSWORD, - } - } - - return defaults.knownAccounts[key]; -} - diff --git a/tests/k6/src/test/benchmark/file-download.ts b/tests/k6/src/test/benchmark/file-download.ts index 21ef37de7..0e8ff5f23 100644 --- a/tests/k6/src/test/benchmark/file-download.ts +++ b/tests/k6/src/test/benchmark/file-download.ts @@ -1,35 +1,24 @@ import {defaults, playbook} from '../../lib' import {Options} from 'k6/options'; import {sleep} from "k6"; -import * as auth from "../../lib/auth"; -import * as types from "../../lib/types"; -import * as utils from "../../lib/utils"; - -interface dataI { - credential: types.Account | types.Token; -} +import auth from "../../lib/auth"; export const options: Options = { - ...defaults.k6OptionsDefault, + ...defaults.K6_OPTION_DEFAULTS, iterations: 1, vus: 1, }; -const account = utils.getAccount('einstein'); +const authFactory = new auth(defaults.ACCOUNTS.for(defaults.ACCOUNTS.EINSTEIN)); const playbooks = { fileUpload: playbook.dav.fileUpload(), fileDownload: playbook.dav.fileDownload(), fileDelete: playbook.dav.fileDelete(), } -export const setup = (): dataI => { - return { - credential: defaults.OC_OIDC ? auth.oidc(account) : account, - } -} -export default (data: dataI) => { - const credential = data.credential; - const userName = account.login; + +export default () => { + const {login: userName} = authFactory.account; const fileName = playbooks.fileUpload({ - credential, + credential: authFactory.credential, userName, asset: defaults.OC_TEST_FILE }); @@ -37,7 +26,7 @@ export default (data: dataI) => { sleep(1) playbooks.fileDownload({ - credential, + credential: authFactory.credential, userName, fileName, }); @@ -45,7 +34,7 @@ export default (data: dataI) => { sleep(1) playbooks.fileDelete({ - credential, + credential: authFactory.credential, userName, fileName, }); diff --git a/tests/k6/src/test/benchmark/file-upload.ts b/tests/k6/src/test/benchmark/file-upload.ts index 062c14c95..0d068e951 100644 --- a/tests/k6/src/test/benchmark/file-upload.ts +++ b/tests/k6/src/test/benchmark/file-upload.ts @@ -1,34 +1,22 @@ import {defaults, playbook} from '../../lib' import {Options} from 'k6/options'; import {sleep} from "k6"; -import * as auth from "../../lib/auth"; -import * as types from "../../lib/types"; -import * as utils from "../../lib/utils"; - -interface dataI { - credential: types.Account | types.Token; -} +import auth from "../../lib/auth"; export const options: Options = { - ...defaults.k6OptionsDefault, + ...defaults.K6_OPTION_DEFAULTS, iterations: 1, vus: 1, }; -const account = utils.getAccount('einstein'); +const authFactory = new auth(defaults.ACCOUNTS.for(defaults.ACCOUNTS.EINSTEIN)); const playbooks = { fileUpload: playbook.dav.fileUpload(), fileDelete: playbook.dav.fileDelete(), } -export const setup = (): dataI => { - return { - credential: defaults.OC_OIDC ? auth.oidc(account) : account, - } -} -export default (data: dataI) => { - const credential = data.credential; - const userName = account.login; +export default () => { + const {login: userName} = authFactory.account; const fileName = playbooks.fileUpload({ - credential, + credential: authFactory.credential, userName, asset: defaults.OC_TEST_FILE }); @@ -36,7 +24,7 @@ export default (data: dataI) => { sleep(1) playbooks.fileDelete({ - credential, + credential: authFactory.credential, userName, fileName, }); diff --git a/tests/k6/src/test/issue/github/ocis/162.ts b/tests/k6/src/test/issue/github/ocis/162.ts index ec574f947..144535de8 100644 --- a/tests/k6/src/test/issue/github/ocis/162.ts +++ b/tests/k6/src/test/issue/github/ocis/162.ts @@ -6,5 +6,4 @@ export const options: Options = { iterations: 200, vus: 50, }; -export const {setup} = uploadFilesBenchmark; export default uploadFilesBenchmark.default; \ No newline at end of file From 1d2447f7ea62cfc23a8c58868e2de80deaa0283b Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Mon, 30 Nov 2020 02:37:58 +0100 Subject: [PATCH 04/27] update README.md --- tests/k6/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/k6/README.md b/tests/k6/README.md index 60635ae7d..f11c98c67 100644 --- a/tests/k6/README.md +++ b/tests/k6/README.md @@ -16,7 +16,8 @@ k6 run ./dist/test/NAME_OF_TEST.js ## Environment variables ```console -$ OC_OCIS_HOST=URL k6 run ... +$ OC_LOGIN=USERNAME OC_PASSWORD=PASSWORD k6 run ... +$ OC_HOST=URL k6 run ... $ OC_OIDC_HOST=URL k6 run ... $ OC_OIDC=BOOL k6 run ... $ OC_TEST_FILE=STRING k6 run ... From c42a4c8ec3b9c36dec32dfb90524c227214b8817 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Mon, 30 Nov 2020 10:54:41 +0100 Subject: [PATCH 05/27] cleanup defaults update README.md --- tests/k6/README.md | 2 +- tests/k6/src/lib/api/dav.ts | 6 ++-- tests/k6/src/lib/api/users.ts | 2 +- tests/k6/src/lib/auth.ts | 15 ++++---- tests/k6/src/lib/defaults.ts | 38 ++++++++++++-------- tests/k6/src/test/benchmark/file-download.ts | 17 ++++----- tests/k6/src/test/benchmark/file-upload.ts | 14 ++++---- 7 files changed, 48 insertions(+), 46 deletions(-) diff --git a/tests/k6/README.md b/tests/k6/README.md index f11c98c67..d50c553d4 100644 --- a/tests/k6/README.md +++ b/tests/k6/README.md @@ -19,6 +19,6 @@ k6 run ./dist/test/NAME_OF_TEST.js $ OC_LOGIN=USERNAME OC_PASSWORD=PASSWORD k6 run ... $ OC_HOST=URL k6 run ... $ OC_OIDC_HOST=URL k6 run ... -$ OC_OIDC=BOOL k6 run ... +$ OC_OIDC_ENABLED=BOOL k6 run ... $ OC_TEST_FILE=STRING k6 run ... ``` \ No newline at end of file diff --git a/tests/k6/src/lib/api/dav.ts b/tests/k6/src/lib/api/dav.ts index 2d7407cff..bfac07300 100644 --- a/tests/k6/src/lib/api/dav.ts +++ b/tests/k6/src/lib/api/dav.ts @@ -7,7 +7,7 @@ export const fileUpload = ( {credential, userName, asset}: { credential: types.Credential; userName: string; asset: types.Asset } ): RefinedResponse => { return http.put( - `${defaults.OC_HOST}/remote.php/dav/files/${userName}/${asset.fileName}`, + `${defaults.ENV.HOST}/remote.php/dav/files/${userName}/${asset.fileName}`, asset.bytes as any, { headers: { @@ -21,7 +21,7 @@ export const fileDownload = ( {credential, userName, fileName}: { credential: types.Credential; userName: string; fileName: string } ): RefinedResponse => { return http.get( - `${defaults.OC_HOST}/remote.php/dav/files/${userName}/${fileName}`, + `${defaults.ENV.HOST}/remote.php/dav/files/${userName}/${fileName}`, { headers: { ...api.headersDefault({credential}) @@ -34,7 +34,7 @@ export const fileDelete = ( {credential, userName, fileName}: { credential: types.Credential; userName: string; fileName: string } ): RefinedResponse => { return http.del( - `${defaults.OC_HOST}/remote.php/dav/files/${userName}/${fileName}`, + `${defaults.ENV.HOST}/remote.php/dav/files/${userName}/${fileName}`, {}, { headers: { diff --git a/tests/k6/src/lib/api/users.ts b/tests/k6/src/lib/api/users.ts index 84f3a7e8e..5be51a7f3 100644 --- a/tests/k6/src/lib/api/users.ts +++ b/tests/k6/src/lib/api/users.ts @@ -7,7 +7,7 @@ export const userInfo = ( {credential, userName}: { credential: types.Credential; userName: string; } ): RefinedResponse => { return http.get( - `${defaults.OC_HOST}/ocs/v1.php/cloud/users/${userName}`, + `${defaults.ENV.HOST}/ocs/v1.php/cloud/users/${userName}`, { headers: { ...api.headersDefault({credential}) diff --git a/tests/k6/src/lib/auth.ts b/tests/k6/src/lib/auth.ts index 13dc3602f..760abab99 100644 --- a/tests/k6/src/lib/auth.ts +++ b/tests/k6/src/lib/auth.ts @@ -13,13 +13,12 @@ export default class Factory { constructor(account: types.Account) { this.account = account; - if (defaults.OC_OIDC) { + if (defaults.ENV.OIDC_ENABLED) { this.provider = new OIDCProvider(account); + return } - if (!defaults.OC_OIDC) { - this.provider = new AccountProvider(account); - } + this.provider = new AccountProvider(account); } public get credential(): types.Credential { @@ -41,9 +40,9 @@ class AccountProvider implements types.AuthProvider { class OIDCProvider implements types.AuthProvider { private account: types.Account; - private redirectUri = `${defaults.OC_OIDC_HOST}/oidc-callback.html`; - private logonUri = `${defaults.OC_OIDC_HOST}/signin/v1/identifier/_/logon`; - private tokenUrl = `${defaults.OC_OIDC_HOST}/konnect/v1/token`; + private redirectUri = `${defaults.ENV.OIDC_HOST}/oidc-callback.html`; + private logonUri = `${defaults.ENV.OIDC_HOST}/signin/v1/identifier/_/logon`; + private tokenUrl = `${defaults.ENV.OIDC_HOST}/konnect/v1/token`; private cache!: { validTo: Date; token: types.Token; @@ -93,7 +92,7 @@ class OIDCProvider implements types.AuthProvider { { headers: { 'Kopano-Konnect-XSRF': '1', - Referer: defaults.OC_OIDC_HOST, + Referer: defaults.ENV.OIDC_HOST, 'Content-Type': 'application/json', }, }, diff --git a/tests/k6/src/lib/defaults.ts b/tests/k6/src/lib/defaults.ts index 3798b1dcf..17e79611c 100644 --- a/tests/k6/src/lib/defaults.ts +++ b/tests/k6/src/lib/defaults.ts @@ -1,21 +1,29 @@ import * as types from './types'; import {Options} from "k6/options"; -const ocTestFile = '../_files/' + (__ENV.OC_TEST_FILE || 'kb_50.jpg').split('/').pop() -export const OC_HOST = __ENV.OC_HOST || 'https://localhost:9200' -export const OC_LOGIN = __ENV.OC_LOGIN -export const OC_PASSWORD = __ENV.OC_PASSWORD -export const OC_OIDC_HOST = __ENV.OC_OIDC_HOST || OC_HOST -export const OC_OIDC = __ENV.OC_OIDC === 'true' || false -export const OC_TEST_FILE = { - fileName: ocTestFile, - bytes: open(ocTestFile, 'b'), +export class K6 { + public static readonly OPTIONS: Options = { + insecureSkipTLSVerify: true, + iterations: 1, + vus: 1, + }; } -export const K6_OPTION_DEFAULTS: Options = { - insecureSkipTLSVerify: true, + +export class ENV { + public static readonly HOST = __ENV.OC_HOST || 'https://localhost:9200'; + public static readonly LOGIN = __ENV.OC_LOGIN; + public static readonly PASSWORD = __ENV.OC_PASSWORD; + public static readonly OIDC_HOST = __ENV.OC_OIDC_HOST || ENV.HOST; + public static readonly OIDC_ENABLED = __ENV.OC_OIDC_ENABLED === 'true' || false; + public static readonly FILE_NAME = '../_files/' + (__ENV.OC_TEST_FILE || 'kb_50.jpg').split('/').pop(); +} + +export const FILE = { + fileName: ENV.FILE_NAME, + bytes: open(ENV.FILE_NAME, 'b'), }; -export class ACCOUNTS { +export class ACCOUNT { public static readonly EINSTEIN = 'einstein'; public static readonly RICHARD = 'richard'; private static readonly list: { [key: string]: types.Account; } = { @@ -30,10 +38,10 @@ export class ACCOUNTS { } public static for(key: string): types.Account { - if (OC_LOGIN && OC_PASSWORD) { + if (ENV.LOGIN && ENV.PASSWORD) { return { - login: OC_LOGIN, - password: OC_PASSWORD, + login: ENV.LOGIN, + password: ENV.PASSWORD, } } diff --git a/tests/k6/src/test/benchmark/file-download.ts b/tests/k6/src/test/benchmark/file-download.ts index 0e8ff5f23..06ed8bfb8 100644 --- a/tests/k6/src/test/benchmark/file-download.ts +++ b/tests/k6/src/test/benchmark/file-download.ts @@ -4,28 +4,25 @@ import {sleep} from "k6"; import auth from "../../lib/auth"; export const options: Options = { - ...defaults.K6_OPTION_DEFAULTS, - iterations: 1, - vus: 1, + ...defaults.K6.OPTIONS, }; -const authFactory = new auth(defaults.ACCOUNTS.for(defaults.ACCOUNTS.EINSTEIN)); -const playbooks = { +const authFactory = new auth(defaults.ACCOUNT.for(defaults.ACCOUNT.EINSTEIN)); +const plays = { fileUpload: playbook.dav.fileUpload(), fileDownload: playbook.dav.fileDownload(), fileDelete: playbook.dav.fileDelete(), } - export default () => { const {login: userName} = authFactory.account; - const fileName = playbooks.fileUpload({ + const fileName = plays.fileUpload({ credential: authFactory.credential, userName, - asset: defaults.OC_TEST_FILE + asset: defaults.FILE, }); sleep(1) - playbooks.fileDownload({ + plays.fileDownload({ credential: authFactory.credential, userName, fileName, @@ -33,7 +30,7 @@ export default () => { sleep(1) - playbooks.fileDelete({ + plays.fileDelete({ credential: authFactory.credential, userName, fileName, diff --git a/tests/k6/src/test/benchmark/file-upload.ts b/tests/k6/src/test/benchmark/file-upload.ts index 0d068e951..2a7042174 100644 --- a/tests/k6/src/test/benchmark/file-upload.ts +++ b/tests/k6/src/test/benchmark/file-upload.ts @@ -4,26 +4,24 @@ import {sleep} from "k6"; import auth from "../../lib/auth"; export const options: Options = { - ...defaults.K6_OPTION_DEFAULTS, - iterations: 1, - vus: 1, + ...defaults.K6.OPTIONS, }; -const authFactory = new auth(defaults.ACCOUNTS.for(defaults.ACCOUNTS.EINSTEIN)); -const playbooks = { +const authFactory = new auth(defaults.ACCOUNT.for(defaults.ACCOUNT.EINSTEIN)); +const plays = { fileUpload: playbook.dav.fileUpload(), fileDelete: playbook.dav.fileDelete(), } export default () => { const {login: userName} = authFactory.account; - const fileName = playbooks.fileUpload({ + const fileName = plays.fileUpload({ credential: authFactory.credential, userName, - asset: defaults.OC_TEST_FILE + asset: defaults.FILE, }); sleep(1) - playbooks.fileDelete({ + plays.fileDelete({ credential: authFactory.credential, userName, fileName, From 938b2ea576ffc44bc01f7aae05fde4a40182b283 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Wed, 2 Dec 2020 04:02:57 +0100 Subject: [PATCH 06/27] add new tests add ability to generate binary files at runtime restructure package layout --- tests/k6/README.md | 3 +- tests/k6/package.json | 6 +- tests/k6/report/ocis-folder-listing-flat.json | 168 +++++++++ tests/k6/report/ocis-many-small.json | 224 ++++++++++++ tests/k6/report/ocis-some-large.json | 296 +++++++++++++++ tests/k6/rollup.config.js | 2 +- tests/k6/scripts/postinstall.js | 53 --- tests/k6/src/lib/api/api.ts | 2 +- tests/k6/src/lib/api/dav.ts | 135 ++++++- tests/k6/src/lib/api/users.ts | 21 +- tests/k6/src/lib/auth.ts | 8 +- tests/k6/src/lib/defaults.ts | 32 +- tests/k6/src/lib/playbook/dav.ts | 338 +++++++++++++++--- tests/k6/src/lib/types.ts | 8 +- tests/k6/src/lib/utils.ts | 55 ++- tests/k6/src/test/benchmark/file-download.ts | 40 --- tests/k6/src/test/benchmark/file-upload.ts | 31 -- tests/k6/src/test/issue/github/ocis/162.ts | 9 - .../jira/ocis/1007/folder-listing/flat.ts | 64 ++++ .../jira/ocis/1007/folder-listing/nested.ts | 81 +++++ .../1007/simple-down-and-upload/many-small.ts | 72 ++++ .../1007/simple-down-and-upload/some-large.ts | 75 ++++ tests/k6/yarn.lock | 80 +---- 23 files changed, 1473 insertions(+), 330 deletions(-) create mode 100644 tests/k6/report/ocis-folder-listing-flat.json create mode 100644 tests/k6/report/ocis-many-small.json create mode 100644 tests/k6/report/ocis-some-large.json delete mode 100644 tests/k6/scripts/postinstall.js delete mode 100644 tests/k6/src/test/benchmark/file-download.ts delete mode 100644 tests/k6/src/test/benchmark/file-upload.ts delete mode 100644 tests/k6/src/test/issue/github/ocis/162.ts create mode 100644 tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts create mode 100644 tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts create mode 100644 tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts create mode 100644 tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts diff --git a/tests/k6/README.md b/tests/k6/README.md index d50c553d4..9f5177065 100644 --- a/tests/k6/README.md +++ b/tests/k6/README.md @@ -11,7 +11,7 @@ $ yarn build ## How to run ```console -k6 run ./dist/test/NAME_OF_TEST.js +k6 run ./dist/NAME_OF_TEST.js ``` ## Environment variables @@ -20,5 +20,4 @@ $ OC_LOGIN=USERNAME OC_PASSWORD=PASSWORD k6 run ... $ OC_HOST=URL k6 run ... $ OC_OIDC_HOST=URL k6 run ... $ OC_OIDC_ENABLED=BOOL k6 run ... -$ OC_TEST_FILE=STRING k6 run ... ``` \ No newline at end of file diff --git a/tests/k6/package.json b/tests/k6/package.json index fd7836fa2..3dcacc9d7 100644 --- a/tests/k6/package.json +++ b/tests/k6/package.json @@ -5,8 +5,7 @@ "scripts": { "clean": "rm -rf ./dist", "build": "rollup -c", - "build:w": "rollup -c -w", - "postinstall": "node ./scripts/postinstall.js" + "build:w": "rollup -c -w" }, "devDependencies": { "@babel/core": "^7.9.0", @@ -25,7 +24,6 @@ "@types/lodash": "^4.14.165", "@typescript-eslint/eslint-plugin": "^2.29.0", "@typescript-eslint/parser": "^2.29.0", - "axios": "^0.21.0", "babel-plugin-lodash": "^3.3.4", "eslint": "^6.8.0", "eslint-config-prettier": "^6.11.0", @@ -34,13 +32,11 @@ "jest": "^25.4.0", "k6": "^0.0.0", "lint-staged": "^10.1.7", - "ora": "^5.1.0", "prettier": "^2.0.5", "rollup": "^2.7.2", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-multi-input": "^1.1.1", "rollup-plugin-terser": "^5.3.0", - "shelljs": "^0.8.4", "typescript": "^3.8.3" }, "dependencies": { diff --git a/tests/k6/report/ocis-folder-listing-flat.json b/tests/k6/report/ocis-folder-listing-flat.json new file mode 100644 index 000000000..c01cae720 --- /dev/null +++ b/tests/k6/report/ocis-folder-listing-flat.json @@ -0,0 +1,168 @@ +{ + "metrics": { + "checks": { + "fails": 0, + "passes": 6003, + "value": 0 + }, + "data_received": { + "count": 5232948, + "rate": 35275.75112278176 + }, + "data_sent": { + "count": 4637493, + "rate": 31261.737915538728 + }, + "http_req_blocked": { + "avg": 0.004372313843078474, + "max": 4.63, + "med": 0.003, + "min": 0.002, + "p(90)": 0.005, + "p(95)": 0.007 + }, + "http_req_connecting": { + "avg": 0.000056305180742961854, + "max": 0.338, + "med": 0, + "min": 0, + "p(90)": 0, + "p(95)": 0 + }, + "http_req_duration": { + "avg": 24.326444277861146, + "max": 493.144, + "med": 21.826, + "min": 10.256, + "p(90)": 38.041000000000004, + "p(95)": 43.9535 + }, + "http_req_receiving": { + "avg": 0.05978927203065133, + "max": 1.579, + "med": 0.05, + "min": 0.036, + "p(90)": 0.085, + "p(95)": 0.104 + }, + "http_req_sending": { + "avg": 0.03032550391470921, + "max": 0.223, + "med": 0.025, + "min": 0.018, + "p(90)": 0.043, + "p(95)": 0.056 + }, + "http_req_tls_handshaking": { + "avg": 0.0005380643011827419, + "max": 3.23, + "med": 0, + "min": 0, + "p(90)": 0, + "p(95)": 0 + }, + "http_req_waiting": { + "avg": 24.23632950191566, + "max": 492.043, + "med": 21.741, + "min": 10.192, + "p(90)": 37.92360000000001, + "p(95)": 43.8319 + }, + "http_reqs": { + "count": 6003, + "rate": 40.46673767636501 + }, + "iteration_duration": { + "avg": 49429.791962999996, + "max": 50603.792868, + "med": 49213.89341, + "min": 48471.689611, + "p(90)": 50325.8129764, + "p(95)": 50464.8029222 + }, + "iterations": { + "count": 3, + "rate": 0.020223257209577714 + }, + "oc_default_play_dav_file_delete_trend": { + "avg": 16.629310000000025, + "max": 75.491, + "med": 15.1365, + "min": 10.256, + "p(90)": 23.539, + "p(95)": 27.27049999999999 + }, + "oc_default_play_dav_file_delete_trend{asset:KB1": { + "avg": 16.629310000000025, + "max": 75.491, + "med": 15.1365, + "min": 10.256, + "p(90)": 23.539, + "p(95)": 27.27049999999999 + }, + "oc_default_play_dav_file_upload_trend": { + "avg": 31.677708999999993, + "max": 267.948, + "med": 29.3345, + "min": 19.082, + "p(90)": 43.212199999999996, + "p(95)": 50.722699999999996 + }, + "oc_default_play_dav_file_upload_trend{asset:KB1": { + "avg": 31.677708999999993, + "max": 267.948, + "med": 29.3345, + "min": 19.082, + "p(90)": 43.212199999999996, + "p(95)": 50.722699999999996 + }, + "oc_default_play_dav_propfind_trend": { + "avg": 370.19599999999997, + "max": 493.144, + "med": 310.431, + "min": 307.013, + "p(90)": 456.6014, + "p(95)": 474.8727 + }, + "vus": { + "max": 1, + "min": 1, + "value": 1 + }, + "vus_max": { + "max": 1, + "min": 1, + "value": 1 + } + }, + "root_group": { + "name": "", + "path": "", + "id": "d41d8cd98f00b204e9800998ecf8427e", + "groups": {}, + "checks": { + "file delete status is 204": { + "name": "file delete status is 204", + "path": "::file delete status is 204", + "id": "18e4ac556fd01961812afd85e16bb9d9", + "passes": 3000, + "fails": 0 + }, + "file upload status is 201": { + "name": "file upload status is 201", + "path": "::file upload status is 201", + "id": "d530d65df94c4e70b68aac6f2f054f1f", + "passes": 3000, + "fails": 0 + }, + "propfind status is 207": { + "name": "propfind status is 207", + "path": "::propfind status is 207", + "id": "6cbc0cbc7ef202f356106cf063105452", + "passes": 3, + "fails": 0 + } + } + } +} diff --git a/tests/k6/report/ocis-many-small.json b/tests/k6/report/ocis-many-small.json new file mode 100644 index 000000000..e274791c0 --- /dev/null +++ b/tests/k6/report/ocis-many-small.json @@ -0,0 +1,224 @@ +{ + "metrics": { + "checks": { + "fails": 0, + "passes": 1440, + "value": 0 + }, + "data_received": { + "count": 1729675379, + "rate": 33808868.65162363 + }, + "data_sent": { + "count": 1736098107, + "rate": 33934409.646178715 + }, + "http_req_blocked": { + "avg": 0.006793055555555532, + "max": 4.046, + "med": 0.003, + "min": 0.002, + "p(90)": 0.006, + "p(95)": 0.008 + }, + "http_req_connecting": { + "avg": 0.00018055555555555557, + "max": 0.26, + "med": 0, + "min": 0, + "p(90)": 0, + "p(95)": 0 + }, + "http_req_duration": { + "avg": 32.08864027777775, + "max": 253.272, + "med": 26.4905, + "min": 10.372, + "p(90)": 50.71580000000001, + "p(95)": 64.83449999999998 + }, + "http_req_receiving": { + "avg": 4.024194444444447, + "max": 128.777, + "med": 0.064, + "min": 0.037, + "p(90)": 14.537700000000015, + "p(95)": 19.81769999999999 + }, + "http_req_sending": { + "avg": 5.342373611111132, + "max": 132.051, + "med": 0.03, + "min": 0.017, + "p(90)": 22.215200000000003, + "p(95)": 30.02865 + }, + "http_req_tls_handshaking": { + "avg": 0.00218125, + "max": 3.141, + "med": 0, + "min": 0, + "p(90)": 0, + "p(95)": 0 + }, + "http_req_waiting": { + "avg": 22.72207222222226, + "max": 251.256, + "med": 21.123, + "min": 8.077, + "p(90)": 34.120799999999996, + "p(95)": 37.62935 + }, + "http_reqs": { + "count": 1440, + "rate": 28.146767566573555 + }, + "iteration_duration": { + "avg": 17041.291093666667, + "max": 17397.314603, + "med": 16968.823006, + "min": 16757.735672, + "p(90)": 17311.6162836, + "p(95)": 17354.4654433 + }, + "iterations": { + "count": 3, + "rate": 0.05863909909702824 + }, + "oc_default_play_dav_file_delete_trend": { + "avg": 15.769127083333343, + "max": 49.32, + "med": 14.7855, + "min": 10.372, + "p(90)": 21.6302, + "p(95)": 24.0062 + }, + "oc_default_play_dav_file_delete_trend{asset:KB500": { + "avg": 16.38810000000001, + "max": 49.32, + "med": 15.4255, + "min": 10.372, + "p(90)": 23.0987, + "p(95)": 24.657150000000005 + }, + "oc_default_play_dav_file_delete_trend{asset:MB25": { + "avg": 14.155766666666667, + "max": 19.967, + "med": 13.262, + "min": 10.793, + "p(90)": 18.776000000000003, + "p(95)": 19.580849999999998 + }, + "oc_default_play_dav_file_delete_trend{asset:MB5": { + "avg": 14.853853333333339, + "max": 26.691, + "med": 14.0415, + "min": 10.496, + "p(90)": 18.943699999999996, + "p(95)": 20.62044999999999 + }, + "oc_default_play_dav_file_download_trend": { + "avg": 37.784668749999994, + "max": 183.499, + "med": 32.0055, + "min": 19.14, + "p(90)": 55.628600000000006, + "p(95)": 93.45874999999992 + }, + "oc_default_play_dav_file_download_trend{asset:KB500": { + "avg": 26.680456666666657, + "max": 55.922, + "med": 24.979, + "min": 19.14, + "p(90)": 34.91720000000001, + "p(95)": 37.47365 + }, + "oc_default_play_dav_file_download_trend{asset:MB25": { + "avg": 113.08066666666669, + "max": 183.499, + "med": 103.05799999999999, + "min": 83.728, + "p(90)": 148.6112, + "p(95)": 162.21334999999996 + }, + "oc_default_play_dav_file_download_trend{asset:MB5": { + "avg": 44.93389333333334, + "max": 75.914, + "med": 43.920500000000004, + "min": 31.472, + "p(90)": 56.58899999999999, + "p(95)": 60.417399999999994 + }, + "oc_default_play_dav_file_upload_trend": { + "avg": 42.71212500000003, + "max": 253.272, + "med": 36.876999999999995, + "min": 21.145, + "p(90)": 56.78170000000001, + "p(95)": 114.79089999999997 + }, + "oc_default_play_dav_file_upload_trend{asset:KB500": { + "avg": 32.439143333333334, + "max": 253.272, + "med": 30.240000000000002, + "min": 21.145, + "p(90)": 40.75260000000001, + "p(95)": 45.08695000000001 + }, + "oc_default_play_dav_file_upload_trend{asset:MB25": { + "avg": 121.4088, + "max": 146.226, + "med": 119.23599999999999, + "min": 100.77, + "p(90)": 138.50189999999998, + "p(95)": 142.34375 + }, + "oc_default_play_dav_file_upload_trend{asset:MB5": { + "avg": 47.518753333333365, + "max": 77.615, + "med": 46.457, + "min": 35.46, + "p(90)": 56.623099999999994, + "p(95)": 61.826049999999974 + }, + "vus": { + "max": 1, + "min": 1, + "value": 1 + }, + "vus_max": { + "max": 1, + "min": 1, + "value": 1 + } + }, + "root_group": { + "name": "", + "path": "", + "id": "d41d8cd98f00b204e9800998ecf8427e", + "groups": {}, + "checks": { + "file delete status is 204": { + "name": "file delete status is 204", + "path": "::file delete status is 204", + "id": "18e4ac556fd01961812afd85e16bb9d9", + "passes": 480, + "fails": 0 + }, + "file download status is 200": { + "name": "file download status is 200", + "path": "::file download status is 200", + "id": "52b41fab3137d895e8ec58fd9dccd86e", + "passes": 480, + "fails": 0 + }, + "file upload status is 201": { + "name": "file upload status is 201", + "path": "::file upload status is 201", + "id": "d530d65df94c4e70b68aac6f2f054f1f", + "passes": 480, + "fails": 0 + } + } + } +} diff --git a/tests/k6/report/ocis-some-large.json b/tests/k6/report/ocis-some-large.json new file mode 100644 index 000000000..32eb31b6f --- /dev/null +++ b/tests/k6/report/ocis-some-large.json @@ -0,0 +1,296 @@ +{ + "metrics": { + "checks": { + "fails": 0, + "passes": 54, + "value": 0 + }, + "data_received": { + "count": 4975515490, + "rate": 54283776.21668842 + }, + "data_sent": { + "count": 4995495858, + "rate": 54501765.65465097 + }, + "http_req_blocked": { + "avg": 0.07648148148148148, + "max": 3.614, + "med": 0.005, + "min": 0.003, + "p(90)": 0.024, + "p(95)": 0.03684999999999994 + }, + "http_req_connecting": { + "avg": 0.004203703703703703, + "max": 0.227, + "med": 0, + "min": 0, + "p(90)": 0, + "p(95)": 0 + }, + "http_req_duration": { + "avg": 1199.7894444444446, + "max": 11778.61, + "med": 81.80799999999999, + "min": 17.916, + "p(90)": 4263.4364000000005, + "p(95)": 7307.079449999999 + }, + "http_req_receiving": { + "avg": 586.4966296296295, + "max": 7419.291, + "med": 0.13, + "min": 0.04, + "p(90)": 1447.7991000000025, + "p(95)": 5254.929599999983 + }, + "http_req_sending": { + "avg": 555.0930740740743, + "max": 11707.466, + "med": 0.0775, + "min": 0.018, + "p(90)": 1635.9796000000044, + "p(95)": 3495.4676999999942 + }, + "http_req_tls_handshaking": { + "avg": 0.052833333333333336, + "max": 2.853, + "med": 0, + "min": 0, + "p(90)": 0, + "p(95)": 0 + }, + "http_req_waiting": { + "avg": 58.199740740740744, + "max": 305.282, + "med": 37.3425, + "min": 14.057, + "p(90)": 105.61020000000003, + "p(95)": 155.87789999999998 + }, + "http_reqs": { + "count": 54, + "rate": 0.5891497919346593 + }, + "iteration_duration": { + "avg": 30521.018089, + "max": 42157.485685, + "med": 26262.18445, + "min": 23143.384132, + "p(90)": 38978.425438, + "p(95)": 40567.9555615 + }, + "iterations": { + "count": 3, + "rate": 0.03273054399636997 + }, + "oc_default_play_dav_file_delete_trend": { + "avg": 42.30277777777778, + "max": 91.667, + "med": 33.669, + "min": 17.916, + "p(90)": 73.0931, + "p(95)": 86.0162 + }, + "oc_default_play_dav_file_delete_trend{asset:GB1": { + "avg": 36.54533333333333, + "max": 45.724, + "med": 33.698, + "min": 30.214, + "p(90)": 43.318799999999996, + "p(95)": 44.5214 + }, + "oc_default_play_dav_file_delete_trend{asset:KB50": { + "avg": 58.788333333333334, + "max": 85.019, + "med": 62.125, + "min": 29.221, + "p(90)": 80.4402, + "p(95)": 82.7296 + }, + "oc_default_play_dav_file_delete_trend{asset:KB500": { + "avg": 41.721333333333334, + "max": 67.982, + "med": 32.438, + "min": 24.744, + "p(90)": 60.8732, + "p(95)": 64.4276 + }, + "oc_default_play_dav_file_delete_trend{asset:MB5": { + "avg": 30.743666666666666, + "max": 56.309, + "med": 18.006, + "min": 17.916, + "p(90)": 48.648399999999995, + "p(95)": 52.478699999999996 + }, + "oc_default_play_dav_file_delete_trend{asset:MB50": { + "avg": 45.24466666666667, + "max": 91.667, + "med": 22.681, + "min": 21.386, + "p(90)": 77.86980000000001, + "p(95)": 84.7684 + }, + "oc_default_play_dav_file_delete_trend{asset:MB500": { + "avg": 40.77333333333333, + "max": 45.129, + "med": 43.551, + "min": 33.64, + "p(90)": 44.8134, + "p(95)": 44.971199999999996 + }, + "oc_default_play_dav_file_download_trend": { + "avg": 1815.5790555555557, + "max": 7454.559, + "med": 190.0605, + "min": 27.771, + "p(90)": 7302.4101, + "p(95)": 7380.7977 + }, + "oc_default_play_dav_file_download_trend{asset:GB1": { + "avg": 7365.578, + "max": 7454.559, + "med": 7367.781, + "min": 7274.394, + "p(90)": 7437.2034, + "p(95)": 7445.8812 + }, + "oc_default_play_dav_file_download_trend{asset:KB50": { + "avg": 77.559, + "max": 144.171, + "med": 60.735, + "min": 27.771, + "p(90)": 127.4838, + "p(95)": 135.82739999999998 + }, + "oc_default_play_dav_file_download_trend{asset:KB500": { + "avg": 64.77866666666667, + "max": 118.418, + "med": 47.796, + "min": 28.122, + "p(90)": 104.29360000000001, + "p(95)": 111.35580000000002 + }, + "oc_default_play_dav_file_download_trend{asset:MB5": { + "avg": 87.07633333333332, + "max": 132.468, + "med": 64.708, + "min": 64.053, + "p(90)": 118.916, + "p(95)": 125.69199999999998 + }, + "oc_default_play_dav_file_download_trend{asset:MB50": { + "avg": 465.49199999999996, + "max": 920.853, + "med": 239.673, + "min": 235.95, + "p(90)": 784.617, + "p(95)": 852.7349999999999 + }, + "oc_default_play_dav_file_download_trend{asset:MB500": { + "avg": 2832.990333333333, + "max": 4296.326, + "med": 2461.95, + "min": 1740.695, + "p(90)": 3929.4508, + "p(95)": 4112.8884 + }, + "oc_default_play_dav_file_upload_trend": { + "avg": 1741.4865, + "max": 11778.61, + "med": 277.241, + "min": 22.627, + "p(90)": 4528.384400000001, + "p(95)": 6293.604199999991 + }, + "oc_default_play_dav_file_upload_trend{asset:GB1": { + "avg": 7096.988666666667, + "max": 11778.61, + "med": 5325.662, + "min": 4186.694, + "p(90)": 10488.020400000001, + "p(95)": 11133.315200000001 + }, + "oc_default_play_dav_file_upload_trend{asset:KB50": { + "avg": 126.274, + "max": 243.95, + "med": 90.139, + "min": 44.733, + "p(90)": 213.18779999999998, + "p(95)": 228.56889999999999 + }, + "oc_default_play_dav_file_upload_trend{asset:KB500": { + "avg": 136.278, + "max": 307.61, + "med": 78.597, + "min": 22.627, + "p(90)": 261.80740000000003, + "p(95)": 284.7087 + }, + "oc_default_play_dav_file_upload_trend{asset:MB5": { + "avg": 105.57533333333333, + "max": 201.903, + "med": 61.229, + "min": 53.594, + "p(90)": 173.76819999999998, + "p(95)": 187.83559999999997 + }, + "oc_default_play_dav_file_upload_trend{asset:MB50": { + "avg": 426.2540000000001, + "max": 598.362, + "med": 433.528, + "min": 246.872, + "p(90)": 565.3951999999999, + "p(95)": 581.8786 + }, + "oc_default_play_dav_file_upload_trend{asset:MB500": { + "avg": 2557.549, + "max": 3159.682, + "med": 2397.078, + "min": 2115.887, + "p(90)": 3007.1612, + "p(95)": 3083.4215999999997 + }, + "vus": { + "max": 1, + "min": 1, + "value": 1 + }, + "vus_max": { + "max": 1, + "min": 1, + "value": 1 + } + }, + "root_group": { + "name": "", + "path": "", + "id": "d41d8cd98f00b204e9800998ecf8427e", + "groups": {}, + "checks": { + "file delete status is 204": { + "name": "file delete status is 204", + "path": "::file delete status is 204", + "id": "18e4ac556fd01961812afd85e16bb9d9", + "passes": 18, + "fails": 0 + }, + "file download status is 200": { + "name": "file download status is 200", + "path": "::file download status is 200", + "id": "52b41fab3137d895e8ec58fd9dccd86e", + "passes": 18, + "fails": 0 + }, + "file upload status is 201": { + "name": "file upload status is 201", + "path": "::file upload status is 201", + "id": "d530d65df94c4e70b68aac6f2f054f1f", + "passes": 18, + "fails": 0 + } + } + } +} diff --git a/tests/k6/rollup.config.js b/tests/k6/rollup.config.js index bc87e1023..baed47a32 100644 --- a/tests/k6/rollup.config.js +++ b/tests/k6/rollup.config.js @@ -26,7 +26,7 @@ export default [ ], plugins: [ multiInput({ - transformOutputPath: (output, input) => `tests/${output.split('/').join('-')}`, + transformOutputPath: (output, input) => `${output.split('/').join('-')}`, }), json(), resolve( diff --git a/tests/k6/scripts/postinstall.js b/tests/k6/scripts/postinstall.js deleted file mode 100644 index bc574dffc..000000000 --- a/tests/k6/scripts/postinstall.js +++ /dev/null @@ -1,53 +0,0 @@ -const shell = require('shelljs') -const path = require("path") -const fs = require('fs'); -const ora = require('ora'); -const axios = require('axios'); - -const downloadFile = async (url, name) => { - const parsedPath = path.parse(url) - const destDir = './dist/_files/' - const destFile = path.join(destDir, name || parsedPath.base) - - if (!fs.existsSync(destDir)) { - shell.mkdir('-p', destDir) - } - - if(fs.existsSync(destFile)){ - return - } - - const spinner = ora(`downloading: ${ url }`).start(); - const { data } = await axios({ - method: "get", - url: url, - responseType: "stream" - }); - const stream = fs.createWriteStream(destFile); - - data.pipe(stream); - - return new Promise((resolve, reject) => { - data.on('error', err => { - console.error(err); - spinner.stop(); - reject(err); - }); - - data.on('end', () => { - stream.end(); - spinner.stop(); - resolve(); - }); - }); -} - -(async () => { - await downloadFile('https://www.sample-videos.com/img/Sample-jpg-image-50kb.jpg', 'kb_50.jpg') - await downloadFile('http://ipv4.download.thinkbroadband.com/5MB.zip', 'mb_5.zip') - await downloadFile('http://ipv4.download.thinkbroadband.com/10MB.zip', 'mb_10.zip') - await downloadFile('http://ipv4.download.thinkbroadband.com/20MB.zip', 'mb_20.zip') - await downloadFile('http://ipv4.download.thinkbroadband.com/50MB.zip', 'mb_50.zip') - await downloadFile('http://ipv4.download.thinkbroadband.com/100MB.zip', 'mb_100.zip') - await downloadFile('http://ipv4.download.thinkbroadband.com/200MB.zip', 'mb_200.zip') -})() diff --git a/tests/k6/src/lib/api/api.ts b/tests/k6/src/lib/api/api.ts index b6bf237b6..1957edcd4 100644 --- a/tests/k6/src/lib/api/api.ts +++ b/tests/k6/src/lib/api/api.ts @@ -1,5 +1,5 @@ import encoding from 'k6/encoding'; -import * as types from "../types"; +import * as types from '../types'; export const headersDefault = ({credential}: { credential: types.Credential }): { [key: string]: string } => { const isOIDCGuard = (credential as types.Token).tokenType !== undefined; diff --git a/tests/k6/src/lib/api/dav.ts b/tests/k6/src/lib/api/dav.ts index bfac07300..ed78e70a2 100644 --- a/tests/k6/src/lib/api/dav.ts +++ b/tests/k6/src/lib/api/dav.ts @@ -1,15 +1,32 @@ -import http, {RefinedResponse, ResponseType} from "k6/http"; +import http, {RefinedResponse, ResponseType} from 'k6/http'; import * as api from './api' -import * as defaults from "../defaults"; -import * as types from "../types"; +import * as defaults from '../defaults'; +import * as types from '../types'; + +export const fileUpload = ( + { + credential, + userName, + path = '', + asset, + tags, + }: { + credential: types.Credential; + userName: string; + asset: types.Asset; + path?: string; + tags?: { [key: string]: string }; + } +): RefinedResponse => { -export const fileUpload = ( - {credential, userName, asset}: { credential: types.Credential; userName: string; asset: types.Asset } -): RefinedResponse => { return http.put( - `${defaults.ENV.HOST}/remote.php/dav/files/${userName}/${asset.fileName}`, + [ + defaults.ENV.HOST, + ...`/remote.php/dav/files/${userName}/${path}/${asset.name}`.split('/').filter(Boolean) + ].join('/'), asset.bytes as any, { + tags, headers: { ...api.headersDefault({credential}) } @@ -17,12 +34,26 @@ export const fileUpload = ( ); } -export const fileDownload = ( - {credential, userName, fileName}: { credential: types.Credential; userName: string; fileName: string } -): RefinedResponse => { +export const fileDownload = ( + { + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + userName: string; + path: string; + tags?: { [key: string]: string }; + } +): RefinedResponse => { return http.get( - `${defaults.ENV.HOST}/remote.php/dav/files/${userName}/${fileName}`, + [ + defaults.ENV.HOST, + ...`/remote.php/dav/files/${userName}/${path}`.split('/').filter(Boolean) + ].join('/'), { + tags, headers: { ...api.headersDefault({credential}) } @@ -30,13 +61,87 @@ export const fileDownload = ( ); } -export const fileDelete = ( - {credential, userName, fileName}: { credential: types.Credential; userName: string; fileName: string } -): RefinedResponse => { +export const fileDelete = ( + { + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + userName: string; + path: string; + tags?: { [key: string]: string }; + } +): RefinedResponse => { return http.del( - `${defaults.ENV.HOST}/remote.php/dav/files/${userName}/${fileName}`, + [ + defaults.ENV.HOST, + ...`/remote.php/dav/files/${userName}/${path}`.split('/').filter(Boolean) + ].join('/'), {}, { + tags, + headers: { + ...api.headersDefault({credential}) + } + } + ); +} + +export const folderCreate = ( + { + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + userName: string; + path: string; + tags?: { [key: string]: string }; + } +): RefinedResponse => { + return http.request( + 'MKCOL', + [ + defaults.ENV.HOST, + ...`/remote.php/dav/files/${userName}/${path}`.split('/').filter(Boolean) + ].join('/'), + {}, + { + tags, + headers: { + ...api.headersDefault({credential}) + } + } + ); +} + +export const folderDelete = fileDelete + +export const propfind = ( + { + credential, + userName, + path = '', + tags, + }: { + credential: types.Credential; + userName: string; + path?: string; + tags?: { [key: string]: string }; + } +): RefinedResponse => { + return http.request( + 'PROPFIND', + [ + defaults.ENV.HOST, + ...`/remote.php/dav/files/${userName}/${path}`.split('/').filter(Boolean) + ].join('/'), + {}, + { + tags, headers: { ...api.headersDefault({credential}) } diff --git a/tests/k6/src/lib/api/users.ts b/tests/k6/src/lib/api/users.ts index 5be51a7f3..027f6d632 100644 --- a/tests/k6/src/lib/api/users.ts +++ b/tests/k6/src/lib/api/users.ts @@ -1,14 +1,23 @@ -import http, {RefinedResponse, ResponseType} from "k6/http"; +import http, {RefinedResponse, ResponseType} from 'k6/http'; import * as api from './api' -import * as defaults from "../defaults"; -import * as types from "../types"; +import * as defaults from '../defaults'; +import * as types from '../types'; -export const userInfo = ( - {credential, userName}: { credential: types.Credential; userName: string; } -): RefinedResponse => { +export const userInfo = ( + { + credential, + userName, + tags, + }: { + credential: types.Credential; + userName: string; + tags?: { [name: string]: string }; + } +): RefinedResponse => { return http.get( `${defaults.ENV.HOST}/ocs/v1.php/cloud/users/${userName}`, { + tags, headers: { ...api.headersDefault({credential}) }, diff --git a/tests/k6/src/lib/auth.ts b/tests/k6/src/lib/auth.ts index 760abab99..6622b4be7 100644 --- a/tests/k6/src/lib/auth.ts +++ b/tests/k6/src/lib/auth.ts @@ -1,7 +1,7 @@ -import * as defaults from "./defaults"; -import http from "k6/http"; -import queryString from "query-string"; -import * as types from "./types"; +import * as defaults from './defaults'; +import http from 'k6/http'; +import queryString from 'query-string'; +import * as types from './types'; import {fail} from 'k6'; import {get} from 'lodash' diff --git a/tests/k6/src/lib/defaults.ts b/tests/k6/src/lib/defaults.ts index 17e79611c..4e2deac52 100644 --- a/tests/k6/src/lib/defaults.ts +++ b/tests/k6/src/lib/defaults.ts @@ -1,13 +1,4 @@ import * as types from './types'; -import {Options} from "k6/options"; - -export class K6 { - public static readonly OPTIONS: Options = { - insecureSkipTLSVerify: true, - iterations: 1, - vus: 1, - }; -} export class ENV { public static readonly HOST = __ENV.OC_HOST || 'https://localhost:9200'; @@ -15,18 +6,12 @@ export class ENV { public static readonly PASSWORD = __ENV.OC_PASSWORD; public static readonly OIDC_HOST = __ENV.OC_OIDC_HOST || ENV.HOST; public static readonly OIDC_ENABLED = __ENV.OC_OIDC_ENABLED === 'true' || false; - public static readonly FILE_NAME = '../_files/' + (__ENV.OC_TEST_FILE || 'kb_50.jpg').split('/').pop(); } -export const FILE = { - fileName: ENV.FILE_NAME, - bytes: open(ENV.FILE_NAME, 'b'), -}; - -export class ACCOUNT { +export class ACCOUNTS { public static readonly EINSTEIN = 'einstein'; public static readonly RICHARD = 'richard'; - private static readonly list: { [key: string]: types.Account; } = { + public static readonly ALL: { [key: string]: types.Account; } = { einstein: { login: 'einstein', password: 'relativity', @@ -36,15 +21,4 @@ export class ACCOUNT { password: 'superfluidity', }, } - - public static for(key: string): types.Account { - if (ENV.LOGIN && ENV.PASSWORD) { - return { - login: ENV.LOGIN, - password: ENV.PASSWORD, - } - } - - return this.list[key]; - } -} +} \ No newline at end of file diff --git a/tests/k6/src/lib/playbook/dav.ts b/tests/k6/src/lib/playbook/dav.ts index 36c677541..ac648c5fa 100644 --- a/tests/k6/src/lib/playbook/dav.ts +++ b/tests/k6/src/lib/playbook/dav.ts @@ -1,70 +1,308 @@ -import {Gauge, Trend} from "k6/metrics"; -import * as api from "../api"; -import * as utils from "../utils"; -import {bytes, check} from "k6"; -import * as types from "../types"; +import {Gauge, Trend} from 'k6/metrics'; +import * as api from '../api'; +import {check} from 'k6'; +import * as types from '../types'; +import {RefinedResponse, ResponseType} from 'k6/http'; -export const fileUpload = () => { - const fileUploadTrend = new Trend('occ_file_upload_trend', true); - const fileUploadErrorRate = new Gauge('occ_file_upload_error_rate'); +export const fileUpload = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { + const playName = name || `oc_${metricID}_play_dav_file_upload`; + const metricTrendName = `${playName}_trend`; + const metricTrend = new Trend(metricTrendName, true); + const metricErrorRateName = `${playName}_error_rate`; + const metricErrorRate = new Gauge(metricErrorRateName); - return ({credential, userName, asset}: { credential: types.Credential; userName: string; asset: types.Asset }): string => { - const fileName = `upload-${userName}-${__VU}-${__ITER}.${utils.extension(asset.fileName)}`; - const uploadResponse = api.dav.fileUpload({ - credential: credential as any, - asset: { - fileName, - bytes: asset.bytes, - }, - userName, - }); + return { + playName, + metricTrendName, + metricErrorRateName, + exec: ( + { + credential, + userName, + path, + asset, + tags, + }: { + credential: types.Credential; + path?: string; + userName: string; + asset: types.Asset; + tags?: { [key: string]: string }; + } + ): { + response: RefinedResponse; + tags: { [key: string]: string }; + } => { + tags = {play: playName, ...tags}; - check(uploadResponse, { - 'file upload status is 201': () => uploadResponse.status === 201, - }) || fileUploadErrorRate.add(1); + const response = api.dav.fileUpload({ + credential: credential as types.Credential, + asset, + userName, + tags, + path, + }); - fileUploadTrend.add(uploadResponse.timings.duration) + check(response, { + 'file upload status is 201': () => response.status === 201, + }, tags) || metricErrorRate.add(1, tags); - return fileName + metricTrend.add(response.timings.duration, tags) + + return { + response, + tags, + } + } } }; -export const fileDelete = () => { - const fileDeleteTrend = new Trend('occ_file_delete_trend', true); - const fileDeleteErrorRate = new Gauge('occ_file_delete_error_rate'); +export const fileDelete = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { + const playName = name || `oc_${metricID}_play_dav_file_delete`; + const metricTrendName = `${playName}_trend`; + const metricTrend = new Trend(metricTrendName, true); + const metricErrorRateName = `${playName}_error_rate`; + const metricErrorRate = new Gauge(metricErrorRateName); - return ({credential, userName, fileName}: { credential: types.Credential, userName: string; fileName: string }) => { - const deleteResponse = api.dav.fileDelete({ - credential: credential as any, - fileName, - userName, - }); + return { + playName, + metricTrendName, + metricErrorRateName, + exec: ( + { + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + userName: string; + path: string; + tags?: { [key: string]: string }; + } + ): { + response: RefinedResponse; + tags: { [key: string]: string }; + } => { + tags = {play: playName, ...tags}; - check(deleteResponse, { - 'file delete status is 204': () => deleteResponse.status === 204, - }) || fileDeleteErrorRate.add(1); + const response = api.dav.fileDelete({ + credential: credential as types.Credential, + path, + userName, + tags, + }); - fileDeleteTrend.add(deleteResponse.timings.duration) + check(response, { + 'file delete status is 204': () => response.status === 204, + }, tags) || metricErrorRate.add(1, tags); + + metricTrend.add(response.timings.duration, tags) + + return { + response, + tags, + } + } } }; -export const fileDownload = () => { - const fileDownloadTrend = new Trend('occ_file_download_trend', true); - const fileDownloadErrorRate = new Gauge('occ_file_download_error_rate'); +export const fileDownload = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { + const playName = name || `oc_${metricID}_play_dav_file_download`; + const metricTrendName = `${playName}_trend`; + const metricTrend = new Trend(metricTrendName, true); + const metricErrorRateName = `${playName}_error_rate`; + const metricErrorRate = new Gauge(metricErrorRateName); - return ({credential, userName, fileName}: { credential: types.Credential, userName: string; fileName: string }): bytes => { - const downloadResponse = api.dav.fileDownload({ - credential: credential as any, - fileName, - userName, - }); + return { + playName, + metricTrendName, + metricErrorRateName, + exec: ( + { + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + userName: string; + path: string; + tags?: { [key: string]: string }; + } + ): { + response: RefinedResponse; + tags: { [key: string]: string }; + } => { + tags = {play: playName, ...tags}; - check(downloadResponse, { - 'file download status is 200': () => downloadResponse.status === 200, - }) || fileDownloadErrorRate.add(1); + const response = api.dav.fileDownload({ + credential: credential as types.Credential, + path, + userName, + tags, + }); - fileDownloadTrend.add(downloadResponse.timings.duration) + check(response, { + 'file download status is 200': () => response.status === 200, + }, tags) || metricErrorRate.add(1, tags); - return downloadResponse.body as bytes + metricTrend.add(response.timings.duration, tags) + + return { + response, + tags, + } + } } }; + +export const folderCreate = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { + const playName = name || `oc_${metricID}_play_dav_folder_create`; + const metricTrendName = `${playName}_trend`; + const metricTrend = new Trend(metricTrendName, true); + const metricErrorRateName = `${playName}_error_rate`; + const metricErrorRate = new Gauge(metricErrorRateName); + + return { + playName, + metricTrendName, + metricErrorRateName, + exec: ( + { + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + userName: string; + path: string; + tags?: { [key: string]: string }; + } + ): { + response: RefinedResponse; + tags: { [key: string]: string }; + } => { + tags = {play: playName, ...tags}; + + const response = api.dav.folderCreate({ + credential: credential as types.Credential, + path, + userName, + tags, + }); + + check(response, { + 'folder create status is 201': () => response.status === 201, + }, tags) || metricErrorRate.add(1, tags); + + metricTrend.add(response.timings.duration, tags) + + return { + response, + tags, + } + } + } +}; + +export const folderDelete = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { + const playName = name || `oc_${metricID}_play_dav_folder_delete`; + const metricTrendName = `${playName}_trend`; + const metricTrend = new Trend(metricTrendName, true); + const metricErrorRateName = `${playName}_error_rate`; + const metricErrorRate = new Gauge(metricErrorRateName); + + return { + playName, + metricTrendName, + metricErrorRateName, + exec: ( + { + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + userName: string; + path: string; + tags?: { [key: string]: string }; + } + ): { + response: RefinedResponse; + tags: { [key: string]: string }; + } => { + tags = {play: playName, ...tags}; + + const response = api.dav.folderDelete({ + credential: credential as types.Credential, + path, + userName, + tags, + }); + + check(response, { + 'folder delete status is 204': () => response.status === 204, + }, tags) || metricErrorRate.add(1, tags); + + metricTrend.add(response.timings.duration, tags) + + return { + response, + tags, + } + } + } +}; + +export const propfind = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { + const playName = name || `oc_${metricID}_play_dav_propfind`; + const metricTrendName = `${playName}_trend`; + const metricTrend = new Trend(metricTrendName, true); + const metricErrorRateName = `${playName}_error_rate`; + const metricErrorRate = new Gauge(metricErrorRateName); + + return { + playName, + metricTrendName, + metricErrorRateName, + exec: ( + { + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + userName: string; + path?: string; + tags?: { [key: string]: string }; + } + ): { + response: RefinedResponse; + tags: { [key: string]: string }; + } => { + tags = {play: playName, ...tags}; + + const response = api.dav.propfind({ + credential: credential as types.Credential, + path, + userName, + tags, + }); + + check(response, { + 'propfind status is 207': () => response.status === 207, + }, tags) || metricErrorRate.add(1, tags); + + metricTrend.add(response.timings.duration, tags) + + return { + response, + tags, + } + } + } +}; \ No newline at end of file diff --git a/tests/k6/src/lib/types.ts b/tests/k6/src/lib/types.ts index 159be1087..8cecf6e40 100644 --- a/tests/k6/src/lib/types.ts +++ b/tests/k6/src/lib/types.ts @@ -1,8 +1,8 @@ -import {bytes} from "k6"; +import {bytes} from 'k6'; export interface Asset { bytes: bytes; - fileName: string; + name: string; } export interface Token { @@ -21,4 +21,6 @@ export type Credential = Token | Account export interface AuthProvider { credential: Credential -} \ No newline at end of file +} + +export type AssetUnit = 'KB' | 'MB' | 'GB' \ No newline at end of file diff --git a/tests/k6/src/lib/utils.ts b/tests/k6/src/lib/utils.ts index 54f9dcb35..85f0599a6 100644 --- a/tests/k6/src/lib/utils.ts +++ b/tests/k6/src/lib/utils.ts @@ -1,8 +1,57 @@ +import {bytes} from 'k6'; +import {randomBytes as k6_randomBytes} from 'k6/crypto'; +import * as defaults from './defaults'; +import * as types from './types'; + +export const randomNumber = ({min, max}: { min: number; max: number; }): number => { + return Math.random() * (max - min) + min; +} + export const randomString = (): string => { - return Math.random().toString(36).slice(2) + return Math.random().toString(20).substr(2) } -export const extension = (p: string): string | undefined => { - return (p.split('/').pop())!.split('.').pop() +export const buildAccount = ({login = defaults.ACCOUNTS.EINSTEIN}: { login: string; }): types.Account => { + if (defaults.ENV.LOGIN && defaults.ENV.PASSWORD) { + return { + login: defaults.ENV.LOGIN, + password: defaults.ENV.PASSWORD, + } + } + + return defaults.ACCOUNTS.ALL[login]; +} + +export const buildAsset = ( + { + name = 'dummy.zip', + size = 1, + unit = 'MB', + }: { + name?: string; + size?: number; + unit?: types.AssetUnit; + } +): types.Asset => { + const gen = { + KB: (s: number): bytes => { + return k6_randomBytes(s * 1024) + }, + MB: (s: number): bytes => { + return gen.KB(s * 1024) + }, + GB: (s: number): bytes => { + return gen.MB(s * 1024) + }, + } + + const fileBaseName = name.split('/').reverse()[0] + const fileName = fileBaseName.split('.')[0] + const fileExtension = fileBaseName.split('.').reverse()[0] || 'zip' + + return { + name: `${fileName}-${__VU}-${__ITER}-${size}-${unit}-${randomString()}.${fileExtension}`, + bytes: gen[unit](size), + } } diff --git a/tests/k6/src/test/benchmark/file-download.ts b/tests/k6/src/test/benchmark/file-download.ts deleted file mode 100644 index 06ed8bfb8..000000000 --- a/tests/k6/src/test/benchmark/file-download.ts +++ /dev/null @@ -1,40 +0,0 @@ -import {defaults, playbook} from '../../lib' -import {Options} from 'k6/options'; -import {sleep} from "k6"; -import auth from "../../lib/auth"; - -export const options: Options = { - ...defaults.K6.OPTIONS, -}; -const authFactory = new auth(defaults.ACCOUNT.for(defaults.ACCOUNT.EINSTEIN)); -const plays = { - fileUpload: playbook.dav.fileUpload(), - fileDownload: playbook.dav.fileDownload(), - fileDelete: playbook.dav.fileDelete(), -} -export default () => { - const {login: userName} = authFactory.account; - const fileName = plays.fileUpload({ - credential: authFactory.credential, - userName, - asset: defaults.FILE, - }); - - sleep(1) - - plays.fileDownload({ - credential: authFactory.credential, - userName, - fileName, - }); - - sleep(1) - - plays.fileDelete({ - credential: authFactory.credential, - userName, - fileName, - }); - - sleep(1) -}; \ No newline at end of file diff --git a/tests/k6/src/test/benchmark/file-upload.ts b/tests/k6/src/test/benchmark/file-upload.ts deleted file mode 100644 index 2a7042174..000000000 --- a/tests/k6/src/test/benchmark/file-upload.ts +++ /dev/null @@ -1,31 +0,0 @@ -import {defaults, playbook} from '../../lib' -import {Options} from 'k6/options'; -import {sleep} from "k6"; -import auth from "../../lib/auth"; - -export const options: Options = { - ...defaults.K6.OPTIONS, -}; -const authFactory = new auth(defaults.ACCOUNT.for(defaults.ACCOUNT.EINSTEIN)); -const plays = { - fileUpload: playbook.dav.fileUpload(), - fileDelete: playbook.dav.fileDelete(), -} -export default () => { - const {login: userName} = authFactory.account; - const fileName = plays.fileUpload({ - credential: authFactory.credential, - userName, - asset: defaults.FILE, - }); - - sleep(1) - - plays.fileDelete({ - credential: authFactory.credential, - userName, - fileName, - }); - - sleep(1) -}; \ No newline at end of file diff --git a/tests/k6/src/test/issue/github/ocis/162.ts b/tests/k6/src/test/issue/github/ocis/162.ts deleted file mode 100644 index 144535de8..000000000 --- a/tests/k6/src/test/issue/github/ocis/162.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {Options} from 'k6/options'; -import * as uploadFilesBenchmark from '../../../benchmark/file-upload' - -export const options: Options = { - ...uploadFilesBenchmark.options, - iterations: 200, - vus: 50, -}; -export default uploadFilesBenchmark.default; \ No newline at end of file diff --git a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts new file mode 100644 index 000000000..884b7b06e --- /dev/null +++ b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts @@ -0,0 +1,64 @@ +import {Options} from "k6/options"; +import {utils, auth, defaults, playbook} from '../../../../../../lib' +import {times} from 'lodash' + +// put 1000 files into one dir and run a 'PROPFIND' through API + +const files: { + size: number; + unit: any; +}[] = times(1000, () => ({size: 1, unit: 'KB'})) +const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); +const plays = { + fileUpload: playbook.dav.fileUpload({}), + propfind: playbook.dav.propfind({}), + fileDelete: playbook.dav.fileDelete({}), +} +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 3, + vus: 1, + thresholds: files.reduce((acc: any, c) => { + acc[`${plays.fileUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.propfind.metricTrendName}`] = [] + acc[`${plays.fileDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + return acc + }, {}), +}; +export default (): void => { + const filesUploaded: { id: string, name: string, }[] = [] + const {account, credential} = authFactory; + + files.forEach(f => { + const id = f.unit + f.size.toString(); + + const asset = utils.buildAsset({ + name: `${account.login}-dummy.zip`, + unit: f.unit as any, + size: f.size, + }) + + plays.fileUpload.exec({ + credential, + asset, + userName: account.login, + tags: {asset: id}, + }); + + filesUploaded.push({id, name: asset.name}) + }) + + plays.propfind.exec({ + credential, + userName: account.login, + }) + + filesUploaded.forEach(f => { + plays.fileDelete.exec({ + credential, + userName: account.login, + path: f.name, + tags: {asset: f.id}, + }); + }) +} \ No newline at end of file diff --git a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts new file mode 100644 index 000000000..2af298381 --- /dev/null +++ b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts @@ -0,0 +1,81 @@ +import {Options} from "k6/options"; +import {utils, auth, defaults, playbook} from '../../../../../../lib' +import {times} from 'lodash' + +// Unpack standard data tarball, run PROPFIND on each dir + +const files: { + size: number; + unit: any; +}[] = times(1000, () => ({size: 1, unit: 'KB'})) +const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); +const plays = { + fileUpload: playbook.dav.fileUpload({}), + propfind: playbook.dav.propfind({}), + folderCreate: playbook.dav.folderCreate({}), + folderDelete: playbook.dav.folderDelete({}), +} +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 3, + vus: 1, + thresholds: files.reduce((acc: any, c) => { + acc[`${plays.fileUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.propfind.metricTrendName}`] = [] + acc[`${plays.folderCreate.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.folderDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + return acc + }, {}), +}; +export default (): void => { + const filesUploaded: { id: string, name: string, folder: string }[] = [] + const {account, credential} = authFactory; + + files.forEach(f => { + const id = f.unit + f.size.toString(); + + const asset = utils.buildAsset({ + name: `${account.login}-dummy.zip`, + unit: f.unit as any, + size: f.size, + }) + + const folder = times(utils.randomNumber({min: 1, max: 10}), () => utils.randomString()).reduce((acc: string[], c) => { + acc.push(c) + + plays.folderCreate.exec({ + credential, + path: acc.join('/'), + userName: account.login, + tags: {asset: id}, + }); + + return acc + }, []).join('/') + + + plays.fileUpload.exec({ + credential, + asset, + path: folder, + userName: account.login, + tags: {asset: id}, + }); + + filesUploaded.push({id, name: asset.name, folder}) + }) + + plays.propfind.exec({ + credential, + userName: account.login, + }) + + filesUploaded.forEach(f => { + plays.folderDelete.exec({ + credential, + userName: account.login, + path: f.folder.split('/')[0], + tags: {asset: f.id}, + }); + }) +} \ No newline at end of file diff --git a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts new file mode 100644 index 000000000..299c95b70 --- /dev/null +++ b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts @@ -0,0 +1,72 @@ +import {Options} from "k6/options"; +import {utils, auth, defaults, playbook} from '../../../../../../lib' +import {times} from 'lodash' + +// upload, download and delete of many files with several sizes and summary size of 500 MB in one directory + +const files: { + size: number; + unit: any; +}[] = [ + ...times(100, () => ({size: 500, unit: 'KB'})), + ...times(50, () => ({size: 5, unit: 'MB'})), + ...times(10, () => ({size: 25, unit: 'MB'})), +] +const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); +const plays = { + fileUpload: playbook.dav.fileUpload({}), + fileDownload: playbook.dav.fileDownload({}), + fileDelete: playbook.dav.fileDelete({}), +} +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 3, + vus: 1, + thresholds: files.reduce((acc: any, c) => { + acc[`${plays.fileUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.fileDownload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.fileDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + return acc + }, {}), +}; +export default (): void => { + const filesUploaded: { id: string, name: string, }[] = [] + const {account, credential} = authFactory; + + files.forEach(f => { + const id = f.unit + f.size.toString(); + + const asset = utils.buildAsset({ + name: `${account.login}-dummy.zip`, + unit: f.unit as any, + size: f.size, + }) + + plays.fileUpload.exec({ + credential, + asset, + userName: account.login, + tags: {asset: id}, + }); + + filesUploaded.push({id, name: asset.name}) + }) + + filesUploaded.forEach(f => { + plays.fileDownload.exec({ + credential, + userName: account.login, + path: f.name, + tags: {asset: f.id}, + }); + }) + + filesUploaded.forEach(f => { + plays.fileDelete.exec({ + credential, + userName: account.login, + path: f.name, + tags: {asset: f.id}, + }); + }) +} \ No newline at end of file diff --git a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts new file mode 100644 index 000000000..02d22570d --- /dev/null +++ b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts @@ -0,0 +1,75 @@ +import {Options} from "k6/options"; +import {utils, auth, defaults, playbook, types} from '../../../../../../lib' + +// upload, download and delete of one file with sizes 50kb, 500kb, 5MB, 50MB, 500MB, 1GB + +const files: { + size: number; + unit: types.AssetUnit; +}[] = [ + {size: 50, unit: 'KB'}, + {size: 500, unit: 'KB'}, + {size: 5, unit: 'MB'}, + {size: 50, unit: 'MB'}, + {size: 500, unit: 'MB'}, + {size: 1, unit: 'GB'}, +] +const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); +const plays = { + fileUpload: playbook.dav.fileUpload({}), + fileDownload: playbook.dav.fileDownload({}), + fileDelete: playbook.dav.fileDelete({}), +} +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 3, + vus: 1, + thresholds: files.reduce((acc: any, c) => { + acc[`${plays.fileUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.fileDownload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.fileDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + return acc + }, {}), +}; + +export default (): void => { + const filesUploaded: { id: string, name: string, }[] = [] + const {account, credential} = authFactory; + + files.forEach(f => { + const id = f.unit + f.size.toString(); + + const asset = utils.buildAsset({ + name: `${account.login}-dummy.zip`, + unit: f.unit as any, + size: f.size, + }) + + plays.fileUpload.exec({ + credential, + asset, + userName: account.login, + tags: {asset: id}, + }); + + filesUploaded.push({id, name: asset.name}) + }) + + filesUploaded.forEach(f => { + plays.fileDownload.exec({ + credential, + userName: account.login, + path: f.name, + tags: {asset: f.id}, + }); + }) + + filesUploaded.forEach(f => { + plays.fileDelete.exec({ + credential, + userName: account.login, + path: f.name, + tags: {asset: f.id}, + }); + }) +} \ No newline at end of file diff --git a/tests/k6/yarn.lock b/tests/k6/yarn.lock index 1197148b1..df96e6678 100644 --- a/tests/k6/yarn.lock +++ b/tests/k6/yarn.lock @@ -1682,13 +1682,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^0.21.0: - version "0.21.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.0.tgz#26df088803a2350dff2c27f96fef99fe49442aca" - integrity sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw== - dependencies: - follow-redirects "^1.10.0" - babel-jest@^25.5.1: version "25.5.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-25.5.1.tgz#bc2e6101f849d6f6aec09720ffc7bc5332e62853" @@ -2028,11 +2021,6 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^2.4.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.5.0.tgz#12763e47251bf951cb75c201dfa58ff1bcb2d047" - integrity sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ== - cli-truncate@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" @@ -2055,11 +2043,6 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -2345,13 +2328,6 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== -defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= - dependencies: - clone "^1.0.2" - define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -2875,11 +2851,6 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -follow-redirects@^1.10.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" - integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -3014,7 +2985,7 @@ glob-parent@^5.0.0, glob-parent@^5.1.0: dependencies: is-glob "^4.0.1" -glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -3252,11 +3223,6 @@ inquirer@^7.0.0: strip-ansi "^6.0.0" through "^2.3.6" -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -3381,11 +3347,6 @@ is-glob@^4.0.0, is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" -is-interactive@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" - integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== - is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" @@ -4575,20 +4536,6 @@ optionator@^0.8.1, optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" -ora@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-5.1.0.tgz#b188cf8cd2d4d9b13fd25383bc3e5cba352c94f8" - integrity sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w== - dependencies: - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-spinners "^2.4.0" - is-interactive "^1.0.0" - log-symbols "^4.0.0" - mute-stream "0.0.8" - strip-ansi "^6.0.0" - wcwidth "^1.0.1" - os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -4944,13 +4891,6 @@ realpath-native@^2.0.0: resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866" integrity sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q== -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - redent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" @@ -5154,7 +5094,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.3.2: +resolve@^1.10.0, resolve@^1.11.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.3.2: version "1.19.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== @@ -5381,15 +5321,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@^0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" - integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - shellwords@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" @@ -6089,13 +6020,6 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= - dependencies: - defaults "^1.0.3" - webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" From cc881c4c9a5fbb4482024b11d2bc74d825235e75 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Wed, 2 Dec 2020 04:25:02 +0100 Subject: [PATCH 07/27] remove reports --- tests/k6/report/ocis-folder-listing-flat.json | 168 ---------- tests/k6/report/ocis-many-small.json | 224 ------------- tests/k6/report/ocis-some-large.json | 296 ------------------ 3 files changed, 688 deletions(-) delete mode 100644 tests/k6/report/ocis-folder-listing-flat.json delete mode 100644 tests/k6/report/ocis-many-small.json delete mode 100644 tests/k6/report/ocis-some-large.json diff --git a/tests/k6/report/ocis-folder-listing-flat.json b/tests/k6/report/ocis-folder-listing-flat.json deleted file mode 100644 index c01cae720..000000000 --- a/tests/k6/report/ocis-folder-listing-flat.json +++ /dev/null @@ -1,168 +0,0 @@ -{ - "metrics": { - "checks": { - "fails": 0, - "passes": 6003, - "value": 0 - }, - "data_received": { - "count": 5232948, - "rate": 35275.75112278176 - }, - "data_sent": { - "count": 4637493, - "rate": 31261.737915538728 - }, - "http_req_blocked": { - "avg": 0.004372313843078474, - "max": 4.63, - "med": 0.003, - "min": 0.002, - "p(90)": 0.005, - "p(95)": 0.007 - }, - "http_req_connecting": { - "avg": 0.000056305180742961854, - "max": 0.338, - "med": 0, - "min": 0, - "p(90)": 0, - "p(95)": 0 - }, - "http_req_duration": { - "avg": 24.326444277861146, - "max": 493.144, - "med": 21.826, - "min": 10.256, - "p(90)": 38.041000000000004, - "p(95)": 43.9535 - }, - "http_req_receiving": { - "avg": 0.05978927203065133, - "max": 1.579, - "med": 0.05, - "min": 0.036, - "p(90)": 0.085, - "p(95)": 0.104 - }, - "http_req_sending": { - "avg": 0.03032550391470921, - "max": 0.223, - "med": 0.025, - "min": 0.018, - "p(90)": 0.043, - "p(95)": 0.056 - }, - "http_req_tls_handshaking": { - "avg": 0.0005380643011827419, - "max": 3.23, - "med": 0, - "min": 0, - "p(90)": 0, - "p(95)": 0 - }, - "http_req_waiting": { - "avg": 24.23632950191566, - "max": 492.043, - "med": 21.741, - "min": 10.192, - "p(90)": 37.92360000000001, - "p(95)": 43.8319 - }, - "http_reqs": { - "count": 6003, - "rate": 40.46673767636501 - }, - "iteration_duration": { - "avg": 49429.791962999996, - "max": 50603.792868, - "med": 49213.89341, - "min": 48471.689611, - "p(90)": 50325.8129764, - "p(95)": 50464.8029222 - }, - "iterations": { - "count": 3, - "rate": 0.020223257209577714 - }, - "oc_default_play_dav_file_delete_trend": { - "avg": 16.629310000000025, - "max": 75.491, - "med": 15.1365, - "min": 10.256, - "p(90)": 23.539, - "p(95)": 27.27049999999999 - }, - "oc_default_play_dav_file_delete_trend{asset:KB1": { - "avg": 16.629310000000025, - "max": 75.491, - "med": 15.1365, - "min": 10.256, - "p(90)": 23.539, - "p(95)": 27.27049999999999 - }, - "oc_default_play_dav_file_upload_trend": { - "avg": 31.677708999999993, - "max": 267.948, - "med": 29.3345, - "min": 19.082, - "p(90)": 43.212199999999996, - "p(95)": 50.722699999999996 - }, - "oc_default_play_dav_file_upload_trend{asset:KB1": { - "avg": 31.677708999999993, - "max": 267.948, - "med": 29.3345, - "min": 19.082, - "p(90)": 43.212199999999996, - "p(95)": 50.722699999999996 - }, - "oc_default_play_dav_propfind_trend": { - "avg": 370.19599999999997, - "max": 493.144, - "med": 310.431, - "min": 307.013, - "p(90)": 456.6014, - "p(95)": 474.8727 - }, - "vus": { - "max": 1, - "min": 1, - "value": 1 - }, - "vus_max": { - "max": 1, - "min": 1, - "value": 1 - } - }, - "root_group": { - "name": "", - "path": "", - "id": "d41d8cd98f00b204e9800998ecf8427e", - "groups": {}, - "checks": { - "file delete status is 204": { - "name": "file delete status is 204", - "path": "::file delete status is 204", - "id": "18e4ac556fd01961812afd85e16bb9d9", - "passes": 3000, - "fails": 0 - }, - "file upload status is 201": { - "name": "file upload status is 201", - "path": "::file upload status is 201", - "id": "d530d65df94c4e70b68aac6f2f054f1f", - "passes": 3000, - "fails": 0 - }, - "propfind status is 207": { - "name": "propfind status is 207", - "path": "::propfind status is 207", - "id": "6cbc0cbc7ef202f356106cf063105452", - "passes": 3, - "fails": 0 - } - } - } -} diff --git a/tests/k6/report/ocis-many-small.json b/tests/k6/report/ocis-many-small.json deleted file mode 100644 index e274791c0..000000000 --- a/tests/k6/report/ocis-many-small.json +++ /dev/null @@ -1,224 +0,0 @@ -{ - "metrics": { - "checks": { - "fails": 0, - "passes": 1440, - "value": 0 - }, - "data_received": { - "count": 1729675379, - "rate": 33808868.65162363 - }, - "data_sent": { - "count": 1736098107, - "rate": 33934409.646178715 - }, - "http_req_blocked": { - "avg": 0.006793055555555532, - "max": 4.046, - "med": 0.003, - "min": 0.002, - "p(90)": 0.006, - "p(95)": 0.008 - }, - "http_req_connecting": { - "avg": 0.00018055555555555557, - "max": 0.26, - "med": 0, - "min": 0, - "p(90)": 0, - "p(95)": 0 - }, - "http_req_duration": { - "avg": 32.08864027777775, - "max": 253.272, - "med": 26.4905, - "min": 10.372, - "p(90)": 50.71580000000001, - "p(95)": 64.83449999999998 - }, - "http_req_receiving": { - "avg": 4.024194444444447, - "max": 128.777, - "med": 0.064, - "min": 0.037, - "p(90)": 14.537700000000015, - "p(95)": 19.81769999999999 - }, - "http_req_sending": { - "avg": 5.342373611111132, - "max": 132.051, - "med": 0.03, - "min": 0.017, - "p(90)": 22.215200000000003, - "p(95)": 30.02865 - }, - "http_req_tls_handshaking": { - "avg": 0.00218125, - "max": 3.141, - "med": 0, - "min": 0, - "p(90)": 0, - "p(95)": 0 - }, - "http_req_waiting": { - "avg": 22.72207222222226, - "max": 251.256, - "med": 21.123, - "min": 8.077, - "p(90)": 34.120799999999996, - "p(95)": 37.62935 - }, - "http_reqs": { - "count": 1440, - "rate": 28.146767566573555 - }, - "iteration_duration": { - "avg": 17041.291093666667, - "max": 17397.314603, - "med": 16968.823006, - "min": 16757.735672, - "p(90)": 17311.6162836, - "p(95)": 17354.4654433 - }, - "iterations": { - "count": 3, - "rate": 0.05863909909702824 - }, - "oc_default_play_dav_file_delete_trend": { - "avg": 15.769127083333343, - "max": 49.32, - "med": 14.7855, - "min": 10.372, - "p(90)": 21.6302, - "p(95)": 24.0062 - }, - "oc_default_play_dav_file_delete_trend{asset:KB500": { - "avg": 16.38810000000001, - "max": 49.32, - "med": 15.4255, - "min": 10.372, - "p(90)": 23.0987, - "p(95)": 24.657150000000005 - }, - "oc_default_play_dav_file_delete_trend{asset:MB25": { - "avg": 14.155766666666667, - "max": 19.967, - "med": 13.262, - "min": 10.793, - "p(90)": 18.776000000000003, - "p(95)": 19.580849999999998 - }, - "oc_default_play_dav_file_delete_trend{asset:MB5": { - "avg": 14.853853333333339, - "max": 26.691, - "med": 14.0415, - "min": 10.496, - "p(90)": 18.943699999999996, - "p(95)": 20.62044999999999 - }, - "oc_default_play_dav_file_download_trend": { - "avg": 37.784668749999994, - "max": 183.499, - "med": 32.0055, - "min": 19.14, - "p(90)": 55.628600000000006, - "p(95)": 93.45874999999992 - }, - "oc_default_play_dav_file_download_trend{asset:KB500": { - "avg": 26.680456666666657, - "max": 55.922, - "med": 24.979, - "min": 19.14, - "p(90)": 34.91720000000001, - "p(95)": 37.47365 - }, - "oc_default_play_dav_file_download_trend{asset:MB25": { - "avg": 113.08066666666669, - "max": 183.499, - "med": 103.05799999999999, - "min": 83.728, - "p(90)": 148.6112, - "p(95)": 162.21334999999996 - }, - "oc_default_play_dav_file_download_trend{asset:MB5": { - "avg": 44.93389333333334, - "max": 75.914, - "med": 43.920500000000004, - "min": 31.472, - "p(90)": 56.58899999999999, - "p(95)": 60.417399999999994 - }, - "oc_default_play_dav_file_upload_trend": { - "avg": 42.71212500000003, - "max": 253.272, - "med": 36.876999999999995, - "min": 21.145, - "p(90)": 56.78170000000001, - "p(95)": 114.79089999999997 - }, - "oc_default_play_dav_file_upload_trend{asset:KB500": { - "avg": 32.439143333333334, - "max": 253.272, - "med": 30.240000000000002, - "min": 21.145, - "p(90)": 40.75260000000001, - "p(95)": 45.08695000000001 - }, - "oc_default_play_dav_file_upload_trend{asset:MB25": { - "avg": 121.4088, - "max": 146.226, - "med": 119.23599999999999, - "min": 100.77, - "p(90)": 138.50189999999998, - "p(95)": 142.34375 - }, - "oc_default_play_dav_file_upload_trend{asset:MB5": { - "avg": 47.518753333333365, - "max": 77.615, - "med": 46.457, - "min": 35.46, - "p(90)": 56.623099999999994, - "p(95)": 61.826049999999974 - }, - "vus": { - "max": 1, - "min": 1, - "value": 1 - }, - "vus_max": { - "max": 1, - "min": 1, - "value": 1 - } - }, - "root_group": { - "name": "", - "path": "", - "id": "d41d8cd98f00b204e9800998ecf8427e", - "groups": {}, - "checks": { - "file delete status is 204": { - "name": "file delete status is 204", - "path": "::file delete status is 204", - "id": "18e4ac556fd01961812afd85e16bb9d9", - "passes": 480, - "fails": 0 - }, - "file download status is 200": { - "name": "file download status is 200", - "path": "::file download status is 200", - "id": "52b41fab3137d895e8ec58fd9dccd86e", - "passes": 480, - "fails": 0 - }, - "file upload status is 201": { - "name": "file upload status is 201", - "path": "::file upload status is 201", - "id": "d530d65df94c4e70b68aac6f2f054f1f", - "passes": 480, - "fails": 0 - } - } - } -} diff --git a/tests/k6/report/ocis-some-large.json b/tests/k6/report/ocis-some-large.json deleted file mode 100644 index 32eb31b6f..000000000 --- a/tests/k6/report/ocis-some-large.json +++ /dev/null @@ -1,296 +0,0 @@ -{ - "metrics": { - "checks": { - "fails": 0, - "passes": 54, - "value": 0 - }, - "data_received": { - "count": 4975515490, - "rate": 54283776.21668842 - }, - "data_sent": { - "count": 4995495858, - "rate": 54501765.65465097 - }, - "http_req_blocked": { - "avg": 0.07648148148148148, - "max": 3.614, - "med": 0.005, - "min": 0.003, - "p(90)": 0.024, - "p(95)": 0.03684999999999994 - }, - "http_req_connecting": { - "avg": 0.004203703703703703, - "max": 0.227, - "med": 0, - "min": 0, - "p(90)": 0, - "p(95)": 0 - }, - "http_req_duration": { - "avg": 1199.7894444444446, - "max": 11778.61, - "med": 81.80799999999999, - "min": 17.916, - "p(90)": 4263.4364000000005, - "p(95)": 7307.079449999999 - }, - "http_req_receiving": { - "avg": 586.4966296296295, - "max": 7419.291, - "med": 0.13, - "min": 0.04, - "p(90)": 1447.7991000000025, - "p(95)": 5254.929599999983 - }, - "http_req_sending": { - "avg": 555.0930740740743, - "max": 11707.466, - "med": 0.0775, - "min": 0.018, - "p(90)": 1635.9796000000044, - "p(95)": 3495.4676999999942 - }, - "http_req_tls_handshaking": { - "avg": 0.052833333333333336, - "max": 2.853, - "med": 0, - "min": 0, - "p(90)": 0, - "p(95)": 0 - }, - "http_req_waiting": { - "avg": 58.199740740740744, - "max": 305.282, - "med": 37.3425, - "min": 14.057, - "p(90)": 105.61020000000003, - "p(95)": 155.87789999999998 - }, - "http_reqs": { - "count": 54, - "rate": 0.5891497919346593 - }, - "iteration_duration": { - "avg": 30521.018089, - "max": 42157.485685, - "med": 26262.18445, - "min": 23143.384132, - "p(90)": 38978.425438, - "p(95)": 40567.9555615 - }, - "iterations": { - "count": 3, - "rate": 0.03273054399636997 - }, - "oc_default_play_dav_file_delete_trend": { - "avg": 42.30277777777778, - "max": 91.667, - "med": 33.669, - "min": 17.916, - "p(90)": 73.0931, - "p(95)": 86.0162 - }, - "oc_default_play_dav_file_delete_trend{asset:GB1": { - "avg": 36.54533333333333, - "max": 45.724, - "med": 33.698, - "min": 30.214, - "p(90)": 43.318799999999996, - "p(95)": 44.5214 - }, - "oc_default_play_dav_file_delete_trend{asset:KB50": { - "avg": 58.788333333333334, - "max": 85.019, - "med": 62.125, - "min": 29.221, - "p(90)": 80.4402, - "p(95)": 82.7296 - }, - "oc_default_play_dav_file_delete_trend{asset:KB500": { - "avg": 41.721333333333334, - "max": 67.982, - "med": 32.438, - "min": 24.744, - "p(90)": 60.8732, - "p(95)": 64.4276 - }, - "oc_default_play_dav_file_delete_trend{asset:MB5": { - "avg": 30.743666666666666, - "max": 56.309, - "med": 18.006, - "min": 17.916, - "p(90)": 48.648399999999995, - "p(95)": 52.478699999999996 - }, - "oc_default_play_dav_file_delete_trend{asset:MB50": { - "avg": 45.24466666666667, - "max": 91.667, - "med": 22.681, - "min": 21.386, - "p(90)": 77.86980000000001, - "p(95)": 84.7684 - }, - "oc_default_play_dav_file_delete_trend{asset:MB500": { - "avg": 40.77333333333333, - "max": 45.129, - "med": 43.551, - "min": 33.64, - "p(90)": 44.8134, - "p(95)": 44.971199999999996 - }, - "oc_default_play_dav_file_download_trend": { - "avg": 1815.5790555555557, - "max": 7454.559, - "med": 190.0605, - "min": 27.771, - "p(90)": 7302.4101, - "p(95)": 7380.7977 - }, - "oc_default_play_dav_file_download_trend{asset:GB1": { - "avg": 7365.578, - "max": 7454.559, - "med": 7367.781, - "min": 7274.394, - "p(90)": 7437.2034, - "p(95)": 7445.8812 - }, - "oc_default_play_dav_file_download_trend{asset:KB50": { - "avg": 77.559, - "max": 144.171, - "med": 60.735, - "min": 27.771, - "p(90)": 127.4838, - "p(95)": 135.82739999999998 - }, - "oc_default_play_dav_file_download_trend{asset:KB500": { - "avg": 64.77866666666667, - "max": 118.418, - "med": 47.796, - "min": 28.122, - "p(90)": 104.29360000000001, - "p(95)": 111.35580000000002 - }, - "oc_default_play_dav_file_download_trend{asset:MB5": { - "avg": 87.07633333333332, - "max": 132.468, - "med": 64.708, - "min": 64.053, - "p(90)": 118.916, - "p(95)": 125.69199999999998 - }, - "oc_default_play_dav_file_download_trend{asset:MB50": { - "avg": 465.49199999999996, - "max": 920.853, - "med": 239.673, - "min": 235.95, - "p(90)": 784.617, - "p(95)": 852.7349999999999 - }, - "oc_default_play_dav_file_download_trend{asset:MB500": { - "avg": 2832.990333333333, - "max": 4296.326, - "med": 2461.95, - "min": 1740.695, - "p(90)": 3929.4508, - "p(95)": 4112.8884 - }, - "oc_default_play_dav_file_upload_trend": { - "avg": 1741.4865, - "max": 11778.61, - "med": 277.241, - "min": 22.627, - "p(90)": 4528.384400000001, - "p(95)": 6293.604199999991 - }, - "oc_default_play_dav_file_upload_trend{asset:GB1": { - "avg": 7096.988666666667, - "max": 11778.61, - "med": 5325.662, - "min": 4186.694, - "p(90)": 10488.020400000001, - "p(95)": 11133.315200000001 - }, - "oc_default_play_dav_file_upload_trend{asset:KB50": { - "avg": 126.274, - "max": 243.95, - "med": 90.139, - "min": 44.733, - "p(90)": 213.18779999999998, - "p(95)": 228.56889999999999 - }, - "oc_default_play_dav_file_upload_trend{asset:KB500": { - "avg": 136.278, - "max": 307.61, - "med": 78.597, - "min": 22.627, - "p(90)": 261.80740000000003, - "p(95)": 284.7087 - }, - "oc_default_play_dav_file_upload_trend{asset:MB5": { - "avg": 105.57533333333333, - "max": 201.903, - "med": 61.229, - "min": 53.594, - "p(90)": 173.76819999999998, - "p(95)": 187.83559999999997 - }, - "oc_default_play_dav_file_upload_trend{asset:MB50": { - "avg": 426.2540000000001, - "max": 598.362, - "med": 433.528, - "min": 246.872, - "p(90)": 565.3951999999999, - "p(95)": 581.8786 - }, - "oc_default_play_dav_file_upload_trend{asset:MB500": { - "avg": 2557.549, - "max": 3159.682, - "med": 2397.078, - "min": 2115.887, - "p(90)": 3007.1612, - "p(95)": 3083.4215999999997 - }, - "vus": { - "max": 1, - "min": 1, - "value": 1 - }, - "vus_max": { - "max": 1, - "min": 1, - "value": 1 - } - }, - "root_group": { - "name": "", - "path": "", - "id": "d41d8cd98f00b204e9800998ecf8427e", - "groups": {}, - "checks": { - "file delete status is 204": { - "name": "file delete status is 204", - "path": "::file delete status is 204", - "id": "18e4ac556fd01961812afd85e16bb9d9", - "passes": 18, - "fails": 0 - }, - "file download status is 200": { - "name": "file download status is 200", - "path": "::file download status is 200", - "id": "52b41fab3137d895e8ec58fd9dccd86e", - "passes": 18, - "fails": 0 - }, - "file upload status is 201": { - "name": "file upload status is 201", - "path": "::file upload status is 201", - "id": "d530d65df94c4e70b68aac6f2f054f1f", - "passes": 18, - "fails": 0 - } - } - } -} From 9ba8fcf08e61a938c85b0e3ee902ff5ae275c14a Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Wed, 2 Dec 2020 14:18:11 +0100 Subject: [PATCH 08/27] simplify playbooks and api --- tests/k6/src/lib/api/api.ts | 31 +- tests/k6/src/lib/api/dav.ts | 143 ++----- tests/k6/src/lib/api/index.ts | 1 - tests/k6/src/lib/api/users.ts | 26 -- tests/k6/src/lib/playbook/dav.ts | 399 +++++------------- tests/k6/src/lib/playbook/playbook.ts | 19 + tests/k6/src/lib/types.ts | 4 +- .../jira/ocis/1007/folder-listing/flat.ts | 18 +- .../jira/ocis/1007/folder-listing/nested.ts | 24 +- .../1007/simple-down-and-upload/many-small.ts | 18 +- .../1007/simple-down-and-upload/some-large.ts | 18 +- 11 files changed, 233 insertions(+), 468 deletions(-) delete mode 100644 tests/k6/src/lib/api/users.ts create mode 100644 tests/k6/src/lib/playbook/playbook.ts diff --git a/tests/k6/src/lib/api/api.ts b/tests/k6/src/lib/api/api.ts index 1957edcd4..7ba632d1b 100644 --- a/tests/k6/src/lib/api/api.ts +++ b/tests/k6/src/lib/api/api.ts @@ -1,7 +1,10 @@ import encoding from 'k6/encoding'; import * as types from '../types'; +import * as defaults from "../defaults"; +import {merge} from 'lodash'; +import http, {RefinedParams, RefinedResponse, RequestBody, ResponseType} from "k6/http"; -export const headersDefault = ({credential}: { credential: types.Credential }): { [key: string]: string } => { +export const buildHeaders = ({credential}: { credential: types.Credential }): { [key: string]: string } => { const isOIDCGuard = (credential as types.Token).tokenType !== undefined; const authOIDC = credential as types.Token; const authBasic = credential as types.Account; @@ -9,4 +12,30 @@ export const headersDefault = ({credential}: { credential: types.Credential }): return { Authorization: isOIDCGuard ? `${authOIDC.tokenType} ${authOIDC.accessToken}` : `Basic ${encoding.b64encode(`${authBasic.login}:${authBasic.password}`)}`, } +} + +export const buildURL = ({path}: { path: string }): string => { + return [ + defaults.ENV.HOST, + ...path.split('/').filter(Boolean) + ].join('/') +} + +export const request = ({method, path, body = {}, params = {}, credential}: { + method: 'PROPFIND' | 'PUT' | 'GET' | 'DELETE' | 'MKCOL', + path: string, + credential: types.Credential; + body?: RequestBody | null, + params?: RefinedParams | null +}): RefinedResponse => { + return http.request( + method, + buildURL({path}), + body, + merge({ + headers: { + ...buildHeaders({credential}) + } + }, params) + ); } \ No newline at end of file diff --git a/tests/k6/src/lib/api/dav.ts b/tests/k6/src/lib/api/dav.ts index ed78e70a2..722e3ad0b 100644 --- a/tests/k6/src/lib/api/dav.ts +++ b/tests/k6/src/lib/api/dav.ts @@ -1,150 +1,59 @@ -import http, {RefinedResponse, ResponseType} from 'k6/http'; +import {RefinedResponse, ResponseType} from 'k6/http'; import * as api from './api' -import * as defaults from '../defaults'; import * as types from '../types'; -export const fileUpload = ( - { - credential, - userName, - path = '', - asset, - tags, - }: { +export class Upload { + public static exec({credential, userName, path = '', asset, tags}: { credential: types.Credential; userName: string; asset: types.Asset; path?: string; - tags?: { [key: string]: string }; + tags?: types.Tags; + }): RefinedResponse { + return api.request({method: 'PUT', credential, path: `/remote.php/dav/files/${userName}/${path}/${asset.name}`, params: {tags}, body: asset.bytes as any}) } -): RefinedResponse => { - - return http.put( - [ - defaults.ENV.HOST, - ...`/remote.php/dav/files/${userName}/${path}/${asset.name}`.split('/').filter(Boolean) - ].join('/'), - asset.bytes as any, - { - tags, - headers: { - ...api.headersDefault({credential}) - } - } - ); } -export const fileDownload = ( - { - credential, - userName, - path, - tags, - }: { +export class Download { + public static exec({credential, userName, path, tags}: { credential: types.Credential; userName: string; path: string; - tags?: { [key: string]: string }; + tags?: types.Tags; + }): RefinedResponse { + return api.request({method: 'GET', credential, path: `/remote.php/dav/files/${userName}/${path}`, params: {tags}}) } -): RefinedResponse => { - return http.get( - [ - defaults.ENV.HOST, - ...`/remote.php/dav/files/${userName}/${path}`.split('/').filter(Boolean) - ].join('/'), - { - tags, - headers: { - ...api.headersDefault({credential}) - } - } - ); } -export const fileDelete = ( - { - credential, - userName, - path, - tags, - }: { +export class Delete { + public static exec({credential, userName, path, tags}: { credential: types.Credential; userName: string; path: string; - tags?: { [key: string]: string }; + tags?: types.Tags; + }): RefinedResponse { + return api.request({method: 'DELETE', credential, path: `/remote.php/dav/files/${userName}/${path}`, params: {tags}}) } -): RefinedResponse => { - return http.del( - [ - defaults.ENV.HOST, - ...`/remote.php/dav/files/${userName}/${path}`.split('/').filter(Boolean) - ].join('/'), - {}, - { - tags, - headers: { - ...api.headersDefault({credential}) - } - } - ); } -export const folderCreate = ( - { - credential, - userName, - path, - tags, - }: { +export class Create { + public static exec({credential, userName, path, tags}: { credential: types.Credential; userName: string; path: string; - tags?: { [key: string]: string }; + tags?: types.Tags; + }): RefinedResponse { + return api.request({method: 'MKCOL', credential, path: `/remote.php/dav/files/${userName}/${path}`, params: {tags}}) } -): RefinedResponse => { - return http.request( - 'MKCOL', - [ - defaults.ENV.HOST, - ...`/remote.php/dav/files/${userName}/${path}`.split('/').filter(Boolean) - ].join('/'), - {}, - { - tags, - headers: { - ...api.headersDefault({credential}) - } - } - ); } -export const folderDelete = fileDelete - -export const propfind = ( - { - credential, - userName, - path = '', - tags, - }: { +export class Propfind { + public static exec({credential, userName, path = '', tags}: { credential: types.Credential; userName: string; path?: string; - tags?: { [key: string]: string }; + tags?: types.Tags; + }): RefinedResponse { + return api.request({method: 'PROPFIND', credential, path: `/remote.php/dav/files/${userName}/${path}`, params: {tags}}) } -): RefinedResponse => { - return http.request( - 'PROPFIND', - [ - defaults.ENV.HOST, - ...`/remote.php/dav/files/${userName}/${path}`.split('/').filter(Boolean) - ].join('/'), - {}, - { - tags, - headers: { - ...api.headersDefault({credential}) - } - } - ); } \ No newline at end of file diff --git a/tests/k6/src/lib/api/index.ts b/tests/k6/src/lib/api/index.ts index 52cba2cff..9219d4ba2 100644 --- a/tests/k6/src/lib/api/index.ts +++ b/tests/k6/src/lib/api/index.ts @@ -1,3 +1,2 @@ export * as api from './api' export * as dav from './dav' -export * as users from './users' \ No newline at end of file diff --git a/tests/k6/src/lib/api/users.ts b/tests/k6/src/lib/api/users.ts deleted file mode 100644 index 027f6d632..000000000 --- a/tests/k6/src/lib/api/users.ts +++ /dev/null @@ -1,26 +0,0 @@ -import http, {RefinedResponse, ResponseType} from 'k6/http'; -import * as api from './api' -import * as defaults from '../defaults'; -import * as types from '../types'; - -export const userInfo = ( - { - credential, - userName, - tags, - }: { - credential: types.Credential; - userName: string; - tags?: { [name: string]: string }; - } -): RefinedResponse => { - return http.get( - `${defaults.ENV.HOST}/ocs/v1.php/cloud/users/${userName}`, - { - tags, - headers: { - ...api.headersDefault({credential}) - }, - } - ); -} \ No newline at end of file diff --git a/tests/k6/src/lib/playbook/dav.ts b/tests/k6/src/lib/playbook/dav.ts index ac648c5fa..07f97d3e4 100644 --- a/tests/k6/src/lib/playbook/dav.ts +++ b/tests/k6/src/lib/playbook/dav.ts @@ -1,308 +1,141 @@ -import {Gauge, Trend} from 'k6/metrics'; import * as api from '../api'; import {check} from 'k6'; import * as types from '../types'; import {RefinedResponse, ResponseType} from 'k6/http'; +import {Play} from "./playbook"; -export const fileUpload = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { - const playName = name || `oc_${metricID}_play_dav_file_upload`; - const metricTrendName = `${playName}_trend`; - const metricTrend = new Trend(metricTrendName, true); - const metricErrorRateName = `${playName}_error_rate`; - const metricErrorRate = new Gauge(metricErrorRateName); - - return { - playName, - metricTrendName, - metricErrorRateName, - exec: ( - { - credential, - userName, - path, - asset, - tags, - }: { - credential: types.Credential; - path?: string; - userName: string; - asset: types.Asset; - tags?: { [key: string]: string }; - } - ): { - response: RefinedResponse; - tags: { [key: string]: string }; - } => { - tags = {play: playName, ...tags}; - - const response = api.dav.fileUpload({ - credential: credential as types.Credential, - asset, - userName, - tags, - path, - }); - - check(response, { - 'file upload status is 201': () => response.status === 201, - }, tags) || metricErrorRate.add(1, tags); - - metricTrend.add(response.timings.duration, tags) - - return { - response, - tags, - } - } +export class Upload extends Play { + constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { + super({name: name || `oc_${metricID}_play_dav_upload`}); } -}; -export const fileDelete = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { - const playName = name || `oc_${metricID}_play_dav_file_delete`; - const metricTrendName = `${playName}_trend`; - const metricTrend = new Trend(metricTrendName, true); - const metricErrorRateName = `${playName}_error_rate`; - const metricErrorRate = new Gauge(metricErrorRateName); - - return { - playName, - metricTrendName, - metricErrorRateName, - exec: ( - { - credential, - userName, - path, - tags, - }: { - credential: types.Credential; - userName: string; - path: string; - tags?: { [key: string]: string }; - } - ): { - response: RefinedResponse; - tags: { [key: string]: string }; - } => { - tags = {play: playName, ...tags}; - - const response = api.dav.fileDelete({ - credential: credential as types.Credential, - path, - userName, - tags, - }); - - check(response, { - 'file delete status is 204': () => response.status === 204, - }, tags) || metricErrorRate.add(1, tags); - - metricTrend.add(response.timings.duration, tags) - - return { - response, - tags, - } + public exec( + {credential, userName, path, asset, tags}: { + credential: types.Credential; + path?: string; + userName: string; + asset: types.Asset; + tags?: types.Tags; } + ): { response: RefinedResponse; tags: types.Tags; } { + tags = {...this.tags, ...tags}; + + const response = api.dav.Upload.exec({credential: credential as types.Credential, asset, userName, tags, path}); + + check(response, { + 'upload status is 201': () => response.status === 201, + }, tags) || this.metricErrorRate.add(1, tags); + + this.metricTrend.add(response.timings.duration, tags) + + return {response, tags} } -}; +} -export const fileDownload = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { - const playName = name || `oc_${metricID}_play_dav_file_download`; - const metricTrendName = `${playName}_trend`; - const metricTrend = new Trend(metricTrendName, true); - const metricErrorRateName = `${playName}_error_rate`; - const metricErrorRate = new Gauge(metricErrorRateName); +export class Delete extends Play { + constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { + super({name: name || `oc_${metricID}_play_dav_delete`}); + } - return { - playName, - metricTrendName, - metricErrorRateName, - exec: ( - { - credential, - userName, - path, - tags, - }: { - credential: types.Credential; - userName: string; - path: string; - tags?: { [key: string]: string }; - } - ): { - response: RefinedResponse; - tags: { [key: string]: string }; - } => { - tags = {play: playName, ...tags}; - - const response = api.dav.fileDownload({ - credential: credential as types.Credential, - path, - userName, - tags, - }); - - check(response, { - 'file download status is 200': () => response.status === 200, - }, tags) || metricErrorRate.add(1, tags); - - metricTrend.add(response.timings.duration, tags) - - return { - response, - tags, - } + public exec( + {credential, userName, path, tags}: { + credential: types.Credential; + path: string; + userName: string; + tags?: types.Tags; } + ): { response: RefinedResponse; tags: types.Tags; } { + tags = {...this.tags, ...tags}; + + const response = api.dav.Delete.exec({credential: credential as types.Credential, userName, tags, path}); + + check(response, { + 'delete status is 204': () => response.status === 204, + }, tags) || this.metricErrorRate.add(1, tags); + + this.metricTrend.add(response.timings.duration, tags) + + return {response, tags} } -}; +} -export const folderCreate = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { - const playName = name || `oc_${metricID}_play_dav_folder_create`; - const metricTrendName = `${playName}_trend`; - const metricTrend = new Trend(metricTrendName, true); - const metricErrorRateName = `${playName}_error_rate`; - const metricErrorRate = new Gauge(metricErrorRateName); +export class Download extends Play { + constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { + super({name: name || `oc_${metricID}_play_dav_download`}); + } - return { - playName, - metricTrendName, - metricErrorRateName, - exec: ( - { - credential, - userName, - path, - tags, - }: { - credential: types.Credential; - userName: string; - path: string; - tags?: { [key: string]: string }; - } - ): { - response: RefinedResponse; - tags: { [key: string]: string }; - } => { - tags = {play: playName, ...tags}; - - const response = api.dav.folderCreate({ - credential: credential as types.Credential, - path, - userName, - tags, - }); - - check(response, { - 'folder create status is 201': () => response.status === 201, - }, tags) || metricErrorRate.add(1, tags); - - metricTrend.add(response.timings.duration, tags) - - return { - response, - tags, - } + public exec( + {credential, userName, path, tags}: { + credential: types.Credential; + path: string; + userName: string; + tags?: types.Tags; } + ): { response: RefinedResponse; tags: types.Tags; } { + tags = {...this.tags, ...tags}; + + const response = api.dav.Download.exec({credential: credential as types.Credential, userName, tags, path}); + + check(response, { + 'download status is 200': () => response.status === 200, + }, tags) || this.metricErrorRate.add(1, tags); + + this.metricTrend.add(response.timings.duration, tags) + + return {response, tags} } -}; +} -export const folderDelete = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { - const playName = name || `oc_${metricID}_play_dav_folder_delete`; - const metricTrendName = `${playName}_trend`; - const metricTrend = new Trend(metricTrendName, true); - const metricErrorRateName = `${playName}_error_rate`; - const metricErrorRate = new Gauge(metricErrorRateName); +export class Create extends Play { + constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { + super({name: name || `oc_${metricID}_play_dav_create`}); + } - return { - playName, - metricTrendName, - metricErrorRateName, - exec: ( - { - credential, - userName, - path, - tags, - }: { - credential: types.Credential; - userName: string; - path: string; - tags?: { [key: string]: string }; - } - ): { - response: RefinedResponse; - tags: { [key: string]: string }; - } => { - tags = {play: playName, ...tags}; - - const response = api.dav.folderDelete({ - credential: credential as types.Credential, - path, - userName, - tags, - }); - - check(response, { - 'folder delete status is 204': () => response.status === 204, - }, tags) || metricErrorRate.add(1, tags); - - metricTrend.add(response.timings.duration, tags) - - return { - response, - tags, - } + public exec( + {credential, userName, path, tags}: { + credential: types.Credential; + path: string; + userName: string; + tags?: types.Tags; } + ): { response: RefinedResponse; tags: types.Tags; } { + tags = {...this.tags, ...tags}; + + const response = api.dav.Create.exec({credential: credential as types.Credential, userName, tags, path}); + + check(response, { + 'create status is 201': () => response.status === 201, + }, tags) || this.metricErrorRate.add(1, tags); + + this.metricTrend.add(response.timings.duration, tags) + + return {response, tags} } -}; +} -export const propfind = ({name, metricID = 'default'}: { name?: string; metricID?: string; }) => { - const playName = name || `oc_${metricID}_play_dav_propfind`; - const metricTrendName = `${playName}_trend`; - const metricTrend = new Trend(metricTrendName, true); - const metricErrorRateName = `${playName}_error_rate`; - const metricErrorRate = new Gauge(metricErrorRateName); +export class Propfind extends Play { + constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { + super({name: name || `oc_${metricID}_play_dav_propfind`}); + } - return { - playName, - metricTrendName, - metricErrorRateName, - exec: ( - { - credential, - userName, - path, - tags, - }: { - credential: types.Credential; - userName: string; - path?: string; - tags?: { [key: string]: string }; - } - ): { - response: RefinedResponse; - tags: { [key: string]: string }; - } => { - tags = {play: playName, ...tags}; - - const response = api.dav.propfind({ - credential: credential as types.Credential, - path, - userName, - tags, - }); - - check(response, { - 'propfind status is 207': () => response.status === 207, - }, tags) || metricErrorRate.add(1, tags); - - metricTrend.add(response.timings.duration, tags) - - return { - response, - tags, - } + public exec( + {credential, userName, path, tags}: { + credential: types.Credential; + path?: string; + userName: string; + tags?: types.Tags; } + ): { response: RefinedResponse; tags: types.Tags; } { + tags = {...this.tags, ...tags}; + + const response = api.dav.Propfind.exec({credential: credential as types.Credential, userName, tags, path}); + + check(response, { + 'propfind status is 207': () => response.status === 207, + }, tags) || this.metricErrorRate.add(1, tags); + + this.metricTrend.add(response.timings.duration, tags) + + return {response, tags} } -}; \ No newline at end of file +} \ No newline at end of file diff --git a/tests/k6/src/lib/playbook/playbook.ts b/tests/k6/src/lib/playbook/playbook.ts new file mode 100644 index 000000000..e85dd292a --- /dev/null +++ b/tests/k6/src/lib/playbook/playbook.ts @@ -0,0 +1,19 @@ +import {Gauge, Trend} from "k6/metrics"; + +export class Play { + public readonly name: string; + public readonly metricTrendName: string; + public readonly metricErrorRateName: string; + public readonly metricTrend: Trend; + public readonly metricErrorRate: Gauge; + protected tags: { [key: string]: string }; + + constructor({name}: { name: string; }) { + this.name = name; + this.metricTrendName = `${this.name}_trend`; + this.metricErrorRateName = `${this.name}_error_rate`; + this.metricTrend = new Trend(this.metricTrendName, true); + this.metricErrorRate = new Gauge(this.metricErrorRateName); + this.tags = {play: this.name} + } +} \ No newline at end of file diff --git a/tests/k6/src/lib/types.ts b/tests/k6/src/lib/types.ts index 8cecf6e40..bcd5cd808 100644 --- a/tests/k6/src/lib/types.ts +++ b/tests/k6/src/lib/types.ts @@ -23,4 +23,6 @@ export interface AuthProvider { credential: Credential } -export type AssetUnit = 'KB' | 'MB' | 'GB' \ No newline at end of file +export type AssetUnit = 'KB' | 'MB' | 'GB' + +export type Tags = { [key: string]: string } \ No newline at end of file diff --git a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts index 884b7b06e..e4e11794a 100644 --- a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts +++ b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts @@ -10,18 +10,18 @@ const files: { }[] = times(1000, () => ({size: 1, unit: 'KB'})) const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); const plays = { - fileUpload: playbook.dav.fileUpload({}), - propfind: playbook.dav.propfind({}), - fileDelete: playbook.dav.fileDelete({}), + davUpload: new playbook.dav.Upload({}), + davPropfind: new playbook.dav.Propfind({}), + davDelete: new playbook.dav.Delete({}), } export const options: Options = { insecureSkipTLSVerify: true, iterations: 3, vus: 1, thresholds: files.reduce((acc: any, c) => { - acc[`${plays.fileUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.propfind.metricTrendName}`] = [] - acc[`${plays.fileDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davPropfind.metricTrendName}`] = [] + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] return acc }, {}), }; @@ -38,7 +38,7 @@ export default (): void => { size: f.size, }) - plays.fileUpload.exec({ + plays.davUpload.exec({ credential, asset, userName: account.login, @@ -48,13 +48,13 @@ export default (): void => { filesUploaded.push({id, name: asset.name}) }) - plays.propfind.exec({ + plays.davPropfind.exec({ credential, userName: account.login, }) filesUploaded.forEach(f => { - plays.fileDelete.exec({ + plays.davDelete.exec({ credential, userName: account.login, path: f.name, diff --git a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts index 2af298381..097fda0b4 100644 --- a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts +++ b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts @@ -10,20 +10,20 @@ const files: { }[] = times(1000, () => ({size: 1, unit: 'KB'})) const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); const plays = { - fileUpload: playbook.dav.fileUpload({}), - propfind: playbook.dav.propfind({}), - folderCreate: playbook.dav.folderCreate({}), - folderDelete: playbook.dav.folderDelete({}), + davUpload: new playbook.dav.Upload({}), + davPropfind: new playbook.dav.Propfind({}), + davCreate: new playbook.dav.Create({}), + davDelete: new playbook.dav.Delete({}), } export const options: Options = { insecureSkipTLSVerify: true, iterations: 3, vus: 1, thresholds: files.reduce((acc: any, c) => { - acc[`${plays.fileUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.propfind.metricTrendName}`] = [] - acc[`${plays.folderCreate.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.folderDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davPropfind.metricTrendName}`] = [] + acc[`${plays.davCreate.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] return acc }, {}), }; @@ -43,7 +43,7 @@ export default (): void => { const folder = times(utils.randomNumber({min: 1, max: 10}), () => utils.randomString()).reduce((acc: string[], c) => { acc.push(c) - plays.folderCreate.exec({ + plays.davCreate.exec({ credential, path: acc.join('/'), userName: account.login, @@ -54,7 +54,7 @@ export default (): void => { }, []).join('/') - plays.fileUpload.exec({ + plays.davUpload.exec({ credential, asset, path: folder, @@ -65,13 +65,13 @@ export default (): void => { filesUploaded.push({id, name: asset.name, folder}) }) - plays.propfind.exec({ + plays.davPropfind.exec({ credential, userName: account.login, }) filesUploaded.forEach(f => { - plays.folderDelete.exec({ + plays.davDelete.exec({ credential, userName: account.login, path: f.folder.split('/')[0], diff --git a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts index 299c95b70..b7ab3d182 100644 --- a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts +++ b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts @@ -14,18 +14,18 @@ const files: { ] const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); const plays = { - fileUpload: playbook.dav.fileUpload({}), - fileDownload: playbook.dav.fileDownload({}), - fileDelete: playbook.dav.fileDelete({}), + davUpload: new playbook.dav.Upload({}), + davDownload: new playbook.dav.Download({}), + davDelete: new playbook.dav.Delete({}), } export const options: Options = { insecureSkipTLSVerify: true, iterations: 3, vus: 1, thresholds: files.reduce((acc: any, c) => { - acc[`${plays.fileUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.fileDownload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.fileDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davDownload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] return acc }, {}), }; @@ -42,7 +42,7 @@ export default (): void => { size: f.size, }) - plays.fileUpload.exec({ + plays.davUpload.exec({ credential, asset, userName: account.login, @@ -53,7 +53,7 @@ export default (): void => { }) filesUploaded.forEach(f => { - plays.fileDownload.exec({ + plays.davDownload.exec({ credential, userName: account.login, path: f.name, @@ -62,7 +62,7 @@ export default (): void => { }) filesUploaded.forEach(f => { - plays.fileDelete.exec({ + plays.davDelete.exec({ credential, userName: account.login, path: f.name, diff --git a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts index 02d22570d..82ef129a6 100644 --- a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts +++ b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts @@ -16,18 +16,18 @@ const files: { ] const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); const plays = { - fileUpload: playbook.dav.fileUpload({}), - fileDownload: playbook.dav.fileDownload({}), - fileDelete: playbook.dav.fileDelete({}), + davUpload: new playbook.dav.Upload({}), + davDownload: new playbook.dav.Download({}), + davDelete: new playbook.dav.Delete({}), } export const options: Options = { insecureSkipTLSVerify: true, iterations: 3, vus: 1, thresholds: files.reduce((acc: any, c) => { - acc[`${plays.fileUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.fileDownload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.fileDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davDownload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] return acc }, {}), }; @@ -45,7 +45,7 @@ export default (): void => { size: f.size, }) - plays.fileUpload.exec({ + plays.davUpload.exec({ credential, asset, userName: account.login, @@ -56,7 +56,7 @@ export default (): void => { }) filesUploaded.forEach(f => { - plays.fileDownload.exec({ + plays.davDownload.exec({ credential, userName: account.login, path: f.name, @@ -65,7 +65,7 @@ export default (): void => { }) filesUploaded.forEach(f => { - plays.fileDelete.exec({ + plays.davDelete.exec({ credential, userName: account.login, path: f.name, From de34fbb995f1018162890739bd9eeccd7f03408a Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 3 Dec 2020 11:45:38 +0100 Subject: [PATCH 09/27] add linting add prettier add concurrent users upload test add api and play for users remove some code smell --- .gitignore | 2 +- ocis/go.mod | 1 + tests/k6/.eslintignore | 2 + tests/k6/.eslintrc | 14 + tests/k6/.prettierrc | 7 + tests/k6/package.json | 29 +- tests/k6/src/lib/api/api.ts | 63 +- tests/k6/src/lib/api/dav.ts | 78 ++- tests/k6/src/lib/api/index.ts | 5 +- tests/k6/src/lib/api/users.ts | 46 ++ tests/k6/src/lib/auth.ts | 95 ++- tests/k6/src/lib/defaults.ts | 11 +- tests/k6/src/lib/index.ts | 12 +- tests/k6/src/lib/playbook/dav.ts | 216 ++++--- tests/k6/src/lib/playbook/index.ts | 3 +- tests/k6/src/lib/playbook/playbook.ts | 8 +- tests/k6/src/lib/playbook/users.ts | 73 +++ tests/k6/src/lib/types.ts | 14 +- tests/k6/src/lib/utils.ts | 69 ++- .../issue/jira/ocis/1007/concurrent-users.ts | 73 +++ .../jira/ocis/1007/folder-listing/flat.ts | 55 +- .../jira/ocis/1007/folder-listing/nested.ts | 82 +-- .../1007/simple-down-and-upload/many-small.ts | 66 +- .../1007/simple-down-and-upload/some-large.ts | 68 +- tests/k6/yarn.lock | 581 +++++++++++++----- 25 files changed, 1138 insertions(+), 535 deletions(-) create mode 100644 tests/k6/.eslintignore create mode 100644 tests/k6/.eslintrc create mode 100644 tests/k6/.prettierrc create mode 100644 tests/k6/src/lib/api/users.ts create mode 100644 tests/k6/src/lib/playbook/users.ts create mode 100644 tests/k6/src/test/issue/jira/ocis/1007/concurrent-users.ts diff --git a/.gitignore b/.gitignore index 42c117c64..8facee1ab 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ node_modules/ .idea -*/yarn-error.log +yarn-error.log # Konnectd konnectd/assets/identifier diff --git a/ocis/go.mod b/ocis/go.mod index 01ca7ada1..3cdf426f4 100644 --- a/ocis/go.mod +++ b/ocis/go.mod @@ -53,4 +53,5 @@ replace ( github.com/owncloud/ocis/thumbnails => ../thumbnails github.com/owncloud/ocis/webdav => ../webdav google.golang.org/grpc => google.golang.org/grpc v1.26.0 + github.com/cs3org/reva => ../../../cs3org/reva ) diff --git a/tests/k6/.eslintignore b/tests/k6/.eslintignore new file mode 100644 index 000000000..76add878f --- /dev/null +++ b/tests/k6/.eslintignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/tests/k6/.eslintrc b/tests/k6/.eslintrc new file mode 100644 index 000000000..a68b15172 --- /dev/null +++ b/tests/k6/.eslintrc @@ -0,0 +1,14 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module" + }, + "extends": [ + "plugin:@typescript-eslint/recommended", + "prettier/@typescript-eslint", + "plugin:prettier/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/tests/k6/.prettierrc b/tests/k6/.prettierrc new file mode 100644 index 000000000..c5d3c0a5a --- /dev/null +++ b/tests/k6/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": true, + "trailingComma": "all", + "singleQuote": true, + "printWidth": 120, + "tabWidth": 4 +} \ No newline at end of file diff --git a/tests/k6/package.json b/tests/k6/package.json index 3dcacc9d7..980ce8bed 100644 --- a/tests/k6/package.json +++ b/tests/k6/package.json @@ -4,9 +4,20 @@ "main": "index.js", "scripts": { "clean": "rm -rf ./dist", + "lint": "eslint './src/**/*.ts' --fix", "build": "rollup -c", "build:w": "rollup -c -w" }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "*.{ts}": [ + "eslint --fix" + ] + }, "devDependencies": { "@babel/core": "^7.9.0", "@babel/polyfill": "^7.12.1", @@ -18,26 +29,26 @@ "@rollup/plugin-json": "^4.0.3", "@rollup/plugin-node-resolve": "^7.1.3", "@rollup/pluginutils": "^4.1.0", - "@types/faker": "^5.1.4", - "@types/jest": "^25.2.1", "@types/k6": "^0.28.2", "@types/lodash": "^4.14.165", - "@typescript-eslint/eslint-plugin": "^2.29.0", - "@typescript-eslint/parser": "^2.29.0", + "@typescript-eslint/eslint-plugin": "^4.9.0", + "@typescript-eslint/parser": "^4.9.0", "babel-plugin-lodash": "^3.3.4", - "eslint": "^6.8.0", - "eslint-config-prettier": "^6.11.0", + "eslint": "^7.14.0", + "eslint-config-prettier": "^6.15.0", "eslint-plugin-jest": "^23.8.2", - "eslint-plugin-prettier": "^3.1.3", + "eslint-plugin-prettier": "^3.2.0", + "husky": "^4.3.0", "jest": "^25.4.0", "k6": "^0.0.0", "lint-staged": "^10.1.7", - "prettier": "^2.0.5", + "prettier": "^2.2.1", + "prettier-eslint": "^12.0.0", "rollup": "^2.7.2", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-multi-input": "^1.1.1", "rollup-plugin-terser": "^5.3.0", - "typescript": "^3.8.3" + "typescript": "^4.1.2" }, "dependencies": { "lodash": "^4.17.20", diff --git a/tests/k6/src/lib/api/api.ts b/tests/k6/src/lib/api/api.ts index 7ba632d1b..d09cc7466 100644 --- a/tests/k6/src/lib/api/api.ts +++ b/tests/k6/src/lib/api/api.ts @@ -1,41 +1,52 @@ import encoding from 'k6/encoding'; import * as types from '../types'; -import * as defaults from "../defaults"; -import {merge} from 'lodash'; -import http, {RefinedParams, RefinedResponse, RequestBody, ResponseType} from "k6/http"; +import * as defaults from '../defaults'; +import { merge } from 'lodash'; +import http, { RefinedParams, RefinedResponse, RequestBody, ResponseType } from 'k6/http'; +import { bytes } from 'k6'; -export const buildHeaders = ({credential}: { credential: types.Credential }): { [key: string]: string } => { +export const buildHeaders = ({ credential }: { credential?: types.Credential }): { [key: string]: string } => { const isOIDCGuard = (credential as types.Token).tokenType !== undefined; const authOIDC = credential as types.Token; const authBasic = credential as types.Account; return { - Authorization: isOIDCGuard ? `${authOIDC.tokenType} ${authOIDC.accessToken}` : `Basic ${encoding.b64encode(`${authBasic.login}:${authBasic.password}`)}`, - } -} + ...(credential && { + Authorization: isOIDCGuard + ? `${authOIDC.tokenType} ${authOIDC.accessToken}` + : `Basic ${encoding.b64encode(`${authBasic.login}:${authBasic.password}`)}`, + }), + }; +}; -export const buildURL = ({path}: { path: string }): string => { - return [ - defaults.ENV.HOST, - ...path.split('/').filter(Boolean) - ].join('/') -} +export const buildURL = ({ path }: { path: string }): string => { + return [defaults.ENV.HOST, ...path.split('/').filter(Boolean)].join('/'); +}; -export const request = ({method, path, body = {}, params = {}, credential}: { - method: 'PROPFIND' | 'PUT' | 'GET' | 'DELETE' | 'MKCOL', - path: string, +export const request = ({ + method, + path, + body = {}, + params = {}, + credential, +}: { + method: 'PROPFIND' | 'PUT' | 'GET' | 'POST' | 'DELETE' | 'MKCOL'; + path: string; credential: types.Credential; - body?: RequestBody | null, - params?: RefinedParams | null + body?: RequestBody | bytes | null; + params?: RefinedParams | null; }): RefinedResponse => { return http.request( method, - buildURL({path}), - body, - merge({ - headers: { - ...buildHeaders({credential}) - } - }, params) + buildURL({ path }), + body as never, + merge( + { + headers: { + ...buildHeaders({ credential }), + }, + }, + params, + ), ); -} \ No newline at end of file +}; diff --git a/tests/k6/src/lib/api/dav.ts b/tests/k6/src/lib/api/dav.ts index 722e3ad0b..ea74a2509 100644 --- a/tests/k6/src/lib/api/dav.ts +++ b/tests/k6/src/lib/api/dav.ts @@ -1,59 +1,111 @@ -import {RefinedResponse, ResponseType} from 'k6/http'; -import * as api from './api' +import { RefinedResponse, ResponseType } from 'k6/http'; +import * as api from './api'; import * as types from '../types'; export class Upload { - public static exec({credential, userName, path = '', asset, tags}: { + public static exec({ + credential, + userName, + path = '', + asset, + tags, + }: { credential: types.Credential; userName: string; asset: types.Asset; path?: string; tags?: types.Tags; }): RefinedResponse { - return api.request({method: 'PUT', credential, path: `/remote.php/dav/files/${userName}/${path}/${asset.name}`, params: {tags}, body: asset.bytes as any}) + return api.request({ + method: 'PUT', + credential, + path: `/remote.php/dav/files/${userName}/${path}/${asset.name}`, + params: { tags }, + body: asset.bytes, + }); } } export class Download { - public static exec({credential, userName, path, tags}: { + public static exec({ + credential, + userName, + path, + tags, + }: { credential: types.Credential; userName: string; path: string; tags?: types.Tags; }): RefinedResponse { - return api.request({method: 'GET', credential, path: `/remote.php/dav/files/${userName}/${path}`, params: {tags}}) + return api.request({ + method: 'GET', + credential, + path: `/remote.php/dav/files/${userName}/${path}`, + params: { tags }, + }); } } export class Delete { - public static exec({credential, userName, path, tags}: { + public static exec({ + credential, + userName, + path, + tags, + }: { credential: types.Credential; userName: string; path: string; tags?: types.Tags; }): RefinedResponse { - return api.request({method: 'DELETE', credential, path: `/remote.php/dav/files/${userName}/${path}`, params: {tags}}) + return api.request({ + method: 'DELETE', + credential, + path: `/remote.php/dav/files/${userName}/${path}`, + params: { tags }, + }); } } export class Create { - public static exec({credential, userName, path, tags}: { + public static exec({ + credential, + userName, + path, + tags, + }: { credential: types.Credential; userName: string; path: string; tags?: types.Tags; }): RefinedResponse { - return api.request({method: 'MKCOL', credential, path: `/remote.php/dav/files/${userName}/${path}`, params: {tags}}) + return api.request({ + method: 'MKCOL', + credential, + path: `/remote.php/dav/files/${userName}/${path}`, + params: { tags }, + }); } } export class Propfind { - public static exec({credential, userName, path = '', tags}: { + public static exec({ + credential, + userName, + path = '', + tags, + }: { credential: types.Credential; userName: string; path?: string; tags?: types.Tags; }): RefinedResponse { - return api.request({method: 'PROPFIND', credential, path: `/remote.php/dav/files/${userName}/${path}`, params: {tags}}) + return api.request({ + method: 'PROPFIND', + credential, + path: `/remote.php/dav/files/${userName}/${path}`, + params: { tags }, + }); } -} \ No newline at end of file +} diff --git a/tests/k6/src/lib/api/index.ts b/tests/k6/src/lib/api/index.ts index 9219d4ba2..cbc6d4d6d 100644 --- a/tests/k6/src/lib/api/index.ts +++ b/tests/k6/src/lib/api/index.ts @@ -1,2 +1,3 @@ -export * as api from './api' -export * as dav from './dav' +export * as api from './api'; +export * as dav from './dav'; +export * as users from './users'; diff --git a/tests/k6/src/lib/api/users.ts b/tests/k6/src/lib/api/users.ts new file mode 100644 index 000000000..75a0dbf24 --- /dev/null +++ b/tests/k6/src/lib/api/users.ts @@ -0,0 +1,46 @@ +import { RefinedResponse, ResponseType } from 'k6/http'; +import * as api from './api'; +import * as types from '../types'; + +export class Create { + public static exec({ + userName, + password, + email, + credential, + tags, + }: { + credential: types.Credential; + userName: string; + password: string; + email: string; + tags?: types.Tags; + }): RefinedResponse { + return api.request({ + method: 'POST', + credential, + path: `/ocs/v1.php/cloud/users`, + params: { tags }, + body: { userid: userName, password, email }, + }); + } +} + +export class Delete { + public static exec({ + userName, + credential, + tags, + }: { + credential: types.Credential; + userName: string; + tags?: types.Tags; + }): RefinedResponse { + return api.request({ + method: 'DELETE', + credential, + path: `/ocs/v1.php/cloud/users/${userName}`, + params: { tags }, + }); + } +} diff --git a/tests/k6/src/lib/auth.ts b/tests/k6/src/lib/auth.ts index 6622b4be7..3aa21e8bf 100644 --- a/tests/k6/src/lib/auth.ts +++ b/tests/k6/src/lib/auth.ts @@ -2,9 +2,8 @@ import * as defaults from './defaults'; import http from 'k6/http'; import queryString from 'query-string'; import * as types from './types'; -import {fail} from 'k6'; -import {get} from 'lodash' - +import { fail } from 'k6'; +import { get } from 'lodash'; export default class Factory { private provider!: types.AuthProvider; @@ -15,14 +14,14 @@ export default class Factory { if (defaults.ENV.OIDC_ENABLED) { this.provider = new OIDCProvider(account); - return + return; } this.provider = new AccountProvider(account); } public get credential(): types.Credential { - return this.provider.credential + return this.provider.credential; } } @@ -46,7 +45,7 @@ class OIDCProvider implements types.AuthProvider { private cache!: { validTo: Date; token: types.Token; - } + }; constructor(account: types.Account) { this.account = account; @@ -63,12 +62,12 @@ class OIDCProvider implements types.AuthProvider { const offset = 5; const d = new Date(); - d.setSeconds(d.getSeconds() + token.expiresIn - offset) + d.setSeconds(d.getSeconds() + token.expiresIn - offset); - return d + return d; })(), token, - } + }; } return this.cache.token; @@ -77,18 +76,16 @@ class OIDCProvider implements types.AuthProvider { private getContinueURI(): string { const logonResponse = http.post( this.logonUri, - JSON.stringify( - { - params: [this.account.login, this.account.password, '1'], - hello: { - scope: 'openid profile email', - client_id: 'phoenix', - redirect_uri: this.redirectUri, - flow: 'oidc' - }, - 'state': 'vp42cf' + JSON.stringify({ + params: [this.account.login, this.account.password, '1'], + hello: { + scope: 'openid profile email', + client_id: 'phoenix', + redirect_uri: this.redirectUri, + flow: 'oidc', }, - ), + state: 'vp42cf', + }), { headers: { 'Kopano-Konnect-XSRF': '1', @@ -107,53 +104,49 @@ class OIDCProvider implements types.AuthProvider { } private getCode(continueURI: string): string { - const authorizeUri = `${continueURI}?${ - queryString.stringify( - { - client_id: 'phoenix', - prompt: 'none', - redirect_uri: this.redirectUri, - response_mode: 'query', - response_type: 'code', - scope: 'openid profile email', - }, - ) - }`; - const authorizeResponse = http.get( - authorizeUri, - { - redirects: 0, - }, - ) + const authorizeUri = `${continueURI}?${queryString.stringify({ + client_id: 'phoenix', + prompt: 'none', + redirect_uri: this.redirectUri, + response_mode: 'query', + response_type: 'code', + scope: 'openid profile email', + })}`; + const authorizeResponse = http.get(authorizeUri, { + redirects: 0, + }); - const code = get(queryString.parseUrl(authorizeResponse.headers.Location), 'query.code') + const code = get(queryString.parseUrl(authorizeResponse.headers.Location), 'query.code'); if (authorizeResponse.status != 302 || !code) { fail(continueURI); } - return code + return code; } private getToken(code: string): types.Token { - const tokenResponse = http.post( - this.tokenUrl, - { - client_id: 'phoenix', - code, - redirect_uri: this.redirectUri, - grant_type: 'authorization_code' - } - ) + const tokenResponse = http.post(this.tokenUrl, { + client_id: 'phoenix', + code, + redirect_uri: this.redirectUri, + grant_type: 'authorization_code', + }); const token = { accessToken: get(tokenResponse.json(), 'access_token'), tokenType: get(tokenResponse.json(), 'token_type'), idToken: get(tokenResponse.json(), 'id_token'), expiresIn: get(tokenResponse.json(), 'expires_in'), - } + }; - if (tokenResponse.status != 200 || !token.accessToken || !token.tokenType || !token.idToken || !token.expiresIn) { + if ( + tokenResponse.status != 200 || + !token.accessToken || + !token.tokenType || + !token.idToken || + !token.expiresIn + ) { fail(this.tokenUrl); } diff --git a/tests/k6/src/lib/defaults.ts b/tests/k6/src/lib/defaults.ts index 4e2deac52..401a2f0d4 100644 --- a/tests/k6/src/lib/defaults.ts +++ b/tests/k6/src/lib/defaults.ts @@ -9,9 +9,14 @@ export class ENV { } export class ACCOUNTS { + public static readonly ADMIN = 'admin'; public static readonly EINSTEIN = 'einstein'; public static readonly RICHARD = 'richard'; - public static readonly ALL: { [key: string]: types.Account; } = { + public static readonly ALL: { [key: string]: types.Account } = { + admin: { + login: 'admin', + password: 'admin', + }, einstein: { login: 'einstein', password: 'relativity', @@ -20,5 +25,5 @@ export class ACCOUNTS { login: 'richard', password: 'superfluidity', }, - } -} \ No newline at end of file + }; +} diff --git a/tests/k6/src/lib/index.ts b/tests/k6/src/lib/index.ts index fe9d94422..056deecb9 100644 --- a/tests/k6/src/lib/index.ts +++ b/tests/k6/src/lib/index.ts @@ -1,6 +1,6 @@ -export * as api from './api' -export * as playbook from './playbook' -export * as auth from './auth' -export * as defaults from './defaults' -export * as types from './types' -export * as utils from './utils' +export * as api from './api'; +export * as playbook from './playbook'; +export * as auth from './auth'; +export * as defaults from './defaults'; +export * as types from './types'; +export * as utils from './utils'; diff --git a/tests/k6/src/lib/playbook/dav.ts b/tests/k6/src/lib/playbook/dav.ts index 07f97d3e4..ec9996dce 100644 --- a/tests/k6/src/lib/playbook/dav.ts +++ b/tests/k6/src/lib/playbook/dav.ts @@ -1,141 +1,177 @@ import * as api from '../api'; -import {check} from 'k6'; +import { check } from 'k6'; import * as types from '../types'; -import {RefinedResponse, ResponseType} from 'k6/http'; -import {Play} from "./playbook"; +import { RefinedResponse, ResponseType } from 'k6/http'; +import { Play } from './playbook'; export class Upload extends Play { - constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { - super({name: name || `oc_${metricID}_play_dav_upload`}); + constructor({ name, metricID = 'default' }: { name?: string; metricID?: string } = {}) { + super({ name: name || `oc_${metricID}_play_dav_upload` }); } - public exec( - {credential, userName, path, asset, tags}: { - credential: types.Credential; - path?: string; - userName: string; - asset: types.Asset; - tags?: types.Tags; - } - ): { response: RefinedResponse; tags: types.Tags; } { - tags = {...this.tags, ...tags}; + public exec({ + credential, + userName, + path, + asset, + tags, + }: { + credential: types.Credential; + path?: string; + userName: string; + asset: types.Asset; + tags?: types.Tags; + }): { response: RefinedResponse; tags: types.Tags } { + tags = { ...this.tags, ...tags }; - const response = api.dav.Upload.exec({credential: credential as types.Credential, asset, userName, tags, path}); + const response = api.dav.Upload.exec({ credential: credential, asset, userName, tags, path }); - check(response, { - 'upload status is 201': () => response.status === 201, - }, tags) || this.metricErrorRate.add(1, tags); + check( + response, + { + 'dav upload status is 201': () => response.status === 201, + }, + tags, + ) || this.metricErrorRate.add(1, tags); - this.metricTrend.add(response.timings.duration, tags) + this.metricTrend.add(response.timings.duration, tags); - return {response, tags} + return { response, tags }; } } export class Delete extends Play { - constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { - super({name: name || `oc_${metricID}_play_dav_delete`}); + constructor({ name, metricID = 'default' }: { name?: string; metricID?: string } = {}) { + super({ name: name || `oc_${metricID}_play_dav_delete` }); } - public exec( - {credential, userName, path, tags}: { - credential: types.Credential; - path: string; - userName: string; - tags?: types.Tags; - } - ): { response: RefinedResponse; tags: types.Tags; } { - tags = {...this.tags, ...tags}; + public exec({ + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + path: string; + userName: string; + tags?: types.Tags; + }): { response: RefinedResponse; tags: types.Tags } { + tags = { ...this.tags, ...tags }; - const response = api.dav.Delete.exec({credential: credential as types.Credential, userName, tags, path}); + const response = api.dav.Delete.exec({ credential: credential, userName, tags, path }); - check(response, { - 'delete status is 204': () => response.status === 204, - }, tags) || this.metricErrorRate.add(1, tags); + check( + response, + { + 'dav delete status is 204': () => response.status === 204, + }, + tags, + ) || this.metricErrorRate.add(1, tags); - this.metricTrend.add(response.timings.duration, tags) + this.metricTrend.add(response.timings.duration, tags); - return {response, tags} + return { response, tags }; } } export class Download extends Play { - constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { - super({name: name || `oc_${metricID}_play_dav_download`}); + constructor({ name, metricID = 'default' }: { name?: string; metricID?: string } = {}) { + super({ name: name || `oc_${metricID}_play_dav_download` }); } - public exec( - {credential, userName, path, tags}: { - credential: types.Credential; - path: string; - userName: string; - tags?: types.Tags; - } - ): { response: RefinedResponse; tags: types.Tags; } { - tags = {...this.tags, ...tags}; + public exec({ + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + path: string; + userName: string; + tags?: types.Tags; + }): { response: RefinedResponse; tags: types.Tags } { + tags = { ...this.tags, ...tags }; - const response = api.dav.Download.exec({credential: credential as types.Credential, userName, tags, path}); + const response = api.dav.Download.exec({ credential: credential, userName, tags, path }); - check(response, { - 'download status is 200': () => response.status === 200, - }, tags) || this.metricErrorRate.add(1, tags); + check( + response, + { + 'dav download status is 200': () => response.status === 200, + }, + tags, + ) || this.metricErrorRate.add(1, tags); - this.metricTrend.add(response.timings.duration, tags) + this.metricTrend.add(response.timings.duration, tags); - return {response, tags} + return { response, tags }; } } export class Create extends Play { - constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { - super({name: name || `oc_${metricID}_play_dav_create`}); + constructor({ name, metricID = 'default' }: { name?: string; metricID?: string } = {}) { + super({ name: name || `oc_${metricID}_play_dav_create` }); } - public exec( - {credential, userName, path, tags}: { - credential: types.Credential; - path: string; - userName: string; - tags?: types.Tags; - } - ): { response: RefinedResponse; tags: types.Tags; } { - tags = {...this.tags, ...tags}; + public exec({ + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + path: string; + userName: string; + tags?: types.Tags; + }): { response: RefinedResponse; tags: types.Tags } { + tags = { ...this.tags, ...tags }; - const response = api.dav.Create.exec({credential: credential as types.Credential, userName, tags, path}); + const response = api.dav.Create.exec({ credential: credential, userName, tags, path }); - check(response, { - 'create status is 201': () => response.status === 201, - }, tags) || this.metricErrorRate.add(1, tags); + check( + response, + { + 'dav create status is 201': () => response.status === 201, + }, + tags, + ) || this.metricErrorRate.add(1, tags); - this.metricTrend.add(response.timings.duration, tags) + this.metricTrend.add(response.timings.duration, tags); - return {response, tags} + return { response, tags }; } } export class Propfind extends Play { - constructor({name, metricID = 'default'}: { name?: string; metricID?: string; }) { - super({name: name || `oc_${metricID}_play_dav_propfind`}); + constructor({ name, metricID = 'default' }: { name?: string; metricID?: string } = {}) { + super({ name: name || `oc_${metricID}_play_dav_propfind` }); } - public exec( - {credential, userName, path, tags}: { - credential: types.Credential; - path?: string; - userName: string; - tags?: types.Tags; - } - ): { response: RefinedResponse; tags: types.Tags; } { - tags = {...this.tags, ...tags}; + public exec({ + credential, + userName, + path, + tags, + }: { + credential: types.Credential; + path?: string; + userName: string; + tags?: types.Tags; + }): { response: RefinedResponse; tags: types.Tags } { + tags = { ...this.tags, ...tags }; - const response = api.dav.Propfind.exec({credential: credential as types.Credential, userName, tags, path}); + const response = api.dav.Propfind.exec({ credential: credential, userName, tags, path }); - check(response, { - 'propfind status is 207': () => response.status === 207, - }, tags) || this.metricErrorRate.add(1, tags); + check( + response, + { + 'dav propfind status is 207': () => response.status === 207, + }, + tags, + ) || this.metricErrorRate.add(1, tags); - this.metricTrend.add(response.timings.duration, tags) + this.metricTrend.add(response.timings.duration, tags); - return {response, tags} + return { response, tags }; } -} \ No newline at end of file +} diff --git a/tests/k6/src/lib/playbook/index.ts b/tests/k6/src/lib/playbook/index.ts index 3d7e48162..7c93922e3 100644 --- a/tests/k6/src/lib/playbook/index.ts +++ b/tests/k6/src/lib/playbook/index.ts @@ -1 +1,2 @@ -export * as dav from './dav' \ No newline at end of file +export * as dav from './dav'; +export * as users from './users'; diff --git a/tests/k6/src/lib/playbook/playbook.ts b/tests/k6/src/lib/playbook/playbook.ts index e85dd292a..f42c5f88b 100644 --- a/tests/k6/src/lib/playbook/playbook.ts +++ b/tests/k6/src/lib/playbook/playbook.ts @@ -1,4 +1,4 @@ -import {Gauge, Trend} from "k6/metrics"; +import { Gauge, Trend } from 'k6/metrics'; export class Play { public readonly name: string; @@ -8,12 +8,12 @@ export class Play { public readonly metricErrorRate: Gauge; protected tags: { [key: string]: string }; - constructor({name}: { name: string; }) { + constructor({ name }: { name: string }) { this.name = name; this.metricTrendName = `${this.name}_trend`; this.metricErrorRateName = `${this.name}_error_rate`; this.metricTrend = new Trend(this.metricTrendName, true); this.metricErrorRate = new Gauge(this.metricErrorRateName); - this.tags = {play: this.name} + this.tags = { play: this.name }; } -} \ No newline at end of file +} diff --git a/tests/k6/src/lib/playbook/users.ts b/tests/k6/src/lib/playbook/users.ts new file mode 100644 index 000000000..ae228ef50 --- /dev/null +++ b/tests/k6/src/lib/playbook/users.ts @@ -0,0 +1,73 @@ +import * as api from '../api'; +import { check } from 'k6'; +import * as types from '../types'; +import { RefinedResponse, ResponseType } from 'k6/http'; +import { Play } from './playbook'; + +export class Create extends Play { + constructor({ name, metricID = 'default' }: { name?: string; metricID?: string } = {}) { + super({ name: name || `oc_${metricID}_play_users_create` }); + } + + public exec({ + credential, + userName, + password, + email, + tags, + }: { + credential: types.Credential; + userName: string; + password: string; + email: string; + tags?: types.Tags; + }): { response: RefinedResponse; tags: types.Tags } { + tags = { ...this.tags, ...tags }; + + const response = api.users.Create.exec({ credential: credential, userName, password, tags, email }); + + check( + response, + { + 'users create status is 200': () => response.status === 200, + }, + tags, + ) || this.metricErrorRate.add(1, tags); + + this.metricTrend.add(response.timings.duration, tags); + + return { response, tags }; + } +} + +export class Delete extends Play { + constructor({ name, metricID = 'default' }: { name?: string; metricID?: string } = {}) { + super({ name: name || `oc_${metricID}_play_users_delete` }); + } + + public exec({ + credential, + userName, + tags, + }: { + credential: types.Credential; + userName: string; + tags?: types.Tags; + }): { response: RefinedResponse; tags: types.Tags } { + tags = { ...this.tags, ...tags }; + + const response = api.users.Delete.exec({ credential: credential, userName, tags }); + + check( + response, + { + 'users delete status is 200': () => response.status === 200, + }, + tags, + ) || this.metricErrorRate.add(1, tags); + + this.metricTrend.add(response.timings.duration, tags); + + return { response, tags }; + } +} diff --git a/tests/k6/src/lib/types.ts b/tests/k6/src/lib/types.ts index bcd5cd808..34a831234 100644 --- a/tests/k6/src/lib/types.ts +++ b/tests/k6/src/lib/types.ts @@ -1,4 +1,4 @@ -import {bytes} from 'k6'; +import { bytes } from 'k6'; export interface Asset { bytes: bytes; @@ -13,16 +13,16 @@ export interface Token { } export interface Account { - login: string - password: string + login: string; + password: string; } -export type Credential = Token | Account +export type Credential = Token | Account; export interface AuthProvider { - credential: Credential + credential: Credential; } -export type AssetUnit = 'KB' | 'MB' | 'GB' +export type Tags = { [key: string]: string }; -export type Tags = { [key: string]: string } \ No newline at end of file +export declare type AssetUnit = 'KB' | 'MB' | 'GB'; diff --git a/tests/k6/src/lib/utils.ts b/tests/k6/src/lib/utils.ts index 85f0599a6..5fa7ec79b 100644 --- a/tests/k6/src/lib/utils.ts +++ b/tests/k6/src/lib/utils.ts @@ -1,57 +1,60 @@ -import {bytes} from 'k6'; -import {randomBytes as k6_randomBytes} from 'k6/crypto'; +import { bytes } from 'k6'; +import { randomBytes as k6_randomBytes } from 'k6/crypto'; import * as defaults from './defaults'; import * as types from './types'; -export const randomNumber = ({min, max}: { min: number; max: number; }): number => { +export const randomNumber = ({ min, max }: { min: number; max: number }): number => { return Math.random() * (max - min) + min; -} +}; -export const randomString = (): string => { - return Math.random().toString(20).substr(2) -} +export const randomString = ({ length = 10 }: { length?: number } = {}): string => { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; -export const buildAccount = ({login = defaults.ACCOUNTS.EINSTEIN}: { login: string; }): types.Account => { + let str = ''; + for (let i = 0; i < length; i++) { + str += chars.charAt(Math.floor(Math.random() * chars.length)); + } + + return str; +}; + +export const buildAccount = ({ login = defaults.ACCOUNTS.EINSTEIN }: { login: string }): types.Account => { if (defaults.ENV.LOGIN && defaults.ENV.PASSWORD) { return { login: defaults.ENV.LOGIN, password: defaults.ENV.PASSWORD, - } + }; } return defaults.ACCOUNTS.ALL[login]; -} - -export const buildAsset = ( - { - name = 'dummy.zip', - size = 1, - unit = 'MB', - }: { - name?: string; - size?: number; - unit?: types.AssetUnit; - } -): types.Asset => { +}; +export const buildAsset = ({ + name = 'dummy.zip', + size = 50, + unit = 'KB', +}: { + name?: string; + size?: number; + unit?: types.AssetUnit; +}): types.Asset => { const gen = { KB: (s: number): bytes => { - return k6_randomBytes(s * 1024) + return k6_randomBytes(s * 1024); }, MB: (s: number): bytes => { - return gen.KB(s * 1024) + return gen.KB(s * 1024); }, GB: (s: number): bytes => { - return gen.MB(s * 1024) + return gen.MB(s * 1024); }, - } + }; - const fileBaseName = name.split('/').reverse()[0] - const fileName = fileBaseName.split('.')[0] - const fileExtension = fileBaseName.split('.').reverse()[0] || 'zip' + const fileBaseName = name.split('/').reverse()[0]; + const fileName = fileBaseName.split('.')[0]; + const fileExtension = fileBaseName.split('.').reverse()[0] || 'zip'; return { - name: `${fileName}-${__VU}-${__ITER}-${size}-${unit}-${randomString()}.${fileExtension}`, + name: `${fileName}-${__VU}-${__ITER}-${unit}-${size}-${randomString()}.${fileExtension}`, bytes: gen[unit](size), - } -} - + }; +}; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/concurrent-users.ts b/tests/k6/src/test/issue/jira/ocis/1007/concurrent-users.ts new file mode 100644 index 000000000..65a01ec48 --- /dev/null +++ b/tests/k6/src/test/issue/jira/ocis/1007/concurrent-users.ts @@ -0,0 +1,73 @@ +import { Options, Threshold } from 'k6/options'; +import { utils, auth, defaults, playbook, types } from '../../../../../lib'; + +const files: Array<{ + size: number; + unit: types.AssetUnit; +}> = [ + { size: 50, unit: 'KB' }, + { size: 500, unit: 'KB' }, + { size: 5, unit: 'MB' }, + { size: 50, unit: 'MB' }, +]; +const adminAuthFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.ADMIN })); +const plays = { + usersCreate: new playbook.users.Create(), + usersDelete: new playbook.users.Delete(), + davUpload: new playbook.dav.Upload(), + davDelete: new playbook.dav.Delete(), +}; +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 10, + vus: 10, + thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + return acc; + }, {}), +}; + +export default (): void => { + const userName: string = utils.randomString(); + const password: string = utils.randomString(); + + plays.usersCreate.exec({ + userName, + password, + email: `${userName}@owncloud.com`, + credential: adminAuthFactory.credential, + }); + const userAuthFactory = new auth.default({ login: userName, password }); + const filesUploaded: { id: string; name: string }[] = []; + + files.forEach((f) => { + const id = f.unit + f.size.toString(); + + const asset = utils.buildAsset({ + name: `${userName}-dummy.zip`, + unit: f.unit, + size: f.size, + }); + + plays.davUpload.exec({ + credential: userAuthFactory.credential, + asset, + userName, + tags: { asset: id }, + }); + + filesUploaded.push({ id, name: asset.name }); + }); + + filesUploaded.forEach((f) => { + plays.davDelete.exec({ + credential: userAuthFactory.credential, + userName: userAuthFactory.account.login, + path: f.name, + tags: { asset: f.id }, + }); + }); + + plays.usersDelete.exec({ userName: userName, credential: adminAuthFactory.credential }); +}; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts index e4e11794a..656ee3f56 100644 --- a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts +++ b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts @@ -1,64 +1,63 @@ -import {Options} from "k6/options"; -import {utils, auth, defaults, playbook} from '../../../../../../lib' -import {times} from 'lodash' +import { Options, Threshold } from 'k6/options'; +import { utils, auth, defaults, playbook, types } from '../../../../../../lib'; +import { times } from 'lodash'; // put 1000 files into one dir and run a 'PROPFIND' through API const files: { size: number; - unit: any; -}[] = times(1000, () => ({size: 1, unit: 'KB'})) -const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); + unit: types.AssetUnit; +}[] = times(1000, () => ({ size: 1, unit: 'KB' })); +const authFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); const plays = { - davUpload: new playbook.dav.Upload({}), - davPropfind: new playbook.dav.Propfind({}), - davDelete: new playbook.dav.Delete({}), -} + davUpload: new playbook.dav.Upload(), + davPropfind: new playbook.dav.Propfind(), + davDelete: new playbook.dav.Delete(), +}; export const options: Options = { insecureSkipTLSVerify: true, iterations: 3, vus: 1, - thresholds: files.reduce((acc: any, c) => { - acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.davPropfind.metricTrendName}`] = [] - acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - return acc + thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + return acc; }, {}), }; export default (): void => { - const filesUploaded: { id: string, name: string, }[] = [] - const {account, credential} = authFactory; + const filesUploaded: { id: string; name: string }[] = []; + const { account, credential } = authFactory; - files.forEach(f => { + files.forEach((f) => { const id = f.unit + f.size.toString(); const asset = utils.buildAsset({ name: `${account.login}-dummy.zip`, - unit: f.unit as any, + unit: f.unit, size: f.size, - }) + }); plays.davUpload.exec({ credential, asset, userName: account.login, - tags: {asset: id}, + tags: { asset: id }, }); - filesUploaded.push({id, name: asset.name}) - }) + filesUploaded.push({ id, name: asset.name }); + }); plays.davPropfind.exec({ credential, userName: account.login, - }) + }); - filesUploaded.forEach(f => { + filesUploaded.forEach((f) => { plays.davDelete.exec({ credential, userName: account.login, path: f.name, - tags: {asset: f.id}, + tags: { asset: f.id }, }); - }) -} \ No newline at end of file + }); +}; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts index 097fda0b4..c5a33af17 100644 --- a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts +++ b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts @@ -1,81 +1,81 @@ -import {Options} from "k6/options"; -import {utils, auth, defaults, playbook} from '../../../../../../lib' -import {times} from 'lodash' +import { Options, Threshold } from 'k6/options'; +import { utils, auth, defaults, playbook, types } from '../../../../../../lib'; +import { times } from 'lodash'; // Unpack standard data tarball, run PROPFIND on each dir const files: { size: number; - unit: any; -}[] = times(1000, () => ({size: 1, unit: 'KB'})) -const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); + unit: types.AssetUnit; +}[] = times(1000, () => ({ size: 1, unit: 'KB' })); +const authFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); const plays = { - davUpload: new playbook.dav.Upload({}), - davPropfind: new playbook.dav.Propfind({}), - davCreate: new playbook.dav.Create({}), - davDelete: new playbook.dav.Delete({}), -} + davUpload: new playbook.dav.Upload(), + davPropfind: new playbook.dav.Propfind(), + davCreate: new playbook.dav.Create(), + davDelete: new playbook.dav.Delete(), +}; export const options: Options = { insecureSkipTLSVerify: true, iterations: 3, vus: 1, - thresholds: files.reduce((acc: any, c) => { - acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.davPropfind.metricTrendName}`] = [] - acc[`${plays.davCreate.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - return acc + thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davCreate.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + return acc; }, {}), }; export default (): void => { - const filesUploaded: { id: string, name: string, folder: string }[] = [] - const {account, credential} = authFactory; + const filesUploaded: { id: string; name: string; folder: string }[] = []; + const { account, credential } = authFactory; - files.forEach(f => { + files.forEach((f) => { const id = f.unit + f.size.toString(); const asset = utils.buildAsset({ name: `${account.login}-dummy.zip`, - unit: f.unit as any, + unit: f.unit, size: f.size, - }) + }); - const folder = times(utils.randomNumber({min: 1, max: 10}), () => utils.randomString()).reduce((acc: string[], c) => { - acc.push(c) + const folder = times(utils.randomNumber({ min: 1, max: 10 }), () => utils.randomString()) + .reduce((acc: string[], c) => { + acc.push(c); - plays.davCreate.exec({ - credential, - path: acc.join('/'), - userName: account.login, - tags: {asset: id}, - }); - - return acc - }, []).join('/') + plays.davCreate.exec({ + credential, + path: acc.join('/'), + userName: account.login, + tags: { asset: id }, + }); + return acc; + }, []) + .join('/'); plays.davUpload.exec({ credential, asset, path: folder, userName: account.login, - tags: {asset: id}, + tags: { asset: id }, }); - filesUploaded.push({id, name: asset.name, folder}) - }) + filesUploaded.push({ id, name: asset.name, folder }); + }); plays.davPropfind.exec({ credential, userName: account.login, - }) + }); - filesUploaded.forEach(f => { + filesUploaded.forEach((f) => { plays.davDelete.exec({ credential, userName: account.login, path: f.folder.split('/')[0], - tags: {asset: f.id}, + tags: { asset: f.id }, }); - }) -} \ No newline at end of file + }); +}; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts index b7ab3d182..4e72077da 100644 --- a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts +++ b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts @@ -1,72 +1,72 @@ -import {Options} from "k6/options"; -import {utils, auth, defaults, playbook} from '../../../../../../lib' -import {times} from 'lodash' +import { Options, Threshold } from 'k6/options'; +import { utils, auth, defaults, playbook, types } from '../../../../../../lib'; +import { times } from 'lodash'; // upload, download and delete of many files with several sizes and summary size of 500 MB in one directory const files: { size: number; - unit: any; + unit: types.AssetUnit; }[] = [ - ...times(100, () => ({size: 500, unit: 'KB'})), - ...times(50, () => ({size: 5, unit: 'MB'})), - ...times(10, () => ({size: 25, unit: 'MB'})), -] -const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); + ...times(100, () => ({ size: 500, unit: 'KB' as types.AssetUnit })), + ...times(50, () => ({ size: 5, unit: 'MB' as types.AssetUnit })), + ...times(10, () => ({ size: 25, unit: 'MB' as types.AssetUnit })), +]; +const authFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); const plays = { - davUpload: new playbook.dav.Upload({}), - davDownload: new playbook.dav.Download({}), - davDelete: new playbook.dav.Delete({}), -} + davUpload: new playbook.dav.Upload(), + davDownload: new playbook.dav.Download(), + davDelete: new playbook.dav.Delete(), +}; export const options: Options = { insecureSkipTLSVerify: true, iterations: 3, vus: 1, - thresholds: files.reduce((acc: any, c) => { - acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.davDownload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - return acc + thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDownload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + return acc; }, {}), }; export default (): void => { - const filesUploaded: { id: string, name: string, }[] = [] - const {account, credential} = authFactory; + const filesUploaded: { id: string; name: string }[] = []; + const { account, credential } = authFactory; - files.forEach(f => { + files.forEach((f) => { const id = f.unit + f.size.toString(); const asset = utils.buildAsset({ name: `${account.login}-dummy.zip`, - unit: f.unit as any, + unit: f.unit, size: f.size, - }) + }); plays.davUpload.exec({ credential, asset, userName: account.login, - tags: {asset: id}, + tags: { asset: id }, }); - filesUploaded.push({id, name: asset.name}) - }) + filesUploaded.push({ id, name: asset.name }); + }); - filesUploaded.forEach(f => { + filesUploaded.forEach((f) => { plays.davDownload.exec({ credential, userName: account.login, path: f.name, - tags: {asset: f.id}, + tags: { asset: f.id }, }); - }) + }); - filesUploaded.forEach(f => { + filesUploaded.forEach((f) => { plays.davDelete.exec({ credential, userName: account.login, path: f.name, - tags: {asset: f.id}, + tags: { asset: f.id }, }); - }) -} \ No newline at end of file + }); +}; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts index 82ef129a6..ca038216c 100644 --- a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts +++ b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts @@ -1,5 +1,5 @@ -import {Options} from "k6/options"; -import {utils, auth, defaults, playbook, types} from '../../../../../../lib' +import { Options, Threshold } from 'k6/options'; +import { utils, auth, defaults, playbook, types } from '../../../../../../lib'; // upload, download and delete of one file with sizes 50kb, 500kb, 5MB, 50MB, 500MB, 1GB @@ -7,69 +7,69 @@ const files: { size: number; unit: types.AssetUnit; }[] = [ - {size: 50, unit: 'KB'}, - {size: 500, unit: 'KB'}, - {size: 5, unit: 'MB'}, - {size: 50, unit: 'MB'}, - {size: 500, unit: 'MB'}, - {size: 1, unit: 'GB'}, -] -const authFactory = new auth.default(utils.buildAccount({login: defaults.ACCOUNTS.EINSTEIN})); + { size: 50, unit: 'KB' }, + { size: 500, unit: 'KB' }, + { size: 5, unit: 'MB' }, + { size: 50, unit: 'MB' }, + { size: 500, unit: 'MB' }, + { size: 1, unit: 'GB' }, +]; +const authFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); const plays = { - davUpload: new playbook.dav.Upload({}), - davDownload: new playbook.dav.Download({}), - davDelete: new playbook.dav.Delete({}), -} + davUpload: new playbook.dav.Upload(), + davDownload: new playbook.dav.Download(), + davDelete: new playbook.dav.Delete(), +}; export const options: Options = { insecureSkipTLSVerify: true, iterations: 3, vus: 1, - thresholds: files.reduce((acc: any, c) => { - acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.davDownload.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}`] = [] - return acc + thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDownload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + return acc; }, {}), }; export default (): void => { - const filesUploaded: { id: string, name: string, }[] = [] - const {account, credential} = authFactory; + const filesUploaded: { id: string; name: string }[] = []; + const { account, credential } = authFactory; - files.forEach(f => { + files.forEach((f) => { const id = f.unit + f.size.toString(); const asset = utils.buildAsset({ name: `${account.login}-dummy.zip`, - unit: f.unit as any, + unit: f.unit, size: f.size, - }) + }); plays.davUpload.exec({ credential, asset, userName: account.login, - tags: {asset: id}, + tags: { asset: id }, }); - filesUploaded.push({id, name: asset.name}) - }) + filesUploaded.push({ id, name: asset.name }); + }); - filesUploaded.forEach(f => { + filesUploaded.forEach((f) => { plays.davDownload.exec({ credential, userName: account.login, path: f.name, - tags: {asset: f.id}, + tags: { asset: f.id }, }); - }) + }); - filesUploaded.forEach(f => { + filesUploaded.forEach((f) => { plays.davDelete.exec({ credential, userName: account.login, path: f.name, - tags: {asset: f.id}, + tags: { asset: f.id }, }); - }) -} \ No newline at end of file + }); +}; diff --git a/tests/k6/yarn.lock b/tests/k6/yarn.lock index df96e6678..35ee33c40 100644 --- a/tests/k6/yarn.lock +++ b/tests/k6/yarn.lock @@ -1013,6 +1013,22 @@ dependencies: find-up "^4.0.0" +"@eslint/eslintrc@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c" + integrity sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1330,11 +1346,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/faker@^5.1.4": - version "5.1.4" - resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.1.4.tgz#1299e3e3e1b115227a33f2330bc038ce03237b52" - integrity sha512-ZK+Bmi5GcWSLe8TQDOj9+K5KImV/41Ydm7Fs3IbtAA11l1MVK0Dlo16KTni5cGZISxGiCaWE+uB9gznWT2GUgw== - "@types/graceful-fs@^4.1.2": version "4.1.4" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.4.tgz#4ff9f641a7c6d1a3508ff88bc3141b152772e753" @@ -1362,14 +1373,6 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jest@^25.2.1": - version "25.2.3" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.2.3.tgz#33d27e4c4716caae4eced355097a47ad363fdcaf" - integrity sha512-JXc1nK/tXHiDhV55dvfzqtmP4S3sy3T3ouV2tkViZgxY/zeUkcpQcQPGRlgF4KmWzWW5oiWYSZwtCB+2RsE4Fw== - dependencies: - jest-diff "^25.2.1" - pretty-format "^25.2.1" - "@types/json-schema@^7.0.3": version "7.0.6" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" @@ -1434,17 +1437,43 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^2.29.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9" - integrity sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ== +"@typescript-eslint/eslint-plugin@^4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.9.0.tgz#8fde15743413661fdc086c9f1f5d74a80b856113" + integrity sha512-WrVzGMzzCrgrpnQMQm4Tnf+dk+wdl/YbgIgd5hKGa2P+lnJ2MON+nQnbwgbxtN9QDLi8HO+JAq0/krMnjQK6Cw== dependencies: - "@typescript-eslint/experimental-utils" "2.34.0" + "@typescript-eslint/experimental-utils" "4.9.0" + "@typescript-eslint/scope-manager" "4.9.0" + debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" + semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.34.0", "@typescript-eslint/experimental-utils@^2.5.0": +"@typescript-eslint/experimental-utils@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" + integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/experimental-utils@4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.9.0.tgz#23a296b85d243afba24e75a43fd55aceda5141f0" + integrity sha512-0p8GnDWB3R2oGhmRXlEnCvYOtaBCijtA5uBfH5GxQKsukdSQyI4opC4NGTUb88CagsoNQ4rb/hId2JuMbzWKFQ== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/scope-manager" "4.9.0" + "@typescript-eslint/types" "4.9.0" + "@typescript-eslint/typescript-estree" "4.9.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/experimental-utils@^2.5.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f" integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA== @@ -1454,16 +1483,45 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^2.29.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.34.0.tgz#50252630ca319685420e9a39ca05fe185a256bc8" - integrity sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA== +"@typescript-eslint/parser@^3.0.0": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" + integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.34.0" - "@typescript-eslint/typescript-estree" "2.34.0" + "@typescript-eslint/experimental-utils" "3.10.1" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" eslint-visitor-keys "^1.1.0" +"@typescript-eslint/parser@^4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.9.0.tgz#bb65f1214b5e221604996db53ef77c9d62b09249" + integrity sha512-QRSDAV8tGZoQye/ogp28ypb8qpsZPV6FOLD+tbN4ohKUWHD2n/u0Q2tIBnCsGwQCiD94RdtLkcqpdK4vKcLCCw== + dependencies: + "@typescript-eslint/scope-manager" "4.9.0" + "@typescript-eslint/types" "4.9.0" + "@typescript-eslint/typescript-estree" "4.9.0" + debug "^4.1.1" + +"@typescript-eslint/scope-manager@4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.9.0.tgz#5eefe305d6b71d1c85af6587b048426bfd4d3708" + integrity sha512-q/81jtmcDtMRE+nfFt5pWqO0R41k46gpVLnuefqVOXl4QV1GdQoBWfk5REcipoJNQH9+F5l+dwa9Li5fbALjzg== + dependencies: + "@typescript-eslint/types" "4.9.0" + "@typescript-eslint/visitor-keys" "4.9.0" + +"@typescript-eslint/types@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" + integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== + +"@typescript-eslint/types@4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.9.0.tgz#3fe8c3632abd07095c7458f7451bd14c85d0033c" + integrity sha512-luzLKmowfiM/IoJL/rus1K9iZpSJK6GlOS/1ezKplb7MkORt2dDcfi8g9B0bsF6JoRGhqn0D3Va55b+vredFHA== + "@typescript-eslint/typescript-estree@2.34.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5" @@ -1477,6 +1535,49 @@ semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/typescript-estree@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" + integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== + dependencies: + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/visitor-keys" "3.10.1" + debug "^4.1.1" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/typescript-estree@4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.9.0.tgz#38a98df6ee281cfd6164d6f9d91795b37d9e508c" + integrity sha512-rmDR++PGrIyQzAtt3pPcmKWLr7MA+u/Cmq9b/rON3//t5WofNR4m/Ybft2vOLj0WtUzjn018ekHjTsnIyBsQug== + dependencies: + "@typescript-eslint/types" "4.9.0" + "@typescript-eslint/visitor-keys" "4.9.0" + debug "^4.1.1" + globby "^11.0.1" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/visitor-keys@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" + integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== + dependencies: + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/visitor-keys@4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.9.0.tgz#f284e9fac43f2d6d35094ce137473ee321f266c8" + integrity sha512-sV45zfdRqQo1A97pOSx3fsjR+3blmwtdCt8LDrXgCX36v4Vmz4KHrhpV6Fo2cRdXmyumxx11AHw0pNJqCNpDyg== + dependencies: + "@typescript-eslint/types" "4.9.0" + eslint-visitor-keys "^2.0.0" + JSONStream@^1.0.4: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -1513,7 +1614,7 @@ acorn@^6.0.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== -acorn@^7.1.0, acorn@^7.1.1: +acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -1526,7 +1627,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3: +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1548,6 +1649,16 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: dependencies: type-fest "^0.11.0" +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -1558,6 +1669,11 @@ ansi-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -1625,6 +1741,11 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -1964,7 +2085,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1973,6 +2094,17 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -1989,11 +2121,6 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -2029,11 +2156,6 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - cliui@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" @@ -2107,6 +2229,11 @@ commander@^6.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== +common-tags@^1.4.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" + integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2120,6 +2247,11 @@ compare-func@^1.3.1: array-ify "^1.0.0" dot-prop "^3.0.0" +compare-versions@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" + integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -2216,7 +2348,7 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -2227,7 +2359,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0: +cross-spawn@^7.0.0, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -2318,7 +2450,7 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= -deep-is@~0.1.3: +deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= @@ -2372,6 +2504,18 @@ diff-sequences@^25.2.6: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dlv@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -2423,7 +2567,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enquirer@^2.3.6: +enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -2442,7 +2586,7 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -2464,7 +2608,7 @@ escodegen@^1.11.1: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^6.11.0: +eslint-config-prettier@^6.15.0: version "6.15.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== @@ -2478,14 +2622,14 @@ eslint-plugin-jest@^23.8.2: dependencies: "@typescript-eslint/experimental-utils" "^2.5.0" -eslint-plugin-prettier@^3.1.3: - version "3.1.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2" - integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg== +eslint-plugin-prettier@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.2.0.tgz#af391b2226fa0e15c96f36c733f6e9035dbd952c" + integrity sha512-kOUSJnFjAUFKwVxuzy6sA5yyMx6+o9ino4gCdShzBNx4eyFRudWRYKCFolKjoM40PEiuU6Cn7wBLfq3WsGg7qg== dependencies: prettier-linter-helpers "^1.0.0" -eslint-scope@^5.0.0: +eslint-scope@^5.0.0, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -2493,41 +2637,41 @@ eslint-scope@^5.0.0: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-utils@^2.0.0: +eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.1.0: +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.14.0, eslint@^7.9.0: + version "7.14.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.14.0.tgz#2d2cac1d28174c510a97b377f122a5507958e344" + integrity sha512-5YubdnPXrlrYAFCKybPuHIAH++PINe1pmKNc5wQRB9HSbqIK1ywAnntE3Wwua4giKu0bjligf1gLF6qxMGOYRA== dependencies: "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.2.1" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" + chalk "^4.0.0" + cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.0" + esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" @@ -2536,26 +2680,24 @@ eslint@^6.8.0: ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" + levn "^0.4.1" + lodash "^4.17.19" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" + optionator "^0.9.1" progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" table "^5.2.3" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.1.2: +espree@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== @@ -2564,12 +2706,21 @@ espree@^6.1.2: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.1.0" +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.3.0" + esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: +esquery@^1.0.1, esquery@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== @@ -2712,15 +2863,6 @@ extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -2755,7 +2897,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.0.0: +fast-glob@^3.0.0, fast-glob@^3.1.1: version "3.2.4" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== @@ -2772,7 +2914,7 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -2791,7 +2933,7 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -figures@^3.0.0, figures@^3.2.0: +figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -2837,6 +2979,13 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-versions@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" + integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== + dependencies: + semver-regex "^2.0.0" + flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -3016,6 +3165,18 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" +globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" @@ -3044,6 +3205,13 @@ hard-rejection@^2.1.0: resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -3135,7 +3303,23 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -iconv-lite@0.4.24, iconv-lite@^0.4.24: +husky@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.0.tgz#0b2ec1d66424e9219d359e26a51c58ec5278f0de" + integrity sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA== + dependencies: + chalk "^4.0.0" + ci-info "^2.0.0" + compare-versions "^3.6.0" + cosmiconfig "^7.0.0" + find-versions "^3.2.0" + opencollective-postinstall "^2.0.2" + pkg-dir "^4.2.0" + please-upgrade-node "^3.2.0" + slash "^3.0.0" + which-pm-runs "^1.0.0" + +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -3147,6 +3331,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" @@ -3204,25 +3393,6 @@ ini@^1.3.4: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -inquirer@^7.0.0: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.19" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.6.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -3549,7 +3719,7 @@ jest-config@^25.5.4: pretty-format "^25.5.0" realpath-native "^2.0.0" -jest-diff@^25.2.1, jest-diff@^25.5.0: +jest-diff@^25.5.0: version "25.5.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.5.0.tgz#1dd26ed64f96667c068cef026b677dfa01afcfa9" integrity sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A== @@ -4018,7 +4188,15 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@^0.3.0, levn@~0.3.0: +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= @@ -4096,6 +4274,11 @@ lodash._reinterpolate@^3.0.0: resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= +lodash.merge@^4.6.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -4143,6 +4326,19 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" +loglevel-colored-level-prefix@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz#6a40218fdc7ae15fc76c3d0f3e676c465388603e" + integrity sha1-akAhj9x64V/HbD0PPmdsRlOIYD4= + dependencies: + chalk "^1.1.3" + loglevel "^1.4.1" + +loglevel@^1.4.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" + integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== + lolex@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/lolex/-/lolex-5.1.2.tgz#953694d098ce7c07bc5ed6d0e42bc6c0c6d5a367" @@ -4358,11 +4554,6 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -4524,7 +4715,12 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -optionator@^0.8.1, optionator@^0.8.3: +opencollective-postinstall@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" + integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== + +optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -4536,10 +4732,17 @@ optionator@^0.8.1, optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" p-each-series@^2.1.0: version "2.1.0" @@ -4724,11 +4927,34 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prettier-eslint@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/prettier-eslint/-/prettier-eslint-12.0.0.tgz#b4dab5111aad1c0dca062eb7f92a69d5fb1ac1d3" + integrity sha512-N8SGGQwAosISXTNl1E57sBbtnqUGlyRWjcfIUxyD3HF4ynehA9GZ8IfJgiep/OfYvCof/JEpy9ZqSl250Wia7A== + dependencies: + "@typescript-eslint/parser" "^3.0.0" + common-tags "^1.4.0" + dlv "^1.1.0" + eslint "^7.9.0" + indent-string "^4.0.0" + lodash.merge "^4.6.0" + loglevel-colored-level-prefix "^1.0.0" + prettier "^2.0.0" + pretty-format "^23.0.1" + require-relative "^0.8.7" + typescript "^3.9.3" + vue-eslint-parser "~7.1.0" + prettier-linter-helpers@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" @@ -4736,12 +4962,20 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.0.5: - version "2.1.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" - integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== +prettier@^2.0.0, prettier@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" + integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== -pretty-format@^25.2.1, pretty-format@^25.5.0: +pretty-format@^23.0.1: + version "23.6.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760" + integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw== + dependencies: + ansi-regex "^3.0.0" + ansi-styles "^3.2.0" + +pretty-format@^25.5.0: version "25.5.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a" integrity sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ== @@ -4949,12 +5183,7 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpp@^3.0.0: +regexpp@^3.0.0, regexpp@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== @@ -5055,6 +5284,11 @@ require-package-name@^2.0.1: resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9" integrity sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk= +require-relative@^0.8.7: + version "0.8.7" + resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" + integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4= + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -5189,17 +5423,12 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - run-parallel@^1.1.9: version "1.1.10" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== -rxjs@^6.6.0, rxjs@^6.6.3: +rxjs@^6.6.3: version "6.6.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== @@ -5255,12 +5484,17 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= +semver-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" + integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== + "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@6.3.0, semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: +semver@6.3.0, semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -5270,6 +5504,13 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== +semver@^7.2.1: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" + semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" @@ -5586,6 +5827,13 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -5632,11 +5880,16 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.0.1: +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -5737,18 +5990,11 @@ through2@^4.0.0: dependencies: readable-stream "3" -"through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8: +"through@>=2.2.7 <3", through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -5854,6 +6100,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -5893,11 +6146,16 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@^3.8.3: +typescript@^3.9.3: version "3.9.7" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== +typescript@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9" + integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ== + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" @@ -5997,6 +6255,18 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vue-eslint-parser@~7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz#c43c1c715ff50778b9a7e9a4e16921185f3425d3" + integrity sha512-8FdXi0gieEwh1IprIBafpiJWcApwrU+l2FEj8c1HtHFdNXMd0+2jUSjBVmcQYohf/E72irwAXEXLga6TQcB3FA== + dependencies: + debug "^4.1.1" + eslint-scope "^5.0.0" + eslint-visitor-keys "^1.1.0" + espree "^6.2.1" + esquery "^1.0.1" + lodash "^4.17.15" + w3c-hr-time@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -6051,6 +6321,11 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-pm-runs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" + integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= + which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -6065,7 +6340,7 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" -word-wrap@~1.2.3: +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== From a3d1e55d29e6e5d4b9d374833fa83d0d7c8d2444 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 3 Dec 2020 11:52:46 +0100 Subject: [PATCH 10/27] test ci --- .drone.star | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/.drone.star b/.drone.star index 558de29a2..b59cf3201 100644 --- a/.drone.star +++ b/.drone.star @@ -123,6 +123,7 @@ def main(ctx): before = \ [ buildOcisBinaryForTesting(ctx) ] + \ + [benchmark(ctx)] + \ testOcisModules(ctx) + \ testPipelines(ctx) @@ -138,7 +139,7 @@ def main(ctx): ] purge = purgeBuildArtifactCache(ctx, 'ocis-binary-amd64') - purge['depends_on'] = getPipelineNames(testPipelines(ctx)) + purge['depends_on'] = getPipelineNames(testPipelines(ctx) + [benchmark(ctx)]) after = [ manifest(ctx), @@ -525,6 +526,51 @@ def coreApiTests(ctx, coreBranch = 'master', coreCommit = '', part_number = 1, n }, } +def benchmark(ctx): + return { + 'kind': 'pipeline', + 'type': 'docker', + 'name': 'benchmark', + 'platform': { + 'os': 'linux', + 'arch': 'amd64', + }, + 'steps': + restoreBuildArtifactCache(ctx, 'ocis-binary-amd64', 'ocis/bin/ocis') + + ocisServer('ocis') + [ + { + 'name': 'build benchmarks', + 'image': 'node', + 'pull': 'always', + 'commands': [ + 'cd tests/k6', + 'yarn', + 'yarn build', + ], + }, + { + 'name': 'run benchmarks', + 'image': 'loadimpact/k6', + 'pull': 'always', + 'environment': { + 'OC_HOST': 'https://ocis-server:9200', + }, + 'commands': [ + 'cd tests/k6', + 'for f in ./dist/test-* ; do k6 run "$f" ; done', + ], + }, + ], + 'depends_on': getPipelineNames([buildOcisBinaryForTesting(ctx)]), + 'trigger': { + 'ref': [ + 'refs/heads/master', + 'refs/tags/v*', + 'refs/pull/**', + ], + }, + } + def uiTests(ctx, phoenixBranch, phoenixCommit): suiteNames = config['uiTests']['suites'].keys() return [uiTestPipeline(ctx, suiteName, phoenixBranch, phoenixCommit) for suiteName in suiteNames] From f61184b1a270e12b5398fc8d9714ebd403f6214b Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 3 Dec 2020 12:03:04 +0100 Subject: [PATCH 11/27] revert reva replace directive --- ocis/go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/ocis/go.mod b/ocis/go.mod index 3cdf426f4..01ca7ada1 100644 --- a/ocis/go.mod +++ b/ocis/go.mod @@ -53,5 +53,4 @@ replace ( github.com/owncloud/ocis/thumbnails => ../thumbnails github.com/owncloud/ocis/webdav => ../webdav google.golang.org/grpc => google.golang.org/grpc v1.26.0 - github.com/cs3org/reva => ../../../cs3org/reva ) From abf89d4ba7a38263e91ac2267f20288f0057bd3c Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 3 Dec 2020 12:16:10 +0100 Subject: [PATCH 12/27] run k6 in quiet mode move k6 to the after stage --- .drone.star | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.star b/.drone.star index b59cf3201..28aa20df8 100644 --- a/.drone.star +++ b/.drone.star @@ -123,7 +123,6 @@ def main(ctx): before = \ [ buildOcisBinaryForTesting(ctx) ] + \ - [benchmark(ctx)] + \ testOcisModules(ctx) + \ testPipelines(ctx) @@ -142,6 +141,7 @@ def main(ctx): purge['depends_on'] = getPipelineNames(testPipelines(ctx) + [benchmark(ctx)]) after = [ + benchmark(ctx), manifest(ctx), changelog(ctx), readme(ctx), @@ -557,7 +557,7 @@ def benchmark(ctx): }, 'commands': [ 'cd tests/k6', - 'for f in ./dist/test-* ; do k6 run "$f" ; done', + 'for f in ./dist/test-* ; do k6 run "$f" -q; done', ], }, ], From f6493e503ff64b503ddd57194b7ce61f81808782 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 3 Dec 2020 12:28:12 +0100 Subject: [PATCH 13/27] update .drone.star --- .drone.star | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.star b/.drone.star index 28aa20df8..8cf27075a 100644 --- a/.drone.star +++ b/.drone.star @@ -124,7 +124,8 @@ def main(ctx): before = \ [ buildOcisBinaryForTesting(ctx) ] + \ testOcisModules(ctx) + \ - testPipelines(ctx) + testPipelines(ctx) + \ + [benchmark(ctx)] stages = [ docker(ctx, 'amd64'), @@ -141,7 +142,6 @@ def main(ctx): purge['depends_on'] = getPipelineNames(testPipelines(ctx) + [benchmark(ctx)]) after = [ - benchmark(ctx), manifest(ctx), changelog(ctx), readme(ctx), From 594b094e545c1767b4f85692516fc288a48a69e0 Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Thu, 3 Dec 2020 13:07:59 +0100 Subject: [PATCH 14/27] add benchmarks to cron and add ci flag --- .drone.star | 8 ++++++-- docs/ocis/development/continuous-integration.md | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.drone.star b/.drone.star index 8cf27075a..f2002f72d 100644 --- a/.drone.star +++ b/.drone.star @@ -124,8 +124,7 @@ def main(ctx): before = \ [ buildOcisBinaryForTesting(ctx) ] + \ testOcisModules(ctx) + \ - testPipelines(ctx) + \ - [benchmark(ctx)] + testPipelines(ctx) stages = [ docker(ctx, 'amd64'), @@ -152,6 +151,7 @@ def main(ctx): ] if ctx.build.event == "cron": + before.append(benchmark(ctx)) notify_pipeline = notify(ctx) notify_pipeline['depends_on'] = \ getPipelineNames(before) @@ -174,6 +174,9 @@ def main(ctx): pipelines = docs_pipelines + [ notify_pipeline ] + elif '[with-benchmarks]' in (ctx.build.title + ctx.build.message): + before.append(benchmark(ctx)) + else: pipelines = before + stages + after @@ -531,6 +534,7 @@ def benchmark(ctx): 'kind': 'pipeline', 'type': 'docker', 'name': 'benchmark', + 'failure': 'ignore', 'platform': { 'os': 'linux', 'arch': 'amd64', diff --git a/docs/ocis/development/continuous-integration.md b/docs/ocis/development/continuous-integration.md index 52a275f4c..f7d2a201b 100644 --- a/docs/ocis/development/continuous-integration.md +++ b/docs/ocis/development/continuous-integration.md @@ -37,6 +37,8 @@ You may add flags to your commit message or PR title in order to speed up pipeli - `[tests-only]`: please add this flag, if you only changed tests or test-related tooling. You do not need to add a changelog for tests-only changes. +- `[with-benchmarks]`: please add this flag, if you want benchmarks to be run in CI. + ### Knowledge base - My pipeline fails because some CI related files or commands are missing. From bb99f44a356b141e3763955a5142fbb945bee085 Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Thu, 3 Dec 2020 13:20:45 +0100 Subject: [PATCH 15/27] fix drone definition --- .drone.star | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/.drone.star b/.drone.star index f2002f72d..59ae33231 100644 --- a/.drone.star +++ b/.drone.star @@ -137,9 +137,6 @@ def main(ctx): releaseSubmodule(ctx), ] - purge = purgeBuildArtifactCache(ctx, 'ocis-binary-amd64') - purge['depends_on'] = getPipelineNames(testPipelines(ctx) + [benchmark(ctx)]) - after = [ manifest(ctx), changelog(ctx), @@ -147,11 +144,16 @@ def main(ctx): badges(ctx), docs(ctx), updateDeployment(ctx), - purge, ] if ctx.build.event == "cron": before.append(benchmark(ctx)) + + purge = purgeBuildArtifactCache(ctx, 'ocis-binary-amd64') + purge['depends_on'] = getPipelineNames(before) + + before.append(purge) + notify_pipeline = notify(ctx) notify_pipeline['depends_on'] = \ getPipelineNames(before) @@ -174,11 +176,17 @@ def main(ctx): pipelines = docs_pipelines + [ notify_pipeline ] - elif '[with-benchmarks]' in (ctx.build.title + ctx.build.message): - before.append(benchmark(ctx)) - else: - pipelines = before + stages + after + purge_dependencies = testPipelines(ctx) + + if '[with-benchmarks]' in (ctx.build.title + ctx.build.message): + before.append(benchmark(ctx)) + purge_dependencies.append(benchmark(ctx)) + + purge = purgeBuildArtifactCache(ctx, 'ocis-binary-amd64') + purge['depends_on'] = getPipelineNames(purge_dependencies) + + pipelines = before + stages + after + [purge] notify_pipeline = notify(ctx) notify_pipeline['depends_on'] = \ From e7ee1c3c9e149392e6099cc8c3d16d021530d2b6 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 3 Dec 2020 13:47:25 +0100 Subject: [PATCH 16/27] update changelog --- changelog/unreleased/add-k6.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/changelog/unreleased/add-k6.md b/changelog/unreleased/add-k6.md index 0bf638896..e0944a9eb 100644 --- a/changelog/unreleased/add-k6.md +++ b/changelog/unreleased/add-k6.md @@ -1,5 +1,8 @@ -Change: Add k6 +Enhancement: Add k6 -add k6 as a load testing framework +Tags: tests + +add k6 as a performance testing framework https://github.com/owncloud/ocis/pull/941 +https://github.com/owncloud/ocis/pull/983 From bd773b54ef433553020c8042c77ce6c677a76f69 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 3 Dec 2020 16:06:04 +0100 Subject: [PATCH 17/27] add eslint add prettier integrate concept of runner libs to share tasks --- tests/k6/.eslintrc | 9 + tests/k6/package.json | 2 + tests/k6/rollup.config.js | 71 +++-- tests/k6/src/lib/api/api.ts | 11 +- tests/k6/src/lib/api/dav.ts | 3 +- tests/k6/src/lib/api/users.ts | 3 +- tests/k6/src/lib/auth.ts | 9 +- tests/k6/src/lib/index.ts | 4 +- tests/k6/src/lib/playbook/dav.ts | 5 +- tests/k6/src/lib/playbook/users.ts | 5 +- tests/k6/src/lib/utils.ts | 1 + .../ocis/1018/propfind/deep.lib.ts} | 55 ++-- .../issue/github/ocis/1018/propfind/deep.ts | 27 ++ .../github/ocis/1018/propfind/flat.lib.ts | 71 +++++ .../issue/github/ocis/1018/propfind/flat.ts | 26 ++ .../1018/upload-download-delete/many-large.ts | 33 +++ .../1018/upload-download-delete/many-small.ts | 31 +++ .../1018/upload-download-delete/shared.lib.ts | 76 ++++++ .../upload-download-delete/with-new-user.ts | 44 +++ .../issue/jira/ocis/1007/concurrent-users.ts | 73 ----- .../jira/ocis/1007/folder-listing/flat.ts | 63 ----- .../1007/simple-down-and-upload/many-small.ts | 72 ----- .../1007/simple-down-and-upload/some-large.ts | 75 ------ tests/k6/yarn.lock | 254 +++++++++++++++++- 24 files changed, 655 insertions(+), 368 deletions(-) rename tests/k6/src/test/issue/{jira/ocis/1007/folder-listing/nested.ts => github/ocis/1018/propfind/deep.lib.ts} (58%) create mode 100644 tests/k6/src/test/issue/github/ocis/1018/propfind/deep.ts create mode 100644 tests/k6/src/test/issue/github/ocis/1018/propfind/flat.lib.ts create mode 100644 tests/k6/src/test/issue/github/ocis/1018/propfind/flat.ts create mode 100644 tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/many-large.ts create mode 100644 tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/many-small.ts create mode 100644 tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/shared.lib.ts create mode 100644 tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/with-new-user.ts delete mode 100644 tests/k6/src/test/issue/jira/ocis/1007/concurrent-users.ts delete mode 100644 tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts delete mode 100644 tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts delete mode 100644 tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts diff --git a/tests/k6/.eslintrc b/tests/k6/.eslintrc index a68b15172..f7c6f491e 100644 --- a/tests/k6/.eslintrc +++ b/tests/k6/.eslintrc @@ -1,4 +1,8 @@ { + "plugins": [ + "simple-import-sort", + "import" + ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 2020, @@ -10,5 +14,10 @@ "plugin:prettier/recommended" ], "rules": { + "simple-import-sort/imports": "error", + "simple-import-sort/exports": "error", + "import/first": "error", + "import/newline-after-import": "error", + "import/no-duplicates": "error", } } \ No newline at end of file diff --git a/tests/k6/package.json b/tests/k6/package.json index 980ce8bed..f0ba2aa02 100644 --- a/tests/k6/package.json +++ b/tests/k6/package.json @@ -36,8 +36,10 @@ "babel-plugin-lodash": "^3.3.4", "eslint": "^7.14.0", "eslint-config-prettier": "^6.15.0", + "eslint-plugin-import": "^2.22.1", "eslint-plugin-jest": "^23.8.2", "eslint-plugin-prettier": "^3.2.0", + "eslint-plugin-simple-import-sort": "^6.0.1", "husky": "^4.3.0", "jest": "^25.4.0", "k6": "^0.0.0", diff --git a/tests/k6/rollup.config.js b/tests/k6/rollup.config.js index baed47a32..90484768e 100644 --- a/tests/k6/rollup.config.js +++ b/tests/k6/rollup.config.js @@ -1,8 +1,8 @@ -import commonjs from '@rollup/plugin-commonjs' -import json from '@rollup/plugin-json' -import resolve from '@rollup/plugin-node-resolve' -import babel from 'rollup-plugin-babel' -import { terser } from 'rollup-plugin-terser' +import commonjs from '@rollup/plugin-commonjs'; +import json from '@rollup/plugin-json'; +import resolve from '@rollup/plugin-node-resolve'; +import babel from 'rollup-plugin-babel'; +import { terser } from 'rollup-plugin-terser'; import multiInput from 'rollup-plugin-multi-input'; import utils from '@rollup/pluginutils'; import pkg from './package.json'; @@ -10,36 +10,31 @@ import pkg from './package.json'; const extensions = ['.js', '.ts']; export default [ - { - input: ['src/test/**/*.ts'], - external: utils.createFilter([ - 'k6/**', - ...Object.keys(pkg.devDependencies), - ], null, { resolve: false }), - output: [ - { - dir: 'dist', - format: 'cjs', - exports: 'named', - chunkFileNames: '_chunks/[name]-[hash].js' - }, - ], - plugins: [ - multiInput({ - transformOutputPath: (output, input) => `${output.split('/').join('-')}`, - }), - json(), - resolve( - { - extensions, - } - ), - commonjs(), - babel({ - extensions, - include: ['src/**/*'], - }), - terser(), - ], - } -] \ No newline at end of file + { + input: ['src/test/**/*.ts', '!src/test/**/*.lib.ts', '!src/test/**/index.ts', '!src/test/**/_*.ts'], + external: utils.createFilter(['k6/**', ...Object.keys(pkg.devDependencies)], null, { resolve: false }), + output: [ + { + dir: 'dist', + format: 'cjs', + exports: 'named', + chunkFileNames: '_chunks/[name]-[hash].js', + }, + ], + plugins: [ + multiInput({ + transformOutputPath: (output, input) => `${output.split('/').join('-')}`, + }), + json(), + resolve({ + extensions, + }), + commonjs(), + babel({ + extensions, + include: ['src/**/*'], + }), + terser(), + ], + }, +]; diff --git a/tests/k6/src/lib/api/api.ts b/tests/k6/src/lib/api/api.ts index d09cc7466..fec810216 100644 --- a/tests/k6/src/lib/api/api.ts +++ b/tests/k6/src/lib/api/api.ts @@ -1,9 +1,10 @@ -import encoding from 'k6/encoding'; -import * as types from '../types'; -import * as defaults from '../defaults'; -import { merge } from 'lodash'; -import http, { RefinedParams, RefinedResponse, RequestBody, ResponseType } from 'k6/http'; import { bytes } from 'k6'; +import encoding from 'k6/encoding'; +import http, { RefinedParams, RefinedResponse, RequestBody, ResponseType } from 'k6/http'; +import { merge } from 'lodash'; + +import * as defaults from '../defaults'; +import * as types from '../types'; export const buildHeaders = ({ credential }: { credential?: types.Credential }): { [key: string]: string } => { const isOIDCGuard = (credential as types.Token).tokenType !== undefined; diff --git a/tests/k6/src/lib/api/dav.ts b/tests/k6/src/lib/api/dav.ts index ea74a2509..a818d3055 100644 --- a/tests/k6/src/lib/api/dav.ts +++ b/tests/k6/src/lib/api/dav.ts @@ -1,6 +1,7 @@ import { RefinedResponse, ResponseType } from 'k6/http'; -import * as api from './api'; + import * as types from '../types'; +import * as api from './api'; export class Upload { public static exec({ diff --git a/tests/k6/src/lib/api/users.ts b/tests/k6/src/lib/api/users.ts index 75a0dbf24..567ca55ea 100644 --- a/tests/k6/src/lib/api/users.ts +++ b/tests/k6/src/lib/api/users.ts @@ -1,6 +1,7 @@ import { RefinedResponse, ResponseType } from 'k6/http'; -import * as api from './api'; + import * as types from '../types'; +import * as api from './api'; export class Create { public static exec({ diff --git a/tests/k6/src/lib/auth.ts b/tests/k6/src/lib/auth.ts index 3aa21e8bf..da50bffcd 100644 --- a/tests/k6/src/lib/auth.ts +++ b/tests/k6/src/lib/auth.ts @@ -1,9 +1,10 @@ -import * as defaults from './defaults'; -import http from 'k6/http'; -import queryString from 'query-string'; -import * as types from './types'; import { fail } from 'k6'; +import http from 'k6/http'; import { get } from 'lodash'; +import queryString from 'query-string'; + +import * as defaults from './defaults'; +import * as types from './types'; export default class Factory { private provider!: types.AuthProvider; diff --git a/tests/k6/src/lib/index.ts b/tests/k6/src/lib/index.ts index 056deecb9..56aea64f2 100644 --- a/tests/k6/src/lib/index.ts +++ b/tests/k6/src/lib/index.ts @@ -1,6 +1,6 @@ export * as api from './api'; -export * as playbook from './playbook'; -export * as auth from './auth'; +export { default as auth } from './auth'; export * as defaults from './defaults'; +export * as playbook from './playbook'; export * as types from './types'; export * as utils from './utils'; diff --git a/tests/k6/src/lib/playbook/dav.ts b/tests/k6/src/lib/playbook/dav.ts index ec9996dce..90c77f61f 100644 --- a/tests/k6/src/lib/playbook/dav.ts +++ b/tests/k6/src/lib/playbook/dav.ts @@ -1,7 +1,8 @@ -import * as api from '../api'; import { check } from 'k6'; -import * as types from '../types'; import { RefinedResponse, ResponseType } from 'k6/http'; + +import * as api from '../api'; +import * as types from '../types'; import { Play } from './playbook'; export class Upload extends Play { diff --git a/tests/k6/src/lib/playbook/users.ts b/tests/k6/src/lib/playbook/users.ts index ae228ef50..289bb99c1 100644 --- a/tests/k6/src/lib/playbook/users.ts +++ b/tests/k6/src/lib/playbook/users.ts @@ -1,7 +1,8 @@ -import * as api from '../api'; import { check } from 'k6'; -import * as types from '../types'; import { RefinedResponse, ResponseType } from 'k6/http'; + +import * as api from '../api'; +import * as types from '../types'; import { Play } from './playbook'; export class Create extends Play { diff --git a/tests/k6/src/lib/utils.ts b/tests/k6/src/lib/utils.ts index 5fa7ec79b..e169f3806 100644 --- a/tests/k6/src/lib/utils.ts +++ b/tests/k6/src/lib/utils.ts @@ -1,5 +1,6 @@ import { bytes } from 'k6'; import { randomBytes as k6_randomBytes } from 'k6/crypto'; + import * as defaults from './defaults'; import * as types from './types'; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts b/tests/k6/src/test/issue/github/ocis/1018/propfind/deep.lib.ts similarity index 58% rename from tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts rename to tests/k6/src/test/issue/github/ocis/1018/propfind/deep.lib.ts index c5a33af17..16611f61a 100644 --- a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/nested.ts +++ b/tests/k6/src/test/issue/github/ocis/1018/propfind/deep.lib.ts @@ -1,34 +1,43 @@ import { Options, Threshold } from 'k6/options'; -import { utils, auth, defaults, playbook, types } from '../../../../../../lib'; import { times } from 'lodash'; -// Unpack standard data tarball, run PROPFIND on each dir +import { playbook, types, utils } from '../../../../../../lib'; -const files: { +interface File { size: number; unit: types.AssetUnit; -}[] = times(1000, () => ({ size: 1, unit: 'KB' })); -const authFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); -const plays = { - davUpload: new playbook.dav.Upload(), - davPropfind: new playbook.dav.Propfind(), - davCreate: new playbook.dav.Create(), - davDelete: new playbook.dav.Delete(), +} + +interface Plays { + davUpload: playbook.dav.Upload; + davPropfind: playbook.dav.Propfind; + davCreate: playbook.dav.Create; + davDelete: playbook.dav.Delete; +} + +export const options = ({ files, plays }: { files: File[]; plays: Plays }): Options => { + return { + thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davCreate.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + return acc; + }, {}), + }; }; -export const options: Options = { - insecureSkipTLSVerify: true, - iterations: 3, - vus: 1, - thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { - acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - acc[`${plays.davCreate.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - return acc; - }, {}), -}; -export default (): void => { + +export default ({ + files, + account, + credential, + plays, +}: { + plays: Plays; + files: File[]; + account: types.Account; + credential: types.Credential; +}): void => { const filesUploaded: { id: string; name: string; folder: string }[] = []; - const { account, credential } = authFactory; files.forEach((f) => { const id = f.unit + f.size.toString(); diff --git a/tests/k6/src/test/issue/github/ocis/1018/propfind/deep.ts b/tests/k6/src/test/issue/github/ocis/1018/propfind/deep.ts new file mode 100644 index 000000000..ad18da671 --- /dev/null +++ b/tests/k6/src/test/issue/github/ocis/1018/propfind/deep.ts @@ -0,0 +1,27 @@ +import { Options } from 'k6/options'; +import { times } from 'lodash'; + +import { auth, defaults, playbook, types, utils } from '../../../../../../lib'; +import { default as propfind, options as propfindOptions } from './deep.lib'; + +// put 1000 files into nested dirs and run a 'PROPFIND' through API + +const files: { + size: number; + unit: types.AssetUnit; +}[] = times(1000, () => ({ size: 1, unit: 'KB' })); +const authFactory = new auth(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); +const plays = { + davUpload: new playbook.dav.Upload(), + davCreate: new playbook.dav.Create(), + davPropfind: new playbook.dav.Propfind(), + davDelete: new playbook.dav.Delete(), +}; +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 3, + vus: 1, + ...propfindOptions({ plays, files }), +}; + +export default (): void => propfind({ files, plays, credential: authFactory.credential, account: authFactory.account }); diff --git a/tests/k6/src/test/issue/github/ocis/1018/propfind/flat.lib.ts b/tests/k6/src/test/issue/github/ocis/1018/propfind/flat.lib.ts new file mode 100644 index 000000000..151d9d8c0 --- /dev/null +++ b/tests/k6/src/test/issue/github/ocis/1018/propfind/flat.lib.ts @@ -0,0 +1,71 @@ +import { Options, Threshold } from 'k6/options'; + +import { playbook, types, utils } from '../../../../../../lib'; + +interface File { + size: number; + unit: types.AssetUnit; +} + +interface Plays { + davUpload: playbook.dav.Upload; + davPropfind: playbook.dav.Propfind; + davDelete: playbook.dav.Delete; +} + +export const options = ({ files, plays }: { files: File[]; plays: Plays }): Options => { + return { + thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + return acc; + }, {}), + }; +}; + +export default ({ + files, + account, + credential, + plays, +}: { + plays: Plays; + files: File[]; + account: types.Account; + credential: types.Credential; +}): void => { + const filesUploaded: { id: string; name: string }[] = []; + + files.forEach((f) => { + const id = f.unit + f.size.toString(); + + const asset = utils.buildAsset({ + name: `${account.login}-dummy.zip`, + unit: f.unit, + size: f.size, + }); + + plays.davUpload.exec({ + credential, + asset, + userName: account.login, + tags: { asset: id }, + }); + + filesUploaded.push({ id, name: asset.name }); + }); + + plays.davPropfind.exec({ + credential, + userName: account.login, + }); + + filesUploaded.forEach((f) => { + plays.davDelete.exec({ + credential, + userName: account.login, + path: f.name, + tags: { asset: f.id }, + }); + }); +}; diff --git a/tests/k6/src/test/issue/github/ocis/1018/propfind/flat.ts b/tests/k6/src/test/issue/github/ocis/1018/propfind/flat.ts new file mode 100644 index 000000000..7c2a7e8af --- /dev/null +++ b/tests/k6/src/test/issue/github/ocis/1018/propfind/flat.ts @@ -0,0 +1,26 @@ +import { Options } from 'k6/options'; +import { times } from 'lodash'; + +import { auth, defaults, playbook, types, utils } from '../../../../../../lib'; +import { default as propfind, options as propfindOptions } from './flat.lib'; + +// put 1000 files into one dir and run a 'PROPFIND' through API + +const files: { + size: number; + unit: types.AssetUnit; +}[] = times(1000, () => ({ size: 1, unit: 'KB' })); +const authFactory = new auth(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); +const plays = { + davUpload: new playbook.dav.Upload(), + davPropfind: new playbook.dav.Propfind(), + davDelete: new playbook.dav.Delete(), +}; +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 3, + vus: 1, + ...propfindOptions({ plays, files }), +}; + +export default (): void => propfind({ files, plays, credential: authFactory.credential, account: authFactory.account }); diff --git a/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/many-large.ts b/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/many-large.ts new file mode 100644 index 000000000..513c9b68b --- /dev/null +++ b/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/many-large.ts @@ -0,0 +1,33 @@ +import { Options } from 'k6/options'; + +import { auth, defaults, playbook, types, utils } from '../../../../../../lib'; +import { default as upDownDelete, options as upDownDeleteOptions } from './shared.lib'; + +// upload, download and delete of many files with several sizes and summary size of 500 MB in one directory + +const files: { + size: number; + unit: types.AssetUnit; +}[] = [ + { size: 50, unit: 'KB' }, + { size: 500, unit: 'KB' }, + { size: 5, unit: 'MB' }, + { size: 50, unit: 'MB' }, + { size: 500, unit: 'MB' }, + { size: 1, unit: 'GB' }, +]; +const authFactory = new auth(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); +const plays = { + davUpload: new playbook.dav.Upload(), + davDownload: new playbook.dav.Download(), + davDelete: new playbook.dav.Delete(), +}; +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 3, + vus: 1, + ...upDownDeleteOptions({ plays, files }), +}; + +export default (): void => + upDownDelete({ files, plays, credential: authFactory.credential, account: authFactory.account }); diff --git a/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/many-small.ts b/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/many-small.ts new file mode 100644 index 000000000..6b792a3d7 --- /dev/null +++ b/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/many-small.ts @@ -0,0 +1,31 @@ +import { Options } from 'k6/options'; +import { times } from 'lodash'; + +import { auth, defaults, playbook, types, utils } from '../../../../../../lib'; +import { default as upDownDelete, options as upDownDeleteOptions } from './shared.lib'; + +// upload, download and delete of many files with several sizes and summary size of 500 MB in one directory + +const files: { + size: number; + unit: types.AssetUnit; +}[] = [ + ...times(100, () => ({ size: 500, unit: 'KB' as types.AssetUnit })), + ...times(50, () => ({ size: 5, unit: 'MB' as types.AssetUnit })), + ...times(10, () => ({ size: 25, unit: 'MB' as types.AssetUnit })), +]; +const authFactory = new auth(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); +const plays = { + davUpload: new playbook.dav.Upload(), + davDownload: new playbook.dav.Download(), + davDelete: new playbook.dav.Delete(), +}; +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 3, + vus: 1, + ...upDownDeleteOptions({ plays, files }), +}; + +export default (): void => + upDownDelete({ files, plays, credential: authFactory.credential, account: authFactory.account }); diff --git a/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/shared.lib.ts b/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/shared.lib.ts new file mode 100644 index 000000000..eb775a2d0 --- /dev/null +++ b/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/shared.lib.ts @@ -0,0 +1,76 @@ +import { Options, Threshold } from 'k6/options'; + +import { playbook, types, utils } from '../../../../../../lib'; + +interface File { + size: number; + unit: types.AssetUnit; +} + +interface Plays { + davUpload: playbook.dav.Upload; + davDownload: playbook.dav.Download; + davDelete: playbook.dav.Delete; +} + +export const options = ({ files, plays }: { files: File[]; plays: Plays }): Options => { + return { + thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { + acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDownload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; + return acc; + }, {}), + }; +}; + +export default ({ + files, + account, + credential, + plays, +}: { + plays: Plays; + files: File[]; + account: types.Account; + credential: types.Credential; +}): void => { + const filesUploaded: { id: string; name: string }[] = []; + + files.forEach((f) => { + const id = f.unit + f.size.toString(); + + const asset = utils.buildAsset({ + name: `${account.login}-dummy.zip`, + unit: f.unit, + size: f.size, + }); + + plays.davUpload.exec({ + credential, + asset, + userName: account.login, + tags: { asset: id }, + }); + + filesUploaded.push({ id, name: asset.name }); + }); + + filesUploaded.forEach((f) => { + plays.davDownload.exec({ + credential, + userName: account.login, + path: f.name, + tags: { asset: f.id }, + }); + }); + + filesUploaded.forEach((f) => { + plays.davDelete.exec({ + credential, + userName: account.login, + path: f.name, + tags: { asset: f.id }, + }); + }); +}; diff --git a/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/with-new-user.ts b/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/with-new-user.ts new file mode 100644 index 000000000..34922e307 --- /dev/null +++ b/tests/k6/src/test/issue/github/ocis/1018/upload-download-delete/with-new-user.ts @@ -0,0 +1,44 @@ +import { Options } from 'k6/options'; +import { times } from 'lodash'; + +import { auth, defaults, playbook, types, utils } from '../../../../../../lib'; +import { default as upDownDelete, options as upDownDeleteOptions } from './shared.lib'; + +// create 10 users. Do the Simple Uploads & downloads with each user in parallel. + +const files: { + size: number; + unit: types.AssetUnit; +}[] = times(10, () => ({ size: 1, unit: 'KB' as types.AssetUnit })); +const authFactory = new auth(utils.buildAccount({ login: defaults.ACCOUNTS.ADMIN })); +const plays = { + davUpload: new playbook.dav.Upload(), + davDownload: new playbook.dav.Download(), + davDelete: new playbook.dav.Delete(), + usersCreate: new playbook.users.Create(), + usersDelete: new playbook.users.Delete(), +}; +export const options: Options = { + insecureSkipTLSVerify: true, + iterations: 10, + vus: 10, + ...upDownDeleteOptions({ plays, files }), +}; + +export default (): void => { + const userName: string = utils.randomString(); + const password: string = utils.randomString(); + + plays.usersCreate.exec({ + userName, + password, + email: `${userName}@owncloud.com`, + credential: authFactory.credential, + }); + + const userAuthFactory = new auth({ login: userName, password }); + + upDownDelete({ files, plays, credential: userAuthFactory.credential, account: userAuthFactory.account }); + + plays.usersDelete.exec({ userName: userName, credential: authFactory.credential }); +}; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/concurrent-users.ts b/tests/k6/src/test/issue/jira/ocis/1007/concurrent-users.ts deleted file mode 100644 index 65a01ec48..000000000 --- a/tests/k6/src/test/issue/jira/ocis/1007/concurrent-users.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Options, Threshold } from 'k6/options'; -import { utils, auth, defaults, playbook, types } from '../../../../../lib'; - -const files: Array<{ - size: number; - unit: types.AssetUnit; -}> = [ - { size: 50, unit: 'KB' }, - { size: 500, unit: 'KB' }, - { size: 5, unit: 'MB' }, - { size: 50, unit: 'MB' }, -]; -const adminAuthFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.ADMIN })); -const plays = { - usersCreate: new playbook.users.Create(), - usersDelete: new playbook.users.Delete(), - davUpload: new playbook.dav.Upload(), - davDelete: new playbook.dav.Delete(), -}; -export const options: Options = { - insecureSkipTLSVerify: true, - iterations: 10, - vus: 10, - thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { - acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - return acc; - }, {}), -}; - -export default (): void => { - const userName: string = utils.randomString(); - const password: string = utils.randomString(); - - plays.usersCreate.exec({ - userName, - password, - email: `${userName}@owncloud.com`, - credential: adminAuthFactory.credential, - }); - const userAuthFactory = new auth.default({ login: userName, password }); - const filesUploaded: { id: string; name: string }[] = []; - - files.forEach((f) => { - const id = f.unit + f.size.toString(); - - const asset = utils.buildAsset({ - name: `${userName}-dummy.zip`, - unit: f.unit, - size: f.size, - }); - - plays.davUpload.exec({ - credential: userAuthFactory.credential, - asset, - userName, - tags: { asset: id }, - }); - - filesUploaded.push({ id, name: asset.name }); - }); - - filesUploaded.forEach((f) => { - plays.davDelete.exec({ - credential: userAuthFactory.credential, - userName: userAuthFactory.account.login, - path: f.name, - tags: { asset: f.id }, - }); - }); - - plays.usersDelete.exec({ userName: userName, credential: adminAuthFactory.credential }); -}; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts b/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts deleted file mode 100644 index 656ee3f56..000000000 --- a/tests/k6/src/test/issue/jira/ocis/1007/folder-listing/flat.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Options, Threshold } from 'k6/options'; -import { utils, auth, defaults, playbook, types } from '../../../../../../lib'; -import { times } from 'lodash'; - -// put 1000 files into one dir and run a 'PROPFIND' through API - -const files: { - size: number; - unit: types.AssetUnit; -}[] = times(1000, () => ({ size: 1, unit: 'KB' })); -const authFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); -const plays = { - davUpload: new playbook.dav.Upload(), - davPropfind: new playbook.dav.Propfind(), - davDelete: new playbook.dav.Delete(), -}; -export const options: Options = { - insecureSkipTLSVerify: true, - iterations: 3, - vus: 1, - thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { - acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - return acc; - }, {}), -}; -export default (): void => { - const filesUploaded: { id: string; name: string }[] = []; - const { account, credential } = authFactory; - - files.forEach((f) => { - const id = f.unit + f.size.toString(); - - const asset = utils.buildAsset({ - name: `${account.login}-dummy.zip`, - unit: f.unit, - size: f.size, - }); - - plays.davUpload.exec({ - credential, - asset, - userName: account.login, - tags: { asset: id }, - }); - - filesUploaded.push({ id, name: asset.name }); - }); - - plays.davPropfind.exec({ - credential, - userName: account.login, - }); - - filesUploaded.forEach((f) => { - plays.davDelete.exec({ - credential, - userName: account.login, - path: f.name, - tags: { asset: f.id }, - }); - }); -}; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts deleted file mode 100644 index 4e72077da..000000000 --- a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/many-small.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Options, Threshold } from 'k6/options'; -import { utils, auth, defaults, playbook, types } from '../../../../../../lib'; -import { times } from 'lodash'; - -// upload, download and delete of many files with several sizes and summary size of 500 MB in one directory - -const files: { - size: number; - unit: types.AssetUnit; -}[] = [ - ...times(100, () => ({ size: 500, unit: 'KB' as types.AssetUnit })), - ...times(50, () => ({ size: 5, unit: 'MB' as types.AssetUnit })), - ...times(10, () => ({ size: 25, unit: 'MB' as types.AssetUnit })), -]; -const authFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); -const plays = { - davUpload: new playbook.dav.Upload(), - davDownload: new playbook.dav.Download(), - davDelete: new playbook.dav.Delete(), -}; -export const options: Options = { - insecureSkipTLSVerify: true, - iterations: 3, - vus: 1, - thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { - acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - acc[`${plays.davDownload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - return acc; - }, {}), -}; -export default (): void => { - const filesUploaded: { id: string; name: string }[] = []; - const { account, credential } = authFactory; - - files.forEach((f) => { - const id = f.unit + f.size.toString(); - - const asset = utils.buildAsset({ - name: `${account.login}-dummy.zip`, - unit: f.unit, - size: f.size, - }); - - plays.davUpload.exec({ - credential, - asset, - userName: account.login, - tags: { asset: id }, - }); - - filesUploaded.push({ id, name: asset.name }); - }); - - filesUploaded.forEach((f) => { - plays.davDownload.exec({ - credential, - userName: account.login, - path: f.name, - tags: { asset: f.id }, - }); - }); - - filesUploaded.forEach((f) => { - plays.davDelete.exec({ - credential, - userName: account.login, - path: f.name, - tags: { asset: f.id }, - }); - }); -}; diff --git a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts b/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts deleted file mode 100644 index ca038216c..000000000 --- a/tests/k6/src/test/issue/jira/ocis/1007/simple-down-and-upload/some-large.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Options, Threshold } from 'k6/options'; -import { utils, auth, defaults, playbook, types } from '../../../../../../lib'; - -// upload, download and delete of one file with sizes 50kb, 500kb, 5MB, 50MB, 500MB, 1GB - -const files: { - size: number; - unit: types.AssetUnit; -}[] = [ - { size: 50, unit: 'KB' }, - { size: 500, unit: 'KB' }, - { size: 5, unit: 'MB' }, - { size: 50, unit: 'MB' }, - { size: 500, unit: 'MB' }, - { size: 1, unit: 'GB' }, -]; -const authFactory = new auth.default(utils.buildAccount({ login: defaults.ACCOUNTS.EINSTEIN })); -const plays = { - davUpload: new playbook.dav.Upload(), - davDownload: new playbook.dav.Download(), - davDelete: new playbook.dav.Delete(), -}; -export const options: Options = { - insecureSkipTLSVerify: true, - iterations: 3, - vus: 1, - thresholds: files.reduce((acc: { [name: string]: Threshold[] }, c) => { - acc[`${plays.davUpload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - acc[`${plays.davDownload.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - acc[`${plays.davDelete.metricTrendName}{asset:${c.unit + c.size.toString()}}`] = []; - return acc; - }, {}), -}; - -export default (): void => { - const filesUploaded: { id: string; name: string }[] = []; - const { account, credential } = authFactory; - - files.forEach((f) => { - const id = f.unit + f.size.toString(); - - const asset = utils.buildAsset({ - name: `${account.login}-dummy.zip`, - unit: f.unit, - size: f.size, - }); - - plays.davUpload.exec({ - credential, - asset, - userName: account.login, - tags: { asset: id }, - }); - - filesUploaded.push({ id, name: asset.name }); - }); - - filesUploaded.forEach((f) => { - plays.davDownload.exec({ - credential, - userName: account.login, - path: f.name, - tags: { asset: f.id }, - }); - }); - - filesUploaded.forEach((f) => { - plays.davDelete.exec({ - credential, - userName: account.login, - path: f.name, - tags: { asset: f.id }, - }); - }); -}; diff --git a/tests/k6/yarn.lock b/tests/k6/yarn.lock index 35ee33c40..3f4c696fe 100644 --- a/tests/k6/yarn.lock +++ b/tests/k6/yarn.lock @@ -1378,6 +1378,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + "@types/k6@^0.28.2": version "0.28.2" resolved "https://registry.yarnpkg.com/@types/k6/-/k6-0.28.2.tgz#619cd018ea43f47457a940cec2579fe00591c980" @@ -1741,6 +1746,17 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= +array-includes@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8" + integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + get-intrinsic "^1.0.1" + is-string "^1.0.5" + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -1751,6 +1767,15 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +array.prototype.flat@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" + integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -2262,6 +2287,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + conventional-changelog-angular@^1.3.3: version "1.6.6" resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-1.6.6.tgz#b27f2b315c16d0a1f23eb181309d0e6a4698ea0f" @@ -2413,7 +2443,7 @@ data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -debug@^2.2.0, debug@^2.3.3: +debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -2516,6 +2546,14 @@ dlv@^1.1.0: resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -2574,13 +2612,40 @@ enquirer@^2.3.5, enquirer@^2.3.6: dependencies: ansi-colors "^4.1.1" -error-ex@^1.3.1: +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" +es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -2615,6 +2680,41 @@ eslint-config-prettier@^6.15.0: dependencies: get-stdin "^6.0.0" +eslint-import-resolver-node@^0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" + integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== + dependencies: + debug "^2.6.9" + resolve "^1.13.1" + +eslint-module-utils@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" + integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA== + dependencies: + debug "^2.6.9" + pkg-dir "^2.0.0" + +eslint-plugin-import@^2.22.1: + version "2.22.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" + integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== + dependencies: + array-includes "^3.1.1" + array.prototype.flat "^1.2.3" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.4" + eslint-module-utils "^2.6.0" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.1" + read-pkg-up "^2.0.0" + resolve "^1.17.0" + tsconfig-paths "^3.9.0" + eslint-plugin-jest@^23.8.2: version "23.20.0" resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.20.0.tgz#e1d69c75f639e99d836642453c4e75ed22da4099" @@ -2629,6 +2729,11 @@ eslint-plugin-prettier@^3.2.0: dependencies: prettier-linter-helpers "^1.0.0" +eslint-plugin-simple-import-sort@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-6.0.1.tgz#24a3af3b745dcd389c060db28e22d0f5e3edf86e" + integrity sha512-RfFnoi7fQtv7z9sZNJidIcZgWc0ZJe8uOPC3ldmatai4Igr5iDpzTmSUDEZKYm4TnrR01N0X32kfKvax7bivHQ== + eslint-scope@^5.0.0, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -2964,7 +3069,7 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -find-up@^2.0.0: +find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= @@ -3061,7 +3166,7 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.0: +get-intrinsic@^1.0.0, get-intrinsic@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== @@ -3422,6 +3527,11 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -3450,6 +3560,11 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -3522,6 +3637,11 @@ is-module@^1.0.0: resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -3558,6 +3678,13 @@ is-reference@^1.1.2: dependencies: "@types/estree" "*" +is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + dependencies: + has-symbols "^1.0.1" + is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" @@ -3573,6 +3700,18 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + is-text-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" @@ -3597,7 +3736,7 @@ is-wsl@^2.1.1: dependencies: is-docker "^2.0.0" -isarray@1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -4127,6 +4266,13 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + json5@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" @@ -4244,6 +4390,16 @@ listr2@^3.2.2: rxjs "^6.6.3" through "^2.3.8" +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -4672,6 +4828,11 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.8.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== + object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -4684,7 +4845,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0: +object.assign@^4.1.0, object.assign@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== @@ -4701,6 +4862,16 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" +object.values@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731" + integrity sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has "^1.0.3" + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -4811,6 +4982,13 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -4869,6 +5047,13 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -4891,6 +5076,11 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" @@ -4903,6 +5093,13 @@ pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -5062,6 +5259,14 @@ react-is@^16.12.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" @@ -5079,6 +5284,15 @@ read-pkg-up@^7.0.1: read-pkg "^5.2.0" type-fest "^0.8.1" +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -5328,7 +5542,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.10.0, resolve@^1.11.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.3.2: +resolve@^1.10.0, resolve@^1.11.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.3.2: version "1.19.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== @@ -5804,6 +6018,22 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string.prototype.trimend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -6076,6 +6306,16 @@ trim-off-newlines@^1.0.0: resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= +tsconfig-paths@^3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" + integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" From cb6513e6fa184d7772df8b7394b6c2cae9befcc8 Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Thu, 3 Dec 2020 16:27:13 +0100 Subject: [PATCH 18/27] fix whitespaces --- .drone.star | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.drone.star b/.drone.star index 59ae33231..3ddc5b451 100644 --- a/.drone.star +++ b/.drone.star @@ -148,7 +148,7 @@ def main(ctx): if ctx.build.event == "cron": before.append(benchmark(ctx)) - + purge = purgeBuildArtifactCache(ctx, 'ocis-binary-amd64') purge['depends_on'] = getPipelineNames(before) @@ -181,11 +181,11 @@ def main(ctx): if '[with-benchmarks]' in (ctx.build.title + ctx.build.message): before.append(benchmark(ctx)) - purge_dependencies.append(benchmark(ctx)) + purge_dependencies.append(benchmark(ctx)) purge = purgeBuildArtifactCache(ctx, 'ocis-binary-amd64') purge['depends_on'] = getPipelineNames(purge_dependencies) - + pipelines = before + stages + after + [purge] notify_pipeline = notify(ctx) From ddb4ffbfa13beed2d283dc82b03257b7d3b4e4dd Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Thu, 3 Dec 2020 16:10:56 +0000 Subject: [PATCH 19/27] Automated changelog update [skip ci] --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b7cdf04f..ee7b11044 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Bugfix - Fix choose account dialogue: [#846](https://github.com/owncloud/ocis/pull/846) * Bugfix - Fix id or username query handling: [#745](https://github.com/owncloud/ocis/pull/745) * Bugfix - Fix konnectd build: [#809](https://github.com/owncloud/ocis/pull/809) +* Bugfix - Fix path of files shared with me in ocs api: [#204](https://github.com/owncloud/product/issues/204) * Bugfix - Use micro default client: [#718](https://github.com/owncloud/ocis/pull/718) * Bugfix - Allow consent-prompt with switch-account: [#788](https://github.com/owncloud/ocis/pull/788) * Bugfix - Mint token with uid and gid: [#737](https://github.com/owncloud/ocis/pull/737) @@ -184,6 +185,13 @@ https://github.com/owncloud/ocis/pull/809 +* Bugfix - Fix path of files shared with me in ocs api: [#204](https://github.com/owncloud/product/issues/204) + + The path of files shared with me using the ocs api was pointing to an incorrect location. + + https://github.com/owncloud/product/issues/204 + https://github.com/owncloud/ocis/pull/994 + * Bugfix - Use micro default client: [#718](https://github.com/owncloud/ocis/pull/718) Tags: glauth From 99279379d9ba2d7ce5e815ccbba6e85d7debfc17 Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Thu, 3 Dec 2020 16:53:50 +0000 Subject: [PATCH 20/27] Automated changelog update [skip ci] --- CHANGELOG.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee7b11044..7104d9f23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,6 @@ * Change - Cache password validation: [#958](https://github.com/owncloud/ocis/pull/958) * Change - Filesystem based index: [#709](https://github.com/owncloud/ocis/pull/709) * Change - Rebuild index command for accounts: [#748](https://github.com/owncloud/ocis/pull/748) -* Change - Add k6: [#941](https://github.com/owncloud/ocis/pull/941) * Change - Add the thumbnails command: [#156](https://github.com/owncloud/ocis/issues/156) * Change - Use bcrypt to hash the user passwords: [#510](https://github.com/owncloud/ocis/issues/510) * Change - Replace the library which scales the images: [#910](https://github.com/owncloud/ocis/pull/910) @@ -64,6 +63,7 @@ * Enhancement - Add basic auth option: [#627](https://github.com/owncloud/ocis/pull/627) * Enhancement - Document how to run OCIS on top of EOS: [#172](https://github.com/owncloud/ocis/pull/172) * Enhancement - Add the glauth service: [#244](https://github.com/owncloud/product/issues/244) +* Enhancement - Add k6: [#941](https://github.com/owncloud/ocis/pull/941) * Enhancement - Add the konnectd service: [#244](https://github.com/owncloud/product/issues/244) * Enhancement - Add the ocis-phoenix service: [#244](https://github.com/owncloud/product/issues/244) * Enhancement - Add the ocis-pkg package: [#244](https://github.com/owncloud/product/issues/244) @@ -300,12 +300,6 @@ https://github.com/owncloud/ocis/pull/748 -* Change - Add k6: [#941](https://github.com/owncloud/ocis/pull/941) - - Add k6 as a load testing framework - - https://github.com/owncloud/ocis/pull/941 - * Change - Add the thumbnails command: [#156](https://github.com/owncloud/ocis/issues/156) Tags: thumbnails @@ -740,6 +734,15 @@ https://github.com/owncloud/product/issues/244 +* Enhancement - Add k6: [#941](https://github.com/owncloud/ocis/pull/941) + + Tags: tests + + Add k6 as a performance testing framework + + https://github.com/owncloud/ocis/pull/941 + https://github.com/owncloud/ocis/pull/983 + * Enhancement - Add the konnectd service: [#244](https://github.com/owncloud/product/issues/244) Tags: konnectd From fd2a96af5aac5ee06f90c125260bbaa6e7e93936 Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Fri, 4 Dec 2020 07:32:33 +0545 Subject: [PATCH 21/27] Fix typo in comment in .drone.star --- .drone.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.star b/.drone.star index 5e3ddf531..83f8cc2b3 100644 --- a/.drone.star +++ b/.drone.star @@ -1667,7 +1667,7 @@ def genericCache(name, action, mounts, cache_key): 'from_secret': 'cache_s3_endpoint' }, 'bucket': 'cache', - 'region': 'us-east-1', # not used at all, but failes if not given! + 'region': 'us-east-1', # not used at all, but fails if not given! 'path_style': 'true', 'cache_key': cache_key, 'rebuild': rebuild, From 151806157b09d135a2a2c657cb4b609858164649 Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Fri, 4 Dec 2020 07:33:14 +0545 Subject: [PATCH 22/27] Update phoenix UI test commit id --- .drone.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.star b/.drone.star index 83f8cc2b3..3f19a93f6 100644 --- a/.drone.star +++ b/.drone.star @@ -22,7 +22,7 @@ config = { }, 'uiTests': { 'phoenixBranch': 'master', - 'phoenixCommit': 'bed4effca2eb492d0ee20eee48575ea1eb92cd35', + 'phoenixCommit': 'c548282ab652b78e8c077d8bdf32b25060414047', 'suites': { 'webUIBasic': [ 'webUILogin', From 5c05441044b5f343e37b05a2595612bbf3d1049d Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Fri, 4 Dec 2020 08:36:41 +0545 Subject: [PATCH 23/27] Update core API test commit id --- .drone.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.star b/.drone.star index 3f19a93f6..606f26168 100644 --- a/.drone.star +++ b/.drone.star @@ -17,7 +17,7 @@ config = { }, 'apiTests': { 'coreBranch': 'master', - 'coreCommit': 'ed326fd54c7f9142389e49aad87653a905c6ddb7', + 'coreCommit': '027bc8b5fe8ad29967184eab200abd4211ef9006', 'numberOfParts': 10 }, 'uiTests': { From 200872b3b4df3ad018e82a6525feb89716ca0dc9 Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Wed, 2 Dec 2020 14:59:44 +0100 Subject: [PATCH 24/27] make insecure upstream servers configurable --- changelog/unreleased/proxy-allow-insecure-upstreams.md | 8 ++++++++ proxy/pkg/config/config.go | 1 + proxy/pkg/flagset/flagset.go | 7 +++++++ proxy/pkg/proxy/proxy.go | 7 +++++++ 4 files changed, 23 insertions(+) create mode 100644 changelog/unreleased/proxy-allow-insecure-upstreams.md diff --git a/changelog/unreleased/proxy-allow-insecure-upstreams.md b/changelog/unreleased/proxy-allow-insecure-upstreams.md new file mode 100644 index 000000000..ed098e39d --- /dev/null +++ b/changelog/unreleased/proxy-allow-insecure-upstreams.md @@ -0,0 +1,8 @@ +Change: Proxy allow insecure upstreams + +Tags: proxy + +We can now configure the proxy if insecure upstream servers are allowed. +This was added since you need to disable certificate checks fore some situations like testing. + +https://github.com/owncloud/ocis/pull/1007 diff --git a/proxy/pkg/config/config.go b/proxy/pkg/config/config.go index 388d81914..09d86626f 100644 --- a/proxy/pkg/config/config.go +++ b/proxy/pkg/config/config.go @@ -106,6 +106,7 @@ type Config struct { PreSignedURL PreSignedURL AutoprovisionAccounts bool EnableBasicAuth bool + Insecure bool } // OIDC is the config for the OpenID-Connect middleware. If set the proxy will try to authenticate every request diff --git a/proxy/pkg/flagset/flagset.go b/proxy/pkg/flagset/flagset.go index 3a1371a40..91a313570 100644 --- a/proxy/pkg/flagset/flagset.go +++ b/proxy/pkg/flagset/flagset.go @@ -185,6 +185,13 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"PROXY_REVA_GATEWAY_ADDR"}, Destination: &cfg.Reva.Address, }, + &cli.BoolFlag{ + Name: "insecure", + Value: false, + Usage: "allow insecure communication to upstream servers", + EnvVars: []string{"PROXY_INSECURE"}, + Destination: &cfg.Insecure, + }, // OIDC diff --git a/proxy/pkg/proxy/proxy.go b/proxy/pkg/proxy/proxy.go index 54fb95a3b..fe057f11a 100644 --- a/proxy/pkg/proxy/proxy.go +++ b/proxy/pkg/proxy/proxy.go @@ -2,6 +2,7 @@ package proxy import ( "context" + "crypto/tls" "net/http" "net/http/httputil" "net/url" @@ -37,6 +38,12 @@ func NewMultiHostReverseProxy(opts ...Option) *MultiHostReverseProxy { } rp.Director = rp.directorSelectionDirector + rp.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: options.Config.Insecure, + }, + } + if options.Config.Policies == nil { rp.logger.Info().Str("source", "runtime").Msg("Policies") options.Config.Policies = defaultPolicies() From 4c9d9904781337c1058484ee0551cdec99bf6c3e Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Thu, 3 Dec 2020 13:55:10 +0100 Subject: [PATCH 25/27] tage default values from http.DefaultTransport --- proxy/pkg/proxy/proxy.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/proxy/pkg/proxy/proxy.go b/proxy/pkg/proxy/proxy.go index fe057f11a..fa25b2d34 100644 --- a/proxy/pkg/proxy/proxy.go +++ b/proxy/pkg/proxy/proxy.go @@ -3,11 +3,13 @@ package proxy import ( "context" "crypto/tls" + "net" "net/http" "net/http/httputil" "net/url" "regexp" "strings" + "time" "github.com/owncloud/ocis/proxy/pkg/proxy/policy" "go.opencensus.io/plugin/ochttp/propagation/tracecontext" @@ -38,7 +40,19 @@ func NewMultiHostReverseProxy(opts ...Option) *MultiHostReverseProxy { } rp.Director = rp.directorSelectionDirector + // equals http.DefaultTransport except TLSClientConfig rp.Transport = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + DualStack: true, + }).DialContext, + ForceAttemptHTTP2: true, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, TLSClientConfig: &tls.Config{ InsecureSkipVerify: options.Config.Insecure, }, From fe2efc3c466be8c68a273d83da26da9b4bc0b593 Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Thu, 3 Dec 2020 13:57:19 +0100 Subject: [PATCH 26/27] change to InsecureBackends flag --- proxy/pkg/config/config.go | 2 +- proxy/pkg/flagset/flagset.go | 4 ++-- proxy/pkg/proxy/proxy.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/proxy/pkg/config/config.go b/proxy/pkg/config/config.go index 09d86626f..4da46e006 100644 --- a/proxy/pkg/config/config.go +++ b/proxy/pkg/config/config.go @@ -106,7 +106,7 @@ type Config struct { PreSignedURL PreSignedURL AutoprovisionAccounts bool EnableBasicAuth bool - Insecure bool + InsecureBackends bool } // OIDC is the config for the OpenID-Connect middleware. If set the proxy will try to authenticate every request diff --git a/proxy/pkg/flagset/flagset.go b/proxy/pkg/flagset/flagset.go index 91a313570..b8e3fb870 100644 --- a/proxy/pkg/flagset/flagset.go +++ b/proxy/pkg/flagset/flagset.go @@ -189,8 +189,8 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { Name: "insecure", Value: false, Usage: "allow insecure communication to upstream servers", - EnvVars: []string{"PROXY_INSECURE"}, - Destination: &cfg.Insecure, + EnvVars: []string{"PROXY_INSECURE_BACKENDS"}, + Destination: &cfg.InsecureBackends, }, // OIDC diff --git a/proxy/pkg/proxy/proxy.go b/proxy/pkg/proxy/proxy.go index fa25b2d34..b4c2e7193 100644 --- a/proxy/pkg/proxy/proxy.go +++ b/proxy/pkg/proxy/proxy.go @@ -54,7 +54,7 @@ func NewMultiHostReverseProxy(opts ...Option) *MultiHostReverseProxy { TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, TLSClientConfig: &tls.Config{ - InsecureSkipVerify: options.Config.Insecure, + InsecureSkipVerify: options.Config.InsecureBackends, }, } From 864ab57e9bce8ff4953bcddf5ada735337b42dcb Mon Sep 17 00:00:00 2001 From: Willy Kloucek <34452982+wkloucek@users.noreply.github.com> Date: Fri, 4 Dec 2020 07:51:19 +0000 Subject: [PATCH 27/27] Automated changelog update [skip ci] --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7104d9f23..c973451cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ * Change - Account management permissions for Admin role: [#124](https://github.com/owncloud/product/issues/124) * Change - Update phoenix to v0.18.0: [#651](https://github.com/owncloud/ocis/pull/651) * Change - Default apps in ownCloud Web: [#688](https://github.com/owncloud/ocis/pull/688) +* Change - Proxy allow insecure upstreams: [#1007](https://github.com/owncloud/ocis/pull/1007) * Change - Make ocis-settings available: [#287](https://github.com/owncloud/ocis/pull/287) * Change - Start ocis-proxy with the ocis server command: [#119](https://github.com/owncloud/ocis/issues/119) * Change - Theme welcome and choose account pages: [#887](https://github.com/owncloud/ocis/pull/887) @@ -482,6 +483,15 @@ https://github.com/owncloud/ocis/pull/688 +* Change - Proxy allow insecure upstreams: [#1007](https://github.com/owncloud/ocis/pull/1007) + + Tags: proxy + + We can now configure the proxy if insecure upstream servers are allowed. This was added since + you need to disable certificate checks fore some situations like testing. + + https://github.com/owncloud/ocis/pull/1007 + * Change - Make ocis-settings available: [#287](https://github.com/owncloud/ocis/pull/287) Tags: settings