From 938b2ea576ffc44bc01f7aae05fde4a40182b283 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Wed, 2 Dec 2020 04:02:57 +0100 Subject: [PATCH] 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 d50c553d49..9f5177065a 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 fd7836fa22..3dcacc9d77 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 0000000000..c01cae7200 --- /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 0000000000..e274791c0d --- /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 0000000000..32eb31b6fe --- /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 bc87e10234..baed47a325 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 bc574dffcd..0000000000 --- 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 b6bf237b64..1957edcd4d 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 bfac073004..ed78e70a24 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 5be51a7f3c..027f6d6321 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 760abab993..6622b4be71 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 17e79611cb..4e2deac520 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 36c677541b..ac648c5faa 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 159be1087d..8cecf6e408 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 54f9dcb354..85f0599a6f 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 06ed8bfb88..0000000000 --- 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 2a70421744..0000000000 --- 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 144535de8c..0000000000 --- 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 0000000000..884b7b06e1 --- /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 0000000000..2af298381c --- /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 0000000000..299c95b702 --- /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 0000000000..02d22570d2 --- /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 1197148b13..df96e66782 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"