mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-03-05 04:20:52 -06:00
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
ocis/config/identifier-registration.yaml
|
||||
*/bin
|
||||
*/dist
|
||||
dist/
|
||||
/hugo
|
||||
*.key
|
||||
*crt
|
||||
|
||||
5
changelog/unreleased/add-k6.md
Normal file
5
changelog/unreleased/add-k6.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Change: Add k6
|
||||
|
||||
add k6 as a load testing framework
|
||||
|
||||
https://github.com/owncloud/ocis/pull/941
|
||||
22
test/k6/ tsconfig.json
Normal file
22
test/k6/ tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"moduleResolution": "node",
|
||||
"module": "commonjs",
|
||||
"noEmit": true,
|
||||
"allowJs": true,
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
8
test/k6/.babelrc
Normal file
8
test/k6/.babelrc
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": ["@babel/env", "@babel/typescript"],
|
||||
"plugins": [
|
||||
"lodash",
|
||||
"@babel/proposal-class-properties",
|
||||
"@babel/proposal-object-rest-spread"
|
||||
]
|
||||
}
|
||||
15
test/k6/README.md
Normal file
15
test/k6/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## Requirements
|
||||
- [K6](https://k6.io/)
|
||||
- [YARN](https://yarnpkg.com/)
|
||||
- [OCIS](https://github.com/owncloud/ocis)
|
||||
|
||||
## How to build
|
||||
```
|
||||
$ yarn
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
## How to run
|
||||
```
|
||||
k6 run ./dist/TESTNAME.js
|
||||
```
|
||||
48
test/k6/package.json
Normal file
48
test/k6/package.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "oc-k6",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"clean": "rm -rf ./dist",
|
||||
"build": "rollup -c",
|
||||
"build:w": "rollup -c -w",
|
||||
"postinstall": "node ./scripts/postinstall.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.9.5",
|
||||
"@babel/preset-typescript": "^7.9.0",
|
||||
"@commitlint/cli": "^8.3.5",
|
||||
"@commitlint/config-conventional": "^8.3.4",
|
||||
"@rollup/plugin-commonjs": "^11.1.0",
|
||||
"@rollup/plugin-json": "^4.0.3",
|
||||
"@rollup/plugin-node-resolve": "^7.1.3",
|
||||
"@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",
|
||||
"axios": "^0.21.0",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-prettier": "^6.11.0",
|
||||
"eslint-plugin-jest": "^23.8.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"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": {
|
||||
"lodash": "^4.17.20"
|
||||
}
|
||||
}
|
||||
41
test/k6/rollup.config.js
Normal file
41
test/k6/rollup.config.js
Normal file
@@ -0,0 +1,41 @@
|
||||
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 path from 'path';
|
||||
|
||||
const extensions = ['.js', '.ts'];
|
||||
|
||||
export default [
|
||||
{
|
||||
input: ['src/test-*.ts'],
|
||||
external: id => ['k6'].some(m => id.includes(m)),
|
||||
output: [
|
||||
{
|
||||
dir: 'dist',
|
||||
format: 'cjs',
|
||||
exports: 'named',
|
||||
chunkFileNames: '_chunks/[name]-[hash].js'
|
||||
},
|
||||
],
|
||||
plugins: [
|
||||
multiInput({
|
||||
transformOutputPath: (output, input) => path.basename(output),
|
||||
}),
|
||||
json(),
|
||||
resolve(
|
||||
{
|
||||
extensions,
|
||||
}
|
||||
),
|
||||
commonjs(),
|
||||
babel({
|
||||
extensions,
|
||||
include: ['src/**/*'],
|
||||
}),
|
||||
terser(),
|
||||
],
|
||||
}
|
||||
]
|
||||
53
test/k6/scripts/postinstall.js
Normal file
53
test/k6/scripts/postinstall.js
Normal file
@@ -0,0 +1,53 @@
|
||||
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')
|
||||
})()
|
||||
28
test/k6/src/lib/api.ts
Normal file
28
test/k6/src/lib/api.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
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 = <RT extends ResponseType | undefined>(account: types.Account, data: bytes, name: string): RefinedResponse<RT> => {
|
||||
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 = <RT extends ResponseType | undefined>(account: any): RefinedResponse<RT> => {
|
||||
return http.get(
|
||||
`https://${defaults.host.name}/ocs/v1.php/cloud/users/${account.login}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Basic ${encoding.b64encode(`${account.login}:${account.password}`)}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
16
test/k6/src/lib/defaults.ts
Normal file
16
test/k6/src/lib/defaults.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import * as types from './types';
|
||||
|
||||
export const host = {
|
||||
name: __ENV.OC_HOST_NAME || 'localhost:9200'
|
||||
}
|
||||
|
||||
export const accounts: { [key: string]: types.Account; } = {
|
||||
einstein: {
|
||||
login: 'einstein',
|
||||
password: 'relativity',
|
||||
},
|
||||
richard: {
|
||||
login: 'richard',
|
||||
password: 'superfluidity',
|
||||
},
|
||||
}
|
||||
3
test/k6/src/lib/index.ts
Normal file
3
test/k6/src/lib/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * as defaults from './defaults'
|
||||
export * as api from './api'
|
||||
export * as utils from './utils'
|
||||
4
test/k6/src/lib/types.ts
Normal file
4
test/k6/src/lib/types.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface Account {
|
||||
login: string
|
||||
password: string
|
||||
}
|
||||
3
test/k6/src/lib/utils.ts
Normal file
3
test/k6/src/lib/utils.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const randomString = (): string => {
|
||||
return Math.random().toString(36).slice(2)
|
||||
}
|
||||
23
test/k6/src/test-issue-162.ts
Normal file
23
test/k6/src/test-issue-162.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import {sleep, check} from 'k6';
|
||||
import {Options} from "k6/options";
|
||||
import {defaults, api, utils} 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-${utils.randomString()}.jpg`)
|
||||
|
||||
check(res, {
|
||||
'status is 201': () => res.status === 201,
|
||||
});
|
||||
|
||||
sleep(1);
|
||||
};
|
||||
6218
test/k6/yarn.lock
Normal file
6218
test/k6/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user