feat(接口测试): 增加TCP协议的接口测试
This commit is contained in:
parent
b63a3ebbbc
commit
8582a4f04f
|
@ -171,6 +171,13 @@
|
|||
<version>${jmeter.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.jmeter</groupId>
|
||||
<artifactId>ApacheJMeter_tcp</artifactId>
|
||||
<version>${jmeter.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
|
|
|
@ -4,8 +4,6 @@ import com.alibaba.fastjson.annotation.JSONField;
|
|||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.dto.scenario.processor.BeanShellPostProcessor;
|
||||
import io.metersphere.api.dto.scenario.processor.BeanShellPreProcessor;
|
||||
import io.metersphere.api.dto.scenario.request.dubbo.ConfigCenter;
|
||||
import io.metersphere.api.dto.scenario.request.dubbo.ConsumerAndService;
|
||||
import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
|
||||
|
@ -39,8 +37,4 @@ public class DubboRequest extends Request {
|
|||
private List<KeyValue> args;
|
||||
@JSONField(ordinal = 9)
|
||||
private List<KeyValue> attachmentArgs;
|
||||
@JSONField(ordinal = 12)
|
||||
private BeanShellPreProcessor beanShellPreProcessor;
|
||||
@JSONField(ordinal = 13)
|
||||
private BeanShellPostProcessor beanShellPostProcessor;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ import com.alibaba.fastjson.annotation.JSONField;
|
|||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import io.metersphere.api.dto.scenario.Body;
|
||||
import io.metersphere.api.dto.scenario.KeyValue;
|
||||
import io.metersphere.api.dto.scenario.processor.BeanShellPostProcessor;
|
||||
import io.metersphere.api.dto.scenario.processor.BeanShellPreProcessor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
|
@ -31,10 +29,6 @@ public class HttpRequest extends Request {
|
|||
private List<KeyValue> headers;
|
||||
@JSONField(ordinal = 8)
|
||||
private Body body;
|
||||
@JSONField(ordinal = 11)
|
||||
private BeanShellPreProcessor beanShellPreProcessor;
|
||||
@JSONField(ordinal = 12)
|
||||
private BeanShellPostProcessor beanShellPostProcessor;
|
||||
@JSONField(ordinal = 14)
|
||||
private Long connectTimeout;
|
||||
@JSONField(ordinal = 15)
|
||||
|
|
|
@ -16,7 +16,8 @@ import lombok.Data;
|
|||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = HttpRequest.class, name = RequestType.HTTP),
|
||||
@JsonSubTypes.Type(value = DubboRequest.class, name = RequestType.DUBBO),
|
||||
@JsonSubTypes.Type(value = SqlRequest.class, name = RequestType.SQL)
|
||||
@JsonSubTypes.Type(value = SqlRequest.class, name = RequestType.SQL),
|
||||
@JsonSubTypes.Type(value = TCPRequest.class, name = RequestType.TCP)
|
||||
})
|
||||
@JSONType(seeAlso = {HttpRequest.class, DubboRequest.class, SqlRequest.class}, typeKey = "type")
|
||||
@Data
|
||||
|
|
|
@ -7,4 +7,6 @@ public class RequestType {
|
|||
public static final String DUBBO = "DUBBO";
|
||||
|
||||
public static final String SQL = "SQL";
|
||||
|
||||
public static final String TCP = "TCP";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package io.metersphere.api.dto.scenario.request;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@JSONType(typeName = RequestType.TCP)
|
||||
public class TCPRequest extends Request {
|
||||
// type 必须放最前面,以便能够转换正确的类
|
||||
private String type = RequestType.TCP;
|
||||
@JSONField(ordinal = 50)
|
||||
private Boolean useEnvironment;
|
||||
@JSONField(ordinal = 51)
|
||||
private String classname;
|
||||
@JSONField(ordinal = 52)
|
||||
private String server;
|
||||
@JSONField(ordinal = 53)
|
||||
private Integer port;
|
||||
@JSONField(ordinal = 54)
|
||||
private Integer ctimeout;
|
||||
@JSONField(ordinal = 55)
|
||||
private Integer timeout;
|
||||
@JSONField(ordinal = 56)
|
||||
private Boolean reUseConnection;
|
||||
@JSONField(ordinal = 57)
|
||||
private Boolean nodelay;
|
||||
@JSONField(ordinal = 58)
|
||||
private Boolean closeConnection;
|
||||
@JSONField(ordinal = 59)
|
||||
private String soLinger;
|
||||
@JSONField(ordinal = 60)
|
||||
private String eolByte;
|
||||
@JSONField(ordinal = 61)
|
||||
private String request;
|
||||
@JSONField(ordinal = 62)
|
||||
private String username;
|
||||
@JSONField(ordinal = 63)
|
||||
private String password;
|
||||
}
|
|
@ -50,6 +50,7 @@
|
|||
<el-radio :label="types.HTTP">HTTP</el-radio>
|
||||
<el-radio :label="types.DUBBO">DUBBO</el-radio>
|
||||
<el-radio :label="types.SQL">SQL</el-radio>
|
||||
<el-radio :label="types.TCP">TCP</el-radio>
|
||||
</el-radio-group>
|
||||
<el-button slot="reference" :disabled="isReadOnly"
|
||||
class="request-create" type="primary" size="mini" icon="el-icon-plus" plain/>
|
||||
|
|
|
@ -2,22 +2,32 @@
|
|||
<div class="request-form">
|
||||
<component @runDebug="runDebug" :is="component" :is-read-only="isReadOnly" :request="request" :scenario="scenario"/>
|
||||
<el-divider v-if="isCompleted"></el-divider>
|
||||
<ms-request-result-tail v-loading="debugReportLoading" v-if="isCompleted" :request="request.debugRequestResult ? request.debugRequestResult : {responseResult: {}, subRequestResults: []}"
|
||||
:scenario-name="request.debugScenario ? request.debugScenario.name : ''" ref="msDebugResult"/>
|
||||
<ms-request-result-tail v-loading="debugReportLoading" v-if="isCompleted"
|
||||
:request="request.debugRequestResult ? request.debugRequestResult : {responseResult: {}, subRequestResults: []}"
|
||||
:scenario-name="request.debugScenario ? request.debugScenario.name : ''"
|
||||
ref="msDebugResult"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {JSR223Processor, Request, RequestFactory, Scenario} from "../../model/ScenarioModel";
|
||||
import MsApiHttpRequestForm from "./ApiHttpRequestForm";
|
||||
import MsApiDubboRequestForm from "./ApiDubboRequestForm";
|
||||
import MsScenarioResults from "../../../report/components/ScenarioResults";
|
||||
import MsRequestResultTail from "../../../report/components/RequestResultTail";
|
||||
import MsApiSqlRequestForm from "./ApiSqlRequestForm";
|
||||
import {JSR223Processor, Request, RequestFactory, Scenario} from "../../model/ScenarioModel";
|
||||
import MsApiHttpRequestForm from "./ApiHttpRequestForm";
|
||||
import MsApiTcpRequestForm from "./ApiTcpRequestForm";
|
||||
import MsApiDubboRequestForm from "./ApiDubboRequestForm";
|
||||
import MsScenarioResults from "../../../report/components/ScenarioResults";
|
||||
import MsRequestResultTail from "../../../report/components/RequestResultTail";
|
||||
import MsApiSqlRequestForm from "./ApiSqlRequestForm";
|
||||
|
||||
export default {
|
||||
name: "MsApiRequestForm",
|
||||
components: {MsApiSqlRequestForm, MsRequestResultTail, MsScenarioResults, MsApiDubboRequestForm, MsApiHttpRequestForm},
|
||||
components: {
|
||||
MsApiSqlRequestForm,
|
||||
MsRequestResultTail,
|
||||
MsScenarioResults,
|
||||
MsApiDubboRequestForm,
|
||||
MsApiHttpRequestForm,
|
||||
MsApiTcpRequestForm
|
||||
},
|
||||
props: {
|
||||
scenario: Scenario,
|
||||
request: Request,
|
||||
|
@ -27,104 +37,107 @@ export default {
|
|||
},
|
||||
debugReportId: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
reportId: "",
|
||||
content: {scenarios:[]},
|
||||
debugReportLoading: false,
|
||||
showDebugReport: false
|
||||
data() {
|
||||
return {
|
||||
reportId: "",
|
||||
content: {scenarios: []},
|
||||
debugReportLoading: false,
|
||||
showDebugReport: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
component({request: {type}}) {
|
||||
let name;
|
||||
switch (type) {
|
||||
case RequestFactory.TYPES.DUBBO:
|
||||
name = "MsApiDubboRequestForm";
|
||||
break;
|
||||
case RequestFactory.TYPES.SQL:
|
||||
name = "MsApiSqlRequestForm";
|
||||
break;
|
||||
case RequestFactory.TYPES.TCP:
|
||||
name = "MsApiTcpRequestForm";
|
||||
break;
|
||||
default:
|
||||
name = "MsApiHttpRequestForm";
|
||||
}
|
||||
return name;
|
||||
},
|
||||
computed: {
|
||||
component({request: {type}}) {
|
||||
let name;
|
||||
switch (type) {
|
||||
case RequestFactory.TYPES.DUBBO:
|
||||
name = "MsApiDubboRequestForm";
|
||||
break;
|
||||
case RequestFactory.TYPES.SQL:
|
||||
name = "MsApiSqlRequestForm";
|
||||
break;
|
||||
default:
|
||||
name = "MsApiHttpRequestForm";
|
||||
}
|
||||
return name;
|
||||
},
|
||||
isCompleted() {
|
||||
return !!this.request.debugReport;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
debugReportId() {
|
||||
this.getReport();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
//兼容旧版本 beanshell
|
||||
if (!this.request.jsr223PreProcessor.script && this.request.beanShellPreProcessor) {
|
||||
this.request.jsr223PreProcessor = new JSR223Processor(this.request.beanShellPreProcessor);
|
||||
}
|
||||
if (!this.request.jsr223PostProcessor.script && this.request.beanShellPostProcessor) {
|
||||
this.request.jsr223PostProcessor = new JSR223Processor(this.request.beanShellPostProcessor);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getReport() {
|
||||
if (this.debugReportId) {
|
||||
this.debugReportLoading = true;
|
||||
this.showDebugReport = true;
|
||||
this.request.debugReport = {};
|
||||
let url = "/api/report/get/" + this.debugReportId;
|
||||
this.$get(url, response => {
|
||||
let report = response.data || {};
|
||||
let res = {};
|
||||
if (response.data) {
|
||||
try {
|
||||
res = JSON.parse(report.content);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
if (res) {
|
||||
this.debugReportLoading = false;
|
||||
this.request.debugReport = res;
|
||||
if (res.scenarios && res.scenarios.length > 0) {
|
||||
this.request.debugScenario = res.scenarios[0];
|
||||
this.request.debugRequestResult = this.request.debugScenario.requestResults[0];
|
||||
this.deleteReport(this.debugReportId);
|
||||
} else {
|
||||
this.request.debugScenario = new Scenario();
|
||||
this.request.debugRequestResult = {responseResult: {}, subRequestResults: []};
|
||||
}
|
||||
this.$refs.msDebugResult.reload();
|
||||
} else {
|
||||
setTimeout(this.getReport, 2000)
|
||||
}
|
||||
} else {
|
||||
this.debugReportLoading = false;
|
||||
isCompleted() {
|
||||
return !!this.request.debugReport;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
debugReportId() {
|
||||
this.getReport();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
//兼容旧版本 beanshell
|
||||
if (!this.request.jsr223PreProcessor.script && this.request.beanShellPreProcessor) {
|
||||
this.request.jsr223PreProcessor = new JSR223Processor(this.request.beanShellPreProcessor);
|
||||
}
|
||||
if (!this.request.jsr223PostProcessor.script && this.request.beanShellPostProcessor) {
|
||||
this.request.jsr223PostProcessor = new JSR223Processor(this.request.beanShellPostProcessor);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getReport() {
|
||||
if (this.debugReportId) {
|
||||
this.debugReportLoading = true;
|
||||
this.showDebugReport = true;
|
||||
this.request.debugReport = {};
|
||||
let url = "/api/report/get/" + this.debugReportId;
|
||||
this.$get(url, response => {
|
||||
let report = response.data || {};
|
||||
let res = {};
|
||||
if (response.data) {
|
||||
try {
|
||||
res = JSON.parse(report.content);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
deleteReport(reportId) {
|
||||
this.$post('/api/report/delete', {id: reportId});
|
||||
},
|
||||
runDebug() {
|
||||
this.$emit('runDebug', this.request);
|
||||
if (res) {
|
||||
this.debugReportLoading = false;
|
||||
this.request.debugReport = res;
|
||||
if (res.scenarios && res.scenarios.length > 0) {
|
||||
this.request.debugScenario = res.scenarios[0];
|
||||
this.request.debugRequestResult = this.request.debugScenario.requestResults[0];
|
||||
this.deleteReport(this.debugReportId);
|
||||
} else {
|
||||
this.request.debugScenario = new Scenario();
|
||||
this.request.debugRequestResult = {responseResult: {}, subRequestResults: []};
|
||||
}
|
||||
this.$refs.msDebugResult.reload();
|
||||
} else {
|
||||
setTimeout(this.getReport, 2000)
|
||||
}
|
||||
} else {
|
||||
this.debugReportLoading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
deleteReport(reportId) {
|
||||
this.$post('/api/report/delete', {id: reportId});
|
||||
},
|
||||
runDebug() {
|
||||
this.$emit('runDebug', this.request);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.scenario-results {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.scenario-results {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.request-form >>> .debug-button {
|
||||
margin-left: auto;
|
||||
display: block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.request-form >>> .debug-button {
|
||||
margin-left: auto;
|
||||
display: block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
<template>
|
||||
<el-form class="tcp" :model="request" :rules="rules" ref="request" label-width="120px" :disabled="isReadOnly">
|
||||
|
||||
<el-form-item :label="$t('api_test.request.name')" prop="name">
|
||||
<el-input v-model="request.name" maxlength="300" show-word-limit/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="TCPClient" prop="classname">
|
||||
<el-select v-model="request.classname" style="width: 100%">
|
||||
<el-option v-for="c in classes" :key="c" :label="c" :value="c"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('api_test.request.tcp.server')" prop="server">
|
||||
<el-input v-model="request.server" maxlength="300" show-word-limit/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('api_test.request.tcp.port')" prop="port">
|
||||
<el-input-number v-model="request.port" controls-position="right" :min="0" :max="65535"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('api_test.request.tcp.connect')" prop="ctimeout">
|
||||
<el-input-number v-model="request.ctimeout" controls-position="right" :min="0"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('api_test.request.tcp.response')" prop="timeout">
|
||||
<el-input-number v-model="request.timeout" controls-position="right" :min="0"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="4">
|
||||
<el-form-item>
|
||||
<el-switch
|
||||
v-model="request.useEnvironment"
|
||||
:active-text="$t('api_test.request.refer_to_environment')"
|
||||
@change="useEnvironmentChange">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label-width="0">
|
||||
<el-switch
|
||||
v-model="request.reUseConnection"
|
||||
:active-text="$t('api_test.request.tcp.re_use_connection')">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label-width="0">
|
||||
<el-switch
|
||||
v-model="request.closeConnection"
|
||||
:active-text="$t('api_test.request.tcp.close_connection')">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label-width="0">
|
||||
<el-switch
|
||||
v-model="request.nodelay"
|
||||
:active-text="$t('api_test.request.tcp.no_delay')">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('api_test.request.tcp.so_linger')" prop="soLinger">
|
||||
<el-input v-model="request.soLinger"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item :label="$t('api_test.request.tcp.eol_byte')" prop="eolByte">
|
||||
<el-input v-model="request.eolByte"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item :label="$t('api_test.request.tcp.request')" prop="request">
|
||||
<el-input type="textarea" v-model="request.request" :autosize="{minRows: 4, maxRows: 6}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('api_test.request.tcp.username')" prop="username">
|
||||
<el-input v-model="request.username" maxlength="100" show-word-limit/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item :label="$t('api_test.request.tcp.password')" prop="password">
|
||||
<el-input v-model="request.password" maxlength="30" show-word-limit show-password
|
||||
autocomplete="new-password"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-button :disabled="!request.enable || !scenario.enable || isReadOnly" class="debug-button" size="small"
|
||||
type="primary" @click="runDebug">{{ $t('api_test.request.debug') }}
|
||||
</el-button>
|
||||
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="$t('api_test.request.assertions.label')" name="assertions">
|
||||
<ms-api-assertions :is-read-only="isReadOnly" :assertions="request.assertions"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.request.extract.label')" name="extract">
|
||||
<ms-api-extract :is-read-only="isReadOnly" :extract="request.extract"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.request.processor.pre_exec_script')" name="beanShellPreProcessor">
|
||||
<ms-jsr233-processor :is-read-only="isReadOnly" :jsr223-processor="request.jsr223PreProcessor"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('api_test.request.processor.post_exec_script')" name="beanShellPostProcessor">
|
||||
<ms-jsr233-processor :is-read-only="isReadOnly" :jsr223-processor="request.jsr223PostProcessor"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {Scenario, TCPRequest} from "@/business/components/api/test/model/ScenarioModel";
|
||||
import MsApiAssertions from "@/business/components/api/test/components/assertion/ApiAssertions";
|
||||
import MsApiExtract from "@/business/components/api/test/components/extract/ApiExtract";
|
||||
import MsJsr233Processor from "@/business/components/api/test/components/processor/Jsr233Processor";
|
||||
|
||||
export default {
|
||||
name: "MsApiTcpRequestForm",
|
||||
components: {MsJsr233Processor, MsApiExtract, MsApiAssertions},
|
||||
props: {
|
||||
request: TCPRequest,
|
||||
scenario: Scenario,
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: "assertions",
|
||||
classes: TCPRequest.CLASSES,
|
||||
rules: {
|
||||
server: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('commons.required', [this.$t('api_test.request.tcp.server')]),
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
useEnvironmentChange(value) {
|
||||
if (value && !this.request.environment) {
|
||||
this.$error(this.$t('api_test.request.please_add_environment_to_scenario'), 2000);
|
||||
this.request.useEnvironment = false;
|
||||
}
|
||||
this.$refs["request"].clearValidate();
|
||||
},
|
||||
runDebug() {
|
||||
this.$emit('runDebug');
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tcp >>> .el-input-number {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
|
@ -291,6 +291,26 @@ export class JDBCSampler extends DefaultTestElement {
|
|||
}
|
||||
}
|
||||
|
||||
export class TCPSampler extends DefaultTestElement {
|
||||
constructor(testName, request = {}) {
|
||||
super('TCPSampler', 'TCPSamplerGui', 'TCPSampler', testName);
|
||||
|
||||
this.stringProp("TCPSampler.classname", request.classname);
|
||||
this.stringProp("TCPSampler.server", request.server);
|
||||
this.stringProp("TCPSampler.port", request.port);
|
||||
this.stringProp("TCPSampler.ctimeout", request.ctimeout);
|
||||
this.stringProp("TCPSampler.timeout", request.timeout);
|
||||
this.boolProp("TCPSampler.reUseConnection", request.reUseConnection);
|
||||
this.boolProp("TCPSampler.nodelay", request.nodelay);
|
||||
this.boolProp("TCPSampler.closeConnection", request.closeConnection);
|
||||
this.stringProp("TCPSampler.soLinger", request.soLinger);
|
||||
this.stringProp("TCPSampler.EolByte", request.eolByte);
|
||||
this.stringProp("TCPSampler.request", request.request);
|
||||
this.stringProp("ConfigTestElement.username", request.username);
|
||||
this.stringProp("ConfigTestElement.password", request.password);
|
||||
}
|
||||
}
|
||||
|
||||
export class HTTPSamplerProxy extends DefaultTestElement {
|
||||
constructor(testName, options = {}) {
|
||||
super('HTTPSamplerProxy', 'HttpTestSampleGui', 'HTTPSamplerProxy', testName);
|
||||
|
@ -335,7 +355,7 @@ export class HTTPSamplerArguments extends Element {
|
|||
|
||||
let collectionProp = this.collectionProp('Arguments.arguments');
|
||||
this.args.forEach(arg => {
|
||||
if (arg.enable === true || arg.enable === undefined) { // 非禁用的条件加入执行
|
||||
if (arg.enable === true || arg.enable === undefined) { // 非禁用的条件加入执行
|
||||
let elementProp = collectionProp.elementProp(arg.name, 'HTTPArgument');
|
||||
elementProp.boolProp('HTTPArgument.always_encode', arg.encode, true);
|
||||
elementProp.boolProp('HTTPArgument.use_equals', arg.equals, true);
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
ThreadGroup,
|
||||
XPath2Extractor,
|
||||
IfController as JMXIfController,
|
||||
ConstantTimer as JMXConstantTimer,
|
||||
ConstantTimer as JMXConstantTimer, TCPSampler,
|
||||
} from "./JMX";
|
||||
import Mock from "mockjs";
|
||||
import {funcFilters} from "@/common/js/func-filter";
|
||||
|
@ -286,6 +286,7 @@ export class RequestFactory {
|
|||
HTTP: "HTTP",
|
||||
DUBBO: "DUBBO",
|
||||
SQL: "SQL",
|
||||
TCP: "TCP",
|
||||
}
|
||||
|
||||
constructor(options = {}) {
|
||||
|
@ -295,6 +296,8 @@ export class RequestFactory {
|
|||
return new DubboRequest(options);
|
||||
case RequestFactory.TYPES.SQL:
|
||||
return new SqlRequest(options);
|
||||
case RequestFactory.TYPES.TCP:
|
||||
return new TCPRequest(options);
|
||||
default:
|
||||
return new HttpRequest(options);
|
||||
}
|
||||
|
@ -305,9 +308,15 @@ export class Request extends BaseConfig {
|
|||
constructor(type, options = {}) {
|
||||
super();
|
||||
this.type = type;
|
||||
options.id = options.id || uuid();
|
||||
this.timer = options.timer = new ConstantTimer(options.timer);
|
||||
this.controller = options.controller = new IfController(options.controller);
|
||||
this.id = options.id || uuid();
|
||||
this.name = options.name;
|
||||
this.enable = options.enable === undefined ? true : options.enable;
|
||||
this.assertions = new Assertions(options.assertions);
|
||||
this.extract = new Extract(options.extract);
|
||||
this.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
|
||||
this.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
|
||||
this.timer = new ConstantTimer(options.timer);
|
||||
this.controller = new IfController(options.controller);
|
||||
}
|
||||
|
||||
showType() {
|
||||
|
@ -322,41 +331,22 @@ export class Request extends BaseConfig {
|
|||
export class HttpRequest extends Request {
|
||||
constructor(options) {
|
||||
super(RequestFactory.TYPES.HTTP, options);
|
||||
this.name = undefined;
|
||||
this.url = undefined;
|
||||
this.path = undefined;
|
||||
this.method = undefined;
|
||||
this.url = options.url;
|
||||
this.path = options.path;
|
||||
this.method = options.method || "GET";
|
||||
this.parameters = [];
|
||||
this.headers = [];
|
||||
this.body = undefined;
|
||||
this.assertions = undefined;
|
||||
this.extract = undefined;
|
||||
this.environment = undefined;
|
||||
this.useEnvironment = undefined;
|
||||
this.body = new Body(options.body);
|
||||
this.environment = options.environment;
|
||||
this.useEnvironment = options.useEnvironment;
|
||||
this.debugReport = undefined;
|
||||
this.beanShellPreProcessor = undefined;
|
||||
this.beanShellPostProcessor = undefined;
|
||||
this.jsr223PreProcessor = undefined;
|
||||
this.jsr223PostProcessor = undefined;
|
||||
this.enable = true;
|
||||
this.connectTimeout = 60 * 1000;
|
||||
this.responseTimeout = undefined;
|
||||
this.followRedirects = true;
|
||||
this.connectTimeout = options.connectTimeout || 60 * 1000;
|
||||
this.responseTimeout = options.responseTimeout;
|
||||
this.followRedirects = options.followRedirects === undefined ? true : options.followRedirects;
|
||||
|
||||
this.set(options);
|
||||
this.sets({parameters: KeyValue, headers: KeyValue}, options);
|
||||
}
|
||||
|
||||
initOptions(options = {}) {
|
||||
options.method = options.method || "GET";
|
||||
options.body = new Body(options.body);
|
||||
options.assertions = new Assertions(options.assertions);
|
||||
options.extract = new Extract(options.extract);
|
||||
options.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
|
||||
options.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
|
||||
return options;
|
||||
}
|
||||
|
||||
isValid(environmentId, environment) {
|
||||
if (this.enable) {
|
||||
if (this.useEnvironment) {
|
||||
|
@ -412,7 +402,6 @@ export class DubboRequest extends Request {
|
|||
|
||||
constructor(options = {}) {
|
||||
super(RequestFactory.TYPES.DUBBO, options);
|
||||
this.name = options.name;
|
||||
this.protocol = options.protocol || DubboRequest.PROTOCOLS.DUBBO;
|
||||
this.interface = options.interface;
|
||||
this.method = options.method;
|
||||
|
@ -421,16 +410,9 @@ export class DubboRequest extends Request {
|
|||
this.consumerAndService = new ConsumerAndService(options.consumerAndService);
|
||||
this.args = [];
|
||||
this.attachmentArgs = [];
|
||||
this.assertions = new Assertions(options.assertions);
|
||||
this.extract = new Extract(options.extract);
|
||||
// Scenario.dubboConfig
|
||||
this.dubboConfig = undefined;
|
||||
this.debugReport = undefined;
|
||||
this.beanShellPreProcessor = new BeanShellProcessor(options.beanShellPreProcessor);
|
||||
this.beanShellPostProcessor = new BeanShellProcessor(options.beanShellPostProcessor);
|
||||
this.enable = options.enable === undefined ? true : options.enable;
|
||||
this.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
|
||||
this.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
|
||||
|
||||
this.sets({args: KeyValue, attachmentArgs: KeyValue}, options);
|
||||
}
|
||||
|
@ -485,8 +467,6 @@ export class SqlRequest extends Request {
|
|||
|
||||
constructor(options = {}) {
|
||||
super(RequestFactory.TYPES.SQL, options);
|
||||
this.id = options.id || uuid();
|
||||
this.name = options.name;
|
||||
this.useEnvironment = options.useEnvironment;
|
||||
this.resultVariable = options.resultVariable;
|
||||
this.variableNames = options.variableNames;
|
||||
|
@ -495,11 +475,6 @@ export class SqlRequest extends Request {
|
|||
this.query = options.query;
|
||||
// this.queryType = options.queryType;
|
||||
this.queryTimeout = options.queryTimeout || 60000;
|
||||
this.enable = options.enable === undefined ? true : options.enable;
|
||||
this.assertions = new Assertions(options.assertions);
|
||||
this.extract = new Extract(options.extract);
|
||||
this.jsr223PreProcessor = new JSR223Processor(options.jsr223PreProcessor);
|
||||
this.jsr223PostProcessor = new JSR223Processor(options.jsr223PostProcessor);
|
||||
|
||||
this.sets({args: KeyValue, attachmentArgs: KeyValue}, options);
|
||||
}
|
||||
|
@ -537,6 +512,59 @@ export class SqlRequest extends Request {
|
|||
}
|
||||
}
|
||||
|
||||
export class TCPRequest extends Request {
|
||||
static CLASSES = ["TCPClientImpl", "BinaryTCPClientImpl", "LengthPrefixedBinaryTCPClientImpl"]
|
||||
|
||||
constructor(options = {}) {
|
||||
super(RequestFactory.TYPES.TCP, options);
|
||||
this.useEnvironment = options.useEnvironment;
|
||||
this.debugReport = undefined;
|
||||
|
||||
this.classname = options.classname || TCPRequest.CLASSES[0];
|
||||
this.server = options.server;
|
||||
this.port = options.port;
|
||||
this.ctimeout = options.ctimeout; // Connect
|
||||
this.timeout = options.timeout; // Response
|
||||
|
||||
this.reUseConnection = options.reUseConnection === undefined ? true : options.reUseConnection;
|
||||
this.nodelay = options.nodelay === undefined ? false : options.nodelay;
|
||||
this.closeConnection = options.closeConnection === undefined ? false : options.closeConnection;
|
||||
this.soLinger = options.soLinger;
|
||||
this.eolByte = options.eolByte;
|
||||
|
||||
this.request = options.request;
|
||||
|
||||
this.username = options.username;
|
||||
this.password = options.password;
|
||||
}
|
||||
|
||||
isValid() {
|
||||
if (this.enable) {
|
||||
if (!this.server) {
|
||||
return {
|
||||
isValid: false,
|
||||
info: 'api_test.request.tcp.server_cannot_be_empty'
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
isValid: true
|
||||
}
|
||||
}
|
||||
|
||||
showType() {
|
||||
return "TCP";
|
||||
}
|
||||
|
||||
showMethod() {
|
||||
return "TCP";
|
||||
}
|
||||
|
||||
clone() {
|
||||
return new TCPRequest(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class ConfigCenter extends BaseConfig {
|
||||
static PROTOCOLS = ["zookeeper", "nacos", "apollo"];
|
||||
|
@ -658,7 +686,7 @@ export class Body extends BaseConfig {
|
|||
export class KeyValue extends BaseConfig {
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
options.enable = options.enable != false ? true : false;
|
||||
options.enable = options.enable === undefined ? true : options.enable;
|
||||
|
||||
super();
|
||||
this.name = undefined;
|
||||
|
@ -1063,6 +1091,8 @@ class JMXGenerator {
|
|||
} else if (request instanceof SqlRequest) {
|
||||
request.dataSource = scenario.databaseConfigMap.get(request.dataSource);
|
||||
sampler = new JDBCSampler(request.name || "", request);
|
||||
} else if (request instanceof TCPRequest) {
|
||||
sampler = new TCPSampler(request.name || "", request);
|
||||
}
|
||||
|
||||
this.addRequestExtractor(sampler, request);
|
||||
|
@ -1297,7 +1327,7 @@ class JMXGenerator {
|
|||
body.push({name: '', value: request.body.raw, encode: false, enable: true});
|
||||
}
|
||||
|
||||
if (request.method != 'GET') {
|
||||
if (request.method !== 'GET') {
|
||||
httpSamplerProxy.add(new HTTPSamplerArguments(body));
|
||||
}
|
||||
}
|
||||
|
@ -1306,7 +1336,7 @@ class JMXGenerator {
|
|||
let files = [];
|
||||
let kvs = this.filterKVFile(request.body.kvs);
|
||||
kvs.forEach(kv => {
|
||||
if ((kv.enable != false) && kv.files) {
|
||||
if ((kv.enable !== false) && kv.files) {
|
||||
kv.files.forEach(file => {
|
||||
let arg = {};
|
||||
arg.name = kv.name;
|
||||
|
|
|
@ -113,6 +113,7 @@ export default {
|
|||
formatErr: 'Format Error',
|
||||
id: 'ID',
|
||||
cannot_be_null: 'not null ',
|
||||
required: "{0} is required",
|
||||
millisecond: 'ms',
|
||||
please_upload: 'Please upload file',
|
||||
reference_documentation: "Reference documentation",
|
||||
|
@ -555,22 +556,38 @@ export default {
|
|||
input_registry_center: "Please enter the registry center",
|
||||
input_consumer_service: "Please enter the consumer & service",
|
||||
check_registry_center: "Can't get interface list, please check the registry center",
|
||||
}
|
||||
},
|
||||
sql: {
|
||||
dataSource: "Data Source",
|
||||
sql_script: "Sql Script",
|
||||
timeout: "Timeout(ms)",
|
||||
database_driver: "Driver",
|
||||
database_url: "Database URL",
|
||||
username: "Username",
|
||||
password: "Password",
|
||||
pool_max: "Max Number of Configuration",
|
||||
query_timeout: "Max Wait(ms)",
|
||||
name_cannot_be_empty: "SQL request name cannot be empty",
|
||||
dataSource_cannot_be_empty: "SQL request datasource cannot be empty",
|
||||
result_variable: "Result variable",
|
||||
variable_names: "Variable names",
|
||||
},
|
||||
sql: {
|
||||
dataSource: "Data Source",
|
||||
sql_script: "Sql Script",
|
||||
timeout: "Timeout(ms)",
|
||||
database_driver: "Driver",
|
||||
database_url: "Database URL",
|
||||
username: "Username",
|
||||
password: "Password",
|
||||
pool_max: "Max Number of Configuration",
|
||||
query_timeout: "Max Wait(ms)",
|
||||
name_cannot_be_empty: "SQL request name cannot be empty",
|
||||
dataSource_cannot_be_empty: "SQL request datasource cannot be empty",
|
||||
result_variable: "Result variable",
|
||||
variable_names: "Variable names",
|
||||
},
|
||||
tcp: {
|
||||
server: "Server Name or IP",
|
||||
port: "Port Number",
|
||||
connect: "Connect(ms)",
|
||||
response: "Response(ms)",
|
||||
re_use_connection: "Re-use connection",
|
||||
no_delay: "Set NoDelay",
|
||||
close_connection: "Close connection",
|
||||
so_linger: "SO LINGER",
|
||||
eol_byte: "End of line byte value",
|
||||
request: "Text to Send",
|
||||
username: "Username",
|
||||
password: "Password",
|
||||
login: "Login Configuration",
|
||||
server_cannot_be_empty: "Server name or IP cannot be empty",
|
||||
},
|
||||
},
|
||||
api_import: {
|
||||
label: "Import",
|
||||
|
|
|
@ -116,6 +116,7 @@ export default {
|
|||
id: 'ID',
|
||||
millisecond: '毫秒',
|
||||
cannot_be_null: '不能为空',
|
||||
required: "{0}是必填的",
|
||||
already_exists: '名称不能重复',
|
||||
date: {
|
||||
select_date: '选择日期',
|
||||
|
@ -572,6 +573,22 @@ export default {
|
|||
dataSource_cannot_be_empty: "SQL请求数据源不能为空",
|
||||
result_variable: "存储结果",
|
||||
variable_names: "按列存储",
|
||||
},
|
||||
tcp: {
|
||||
server: "服务器名或IP",
|
||||
port: "端口",
|
||||
connect: "连接(ms)",
|
||||
response: "响应(ms)",
|
||||
re_use_connection: "Re-use connection",
|
||||
no_delay: "设置无延迟",
|
||||
close_connection: "关闭连接",
|
||||
so_linger: "SO LINGER",
|
||||
eol_byte: "行尾(EOL)字节值",
|
||||
request: "要发送的文本",
|
||||
username: "用户名",
|
||||
password: "密码",
|
||||
login: "登录设置",
|
||||
server_cannot_be_empty: "服务器名或IP不能为空",
|
||||
}
|
||||
},
|
||||
api_import: {
|
||||
|
|
|
@ -116,6 +116,7 @@ export default {
|
|||
id: 'ID',
|
||||
millisecond: '毫秒',
|
||||
cannot_be_null: '不能為空',
|
||||
required: "{0}是必填的",
|
||||
already_exists: '名稱不能重復',
|
||||
date: {
|
||||
select_date: '選擇日期',
|
||||
|
@ -574,6 +575,22 @@ export default {
|
|||
variable_names: "按列存儲",
|
||||
}
|
||||
},
|
||||
tcp: {
|
||||
server: "服務器名或IP",
|
||||
port: "端口",
|
||||
connect: "連接(ms)",
|
||||
response: "響應(ms)",
|
||||
re_use_connection: "Re-use connection",
|
||||
no_delay: "設置無延遲",
|
||||
close_connection: "關閉連接",
|
||||
so_linger: "SO LINGER",
|
||||
eol_byte: "行尾(EOL)字節值",
|
||||
request: "要發送的文本",
|
||||
username: "用戶名",
|
||||
password: "密碼",
|
||||
login: "登錄設置",
|
||||
server_cannot_be_empty: "服務器名或IP不能為空",
|
||||
},
|
||||
api_import: {
|
||||
label: "導入",
|
||||
title: "接口測試導入",
|
||||
|
|
Loading…
Reference in New Issue