diff --git a/README.md b/README.md index fee6cfc74a..d13db07b6b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -* nGrinder 3.5.1 has been released. See https://github.com/naver/ngrinder/releases +* nGrinder 3.5.1-p1 has been released. See https://github.com/naver/ngrinder/releases nGrinder ======== diff --git a/RELEASE-NOTE.md b/RELEASE-NOTE.md index 47f88eb682..e9c29bba7d 100644 --- a/RELEASE-NOTE.md +++ b/RELEASE-NOTE.md @@ -1,59 +1,66 @@ +3.5.1-p1 (2020.09.01) +================== +- Changes + * Add additional groovy dependencies. + - json, xml, sql, datetime, templates. + * Change webpack default profile. + 3.5.1 (2020.08.31) ================== -* Changes +- Changes * Support Java 11. - * nGrinder now supports Java 11. Controller & Agent supports Java 1.8 or above. - * Bump several libraries version up. + - nGrinder now supports Java 11. Controller & Agent supports Java 1.8 or above. + - Bump several libraries version up. -* Trivial Fix +- Trivial Fix * Remove mobile phone column from NUSER table. * Make several UI improvements. 3.5.0 (2020.07.30) ================== -* New Feature +- New Feature * Introduce server mode agent - * In previous version, nGrinder agents made TCP connections from agent to controller and this made hard to locate a nGrinder controller behind a firewall. From version 3.5.0, nGrinder introduces server mode agent so that a controller make a connection from a controller to agents. - * See https://github.com/naver/ngrinder/wiki/server-mode-agent + - In previous version, nGrinder agents made TCP connections from agent to controller and this made hard to locate a nGrinder controller behind a firewall. From version 3.5.0, nGrinder introduces server mode agent so that a controller make a connection from a controller to agents. + - See https://github.com/naver/ngrinder/wiki/server-mode-agent * Update agents automatically - * When the test is executed with older version of agent, it triggers agent auto update. + - When the test is executed with older version of agent, it triggers agent auto update. * Support GitHub script storage - * Users can save and run their test script saved in not only embedded SVN server but also external GitHub repository. GitHub enterprise deployed in each own organization is also supported. - * See https://github.com/naver/ngrinder/wiki/github-script-storage + - Users can save and run their test script saved in not only embedded SVN server but also external GitHub repository. GitHub enterprise deployed in each own organization is also supported. + - See https://github.com/naver/ngrinder/wiki/github-script-storage * Support MySQL - * Since 3.5.0, we support H2 and MySQL as databases and fade out Cubrid and provide cubrid-to-mysql migration script. - * See https://github.com/naver/ngrinder/wiki/mysql-migration + - Since 3.5.0, we support H2 and MySQL as databases and fade out Cubrid and provide cubrid-to-mysql migration script. + - See https://github.com/naver/ngrinder/wiki/mysql-migration * Improve test restart time - * In previous version, nGrinder agent doesn't cache executed test lib & resources, Therefore, it took long time to execute tests in the case of using large amount of libraries and resource. From nGrinder 3.5.0, the test execution is much faster by sending only changed test resources to agents + - In previous version, nGrinder agent doesn't cache executed test lib & resources, Therefore, it took long time to execute tests in the case of using large amount of libraries and resource. From nGrinder 3.5.0, the test execution is much faster by sending only changed test resources to agents * Fade out nGrinder-recorder - * nGrinder-recorder is no longer supported. + - nGrinder-recorder is no longer supported. * Support multiple user defined statistics - * See https://github.com/naver/ngrinder/wiki/multiple-user-defined-statistic-in-ngrinder + - See https://github.com/naver/ngrinder/wiki/multiple-user-defined-statistic-in-ngrinder * Ignore error count - * Some of users want to continue testing even if there were many errors in the test. So nGrinder 3.5.0 supports that as a test option in advanced configuration panel + - Some of users want to continue testing even if there were many errors in the test. So nGrinder 3.5.0 supports that as a test option in advanced configuration panel * Support custom classpath - * If you want to set classpath for test scripts, you can use this. - * See https://github.com/naver/ngrinder/wiki/custom-classpath + - If you want to set classpath for test scripts, you can use this. + - See https://github.com/naver/ngrinder/wiki/custom-classpath -* Modernize +- Modernize * Back-end - * Spring boot - * Change from spring framework 4 to spring boot 2. - * Remove embedded Jetty. - * Hazelcast - * Use Hazelcast to share data among clusters - * Reduce load of database. - * Gradle - * Use Gradle 6.3 as a build system. + - Spring boot + - Change from spring framework 4 to spring boot 2. + - Remove embedded Jetty. + - Hazelcast + - Use Hazelcast to share data among clusters + - Reduce load of database. + - Gradle + - Use Gradle 6.3 as a build system. * Front-end - * Vue.js - * Introduce SPA for imporve responsibility & usability. - * Use webpack as a module bundler. - * UX/UI - * Use Billboard.js to draw charts. - * Bump bootstrap up from 2 to 4. - -* Bug fix + - Vue.js + - Introduce SPA for imporve responsibility & usability. + - Use webpack as a module bundler. + - UX/UI + - Use Billboard.js to draw charts. + - Bump bootstrap up from 2 to 4. + +- Bug fix * #490 Fix log file name for agent command line * #558 Fix agent state API to work in private agent * #571 Prevent zombie agents from remaining in distributed cache diff --git a/build.gradle b/build.gradle index 14d3a0aee7..9dbcf5c330 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ allprojects { apply plugin: "idea" group = "org.ngrinder" - version = "3.5.1" + version = "3.5.1-p1" idea { module { @@ -29,7 +29,7 @@ subprojects { targetCompatibility = 1.8 ext { - profile = project.hasProperty('profile') ? profile : 'development' + profile = project.hasProperty('profile') ? profile : 'production' slf4j_version = "1.7.28" spring_security_version = "5.3.4.RELEASE" spring_boot_version = "2.3.3.RELEASE" @@ -39,6 +39,7 @@ subprojects { mockito_version = "2.23.4" handlebars_version = "4.0.5" jackson_version = "2.11.2" + groovy_version = "3.0.5" } repositories { diff --git a/ngrinder-controller/build.gradle b/ngrinder-controller/build.gradle index af6ac1b998..7c883bc772 100644 --- a/ngrinder-controller/build.gradle +++ b/ngrinder-controller/build.gradle @@ -74,7 +74,7 @@ dependencies { compile (group: "com.hazelcast", name: "hazelcast-spring", version: hazelcast_version) compile (group: "org.kohsuke", name: "github-api", version: "1.99") compile (group: "commons-validator", name: "commons-validator", version: "1.6") - compile (group: 'org.codehaus.groovy', name: 'groovy-jsr223', version: '3.0.5') + compile (group: 'org.codehaus.groovy', name: 'groovy-jsr223', version: groovy_version) compileOnly (group: "org.projectlombok", name: "lombok", version: "1.18.8") annotationProcessor (group: "org.projectlombok", name: "lombok", version: "1.18.8") diff --git a/ngrinder-controller/src/main/java/org/ngrinder/agent/service/AgentPackageService.java b/ngrinder-controller/src/main/java/org/ngrinder/agent/service/AgentPackageService.java index 2d877cbc6a..1488f34ede 100644 --- a/ngrinder-controller/src/main/java/org/ngrinder/agent/service/AgentPackageService.java +++ b/ngrinder-controller/src/main/java/org/ngrinder/agent/service/AgentPackageService.java @@ -22,6 +22,7 @@ import static org.apache.commons.lang.StringUtils.isNotEmpty; import static org.ngrinder.common.util.CompressionUtils.*; import static org.ngrinder.common.util.EncodingUtils.decodePathWithUTF8; +import static org.ngrinder.common.util.StringUtils.replaceLast; /** * Agent package service. @@ -125,11 +126,13 @@ public boolean isJar(File libFile) { * @param libs lib set * @return true if dependent lib */ - private boolean isDependentLib(File libFile, Set libs) { + protected boolean isDependentLib(File libFile, Set libs) { if (libFile.getName().contains("grinder-3.9.1.jar")) { return false; } - String name = libFile.getName().replace("-SNAPSHOT", "").replace("-GA", ""); + + // Replace release types (-SNAPSHOT, -GA, -p1, ...) + String name = replaceLast(libFile.getName(), "-[a-zA-Z][a-zA-Z1-9]+\\.", "."); final int libVersionStartIndex = name.lastIndexOf("-"); name = name.substring(0, (libVersionStartIndex == -1) ? name.lastIndexOf(".") : libVersionStartIndex); return libs.contains(name); diff --git a/ngrinder-controller/src/main/java/org/ngrinder/common/util/StringUtils.java b/ngrinder-controller/src/main/java/org/ngrinder/common/util/StringUtils.java new file mode 100644 index 0000000000..833398d61b --- /dev/null +++ b/ngrinder-controller/src/main/java/org/ngrinder/common/util/StringUtils.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012-present NAVER Corp. + * + * This file is part of The nGrinder software distribution. Refer to + * the file LICENSE which is part of The nGrinder distribution for + * licensing details. The nGrinder distribution is available on the + * Internet at https://naver.github.io/ngrinder + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.ngrinder.common.util; + +/** + * String utility. + * + * @since 3.5.1-p1 + */ +public class StringUtils { + + public static String replaceLast(String str, String regex, String replacement) { + return str.replaceFirst("(?s)(.*)" + regex, "$1" + replacement); + } +} diff --git a/ngrinder-controller/src/main/resources/application.yml b/ngrinder-controller/src/main/resources/application.yml index 51c275c6a1..fda46d12c0 100644 --- a/ngrinder-controller/src/main/resources/application.yml +++ b/ngrinder-controller/src/main/resources/application.yml @@ -1,5 +1,5 @@ ngrinder: - version: 3.5.1 + version: 3.5.1-p1 server: default-encoding: UTF-8 diff --git a/ngrinder-controller/src/main/resources/script_template/groovy_maven/pom.xml b/ngrinder-controller/src/main/resources/script_template/groovy_maven/pom.xml index b1898c344b..1e79c19c06 100644 --- a/ngrinder-controller/src/main/resources/script_template/groovy_maven/pom.xml +++ b/ngrinder-controller/src/main/resources/script_template/groovy_maven/pom.xml @@ -6,7 +6,7 @@ 0.0.1 - 3.5.1 + 3.5.1-p1 1.8 1.8 UTF-8 diff --git a/ngrinder-controller/src/test/java/org/ngrinder/agent/service/AgentPackageServiceTest.java b/ngrinder-controller/src/test/java/org/ngrinder/agent/service/AgentPackageServiceTest.java new file mode 100644 index 0000000000..8bda0e7698 --- /dev/null +++ b/ngrinder-controller/src/test/java/org/ngrinder/agent/service/AgentPackageServiceTest.java @@ -0,0 +1,40 @@ +package org.ngrinder.agent.service; + +import org.junit.Test; +import org.ngrinder.AbstractNGrinderTransactionalTest; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.File; +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class AgentPackageServiceTest extends AbstractNGrinderTransactionalTest { + + @Autowired + private AgentPackageService agentPackageService; + + @Test + public void testIsDependentLib() { + Set libs = new HashSet<>(); + libs.add("ngrinder-groovy"); + libs.add("ngrinder-core"); + libs.add("ngrinder-runtime"); + libs.add("javassist"); + libs.add("jna"); + libs.add("jboss-transaction-api_1.2_spec"); + + assertTrue(agentPackageService.isDependentLib(new File("ngrinder-core-3.5.1-SNAPSHOT.jar"), libs)); + assertTrue(agentPackageService.isDependentLib(new File("ngrinder-groovy-3.5.1.jar"), libs)); + assertTrue(agentPackageService.isDependentLib(new File("ngrinder-runtime-3.5.1-p4.jar"), libs)); + assertTrue(agentPackageService.isDependentLib(new File("javassist-3.24.0-GA.jar"), libs)); + assertTrue(agentPackageService.isDependentLib(new File("jna-5.6.0.jar"), libs)); + assertTrue(agentPackageService.isDependentLib(new File("jboss-transaction-api_1.2_spec-1.1.1.Final.jar"), libs)); + + assertFalse(agentPackageService.isDependentLib(new File("jcommander-1.32.jar"), libs)); + assertFalse(agentPackageService.isDependentLib(new File("commons-collections-3.2.1.jar"), libs)); + } + +} diff --git a/ngrinder-controller/src/test/java/org/ngrinder/common/util/StringUtilsTest.java b/ngrinder-controller/src/test/java/org/ngrinder/common/util/StringUtilsTest.java new file mode 100644 index 0000000000..88a52e2c38 --- /dev/null +++ b/ngrinder-controller/src/test/java/org/ngrinder/common/util/StringUtilsTest.java @@ -0,0 +1,22 @@ +package org.ngrinder.common.util; + +import org.junit.Test; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.ngrinder.common.util.StringUtils.replaceLast; + +public class StringUtilsTest { + + @Test + public void testReplaceLast() { + String str1 = "ngrinder-core-3.5.1-p1.jar"; + assertThat(replaceLast(str1, "-p[1-9]", ""), is("ngrinder-core-3.5.1.jar")); + + String str2 = "ngrin-p2der-c-p3ore-3.5.1-p1.jar"; + assertThat(replaceLast(str2, "-p[1-9]", ""), is("ngrin-p2der-c-p3ore-3.5.1.jar")); + + String str3 = "ngr-pginder-core-3.5.1-p0.jar"; + assertThat(replaceLast(str3, "-p[1-9]", ""), is("ngr-pginder-core-3.5.1-p0.jar")); + } +} diff --git a/ngrinder-frontend/package.json b/ngrinder-frontend/package.json index ab5b2c8bea..c5dc9d681d 100644 --- a/ngrinder-frontend/package.json +++ b/ngrinder-frontend/package.json @@ -1,6 +1,6 @@ { "name": "ngrinder", - "version": "3.5.1", + "version": "3.5.1-p1", "description": "ngrinder GUI", "private": true, "repository": { @@ -8,10 +8,10 @@ "url": "https://github.com/naver/ngrinder.git" }, "scripts": { - "build-dev": "webpack", - "build-prod": "webpack --p", - "watch-dev": "webpack --watch", - "watch-prod": "webpack --watch --p", + "build-dev": "webpack --d", + "build-prod": "webpack", + "watch-dev": "webpack --watch --d", + "watch-prod": "webpack --watch", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", diff --git a/ngrinder-frontend/webpack.config.js b/ngrinder-frontend/webpack.config.js index b673bcd60c..2e85a9c294 100644 --- a/ngrinder-frontend/webpack.config.js +++ b/ngrinder-frontend/webpack.config.js @@ -6,12 +6,12 @@ var webpack = require('webpack'); var outputDir = path.resolve('../ngrinder-controller/build/classes/main/static'); var argv = require('yargs').argv; -var productionBuild = argv.p || argv.prod || argv.production || false; +var developmentBuild = argv.d || argv.dev || argv.development || false; -if (productionBuild) { - console.log('### production build is enabled. ga is included and javascript is optimized\r'); -} else { +if (developmentBuild) { console.log('### production build is disabled.\r'); +} else { + console.log('### production build is enabled. ga is included and javascript is optimized\r'); } if (argv.w || argv.watch) { @@ -23,26 +23,26 @@ console.log('### passed env is ' + JSON.stringify(argv.env)); var cssLoader = { loader: 'css-loader', options: { - sourceMap: !productionBuild, + sourceMap: developmentBuild, }, }; var lessLoader = { loader: 'less-loader', options: { - sourceMap: !productionBuild, + sourceMap: developmentBuild, }, }; module.exports = function (env) { - var ngrinderVersion = '3.5.1'; + var ngrinderVersion = '3.5.1-p1'; if (env !== undefined && env.ngrinderVersion !== undefined) { ngrinderVersion = env.ngrinderVersion; } console.log('### frontend version is ' + ngrinderVersion + '\r'); var webpackConfig = { - mode: productionBuild ? 'production' : 'development', + mode: developmentBuild ? 'development' : 'production', performance: { hints: false, }, @@ -166,7 +166,7 @@ module.exports = function (env) { }, ]), new webpack.LoaderOptionsPlugin({ - debug: !productionBuild, + debug: developmentBuild, options: { context: __dirname, htmlLoader: { @@ -180,7 +180,7 @@ module.exports = function (env) { ], }; - if (!productionBuild) { + if (developmentBuild) { console.log('### sourcemap is enabled.\r'); webpackConfig.devtool = "#inline-source-map"; } else { diff --git a/ngrinder-groovy/build.gradle b/ngrinder-groovy/build.gradle index c4ff8e0fa2..9f1295e44b 100644 --- a/ngrinder-groovy/build.gradle +++ b/ngrinder-groovy/build.gradle @@ -8,7 +8,12 @@ configurations { dependencies { compile (project(":ngrinder-runtime")) - compile (group: "org.codehaus.groovy", name: "groovy", version:"3.0.5") + compile (group: "org.codehaus.groovy", name: "groovy", version: groovy_version) + compile (group: 'org.codehaus.groovy', name: 'groovy-datetime', version: groovy_version) + compile (group: 'org.codehaus.groovy', name: 'groovy-templates', version: groovy_version) + compile (group: 'org.codehaus.groovy', name: 'groovy-json', version: groovy_version) + compile (group: 'org.codehaus.groovy', name: 'groovy-sql', version: groovy_version) + compile (group: 'org.codehaus.groovy', name: 'groovy-xml', version: groovy_version) testCompile (group: "org.mockito", name: "mockito-core", version: mockito_version)