feat(接口测试): 增加TCP协议的接口测试

This commit is contained in:
q4speed 2020-10-09 18:08:49 +08:00
parent b63a3ebbbc
commit 8582a4f04f
14 changed files with 507 additions and 177 deletions

View File

@ -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>

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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";
}

View File

@ -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;
}

View File

@ -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/>

View File

@ -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>

View File

@ -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>

View File

@ -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);

View File

@ -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;

View File

@ -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",

View File

@ -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: {

View File

@ -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: "接口測試導入",