├── .coveralls.yml ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── LICENSE ├── MAINTAINERS ├── README.md ├── RELEASE.md ├── dist └── pom.xml ├── mvnw ├── mvnw.cmd ├── pom.xml ├── remote-test ├── .gitignore ├── README.md ├── pom.xml └── src │ └── test │ ├── groovy │ ├── TestNGTest.groovy │ └── Tester.groovy │ └── resources │ ├── grapeConfig.xml │ └── testng-remote.xml ├── remote ├── pom.xml └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── testng │ │ │ ├── remote │ │ │ ├── AbstractRemoteTestNG.java │ │ │ ├── AbstractRemoteTestNGFactory.java │ │ │ ├── IRemoteTestNG.java │ │ │ ├── Orderable.java │ │ │ ├── RemoteArgs.java │ │ │ ├── RemoteTestNG.java │ │ │ ├── strprotocol │ │ │ │ ├── AbstractRemoteTestRunnerClient.java │ │ │ │ ├── BaseMessageSender.java │ │ │ │ ├── GenericMessage.java │ │ │ │ ├── IMessage.java │ │ │ │ ├── IMessageSender.java │ │ │ │ ├── IRemoteSuiteListener.java │ │ │ │ ├── IRemoteTestListener.java │ │ │ │ ├── IStringMessage.java │ │ │ │ ├── JsonMessageSender.java │ │ │ │ ├── MessageHelper.java │ │ │ │ ├── MessageHub.java │ │ │ │ ├── MessageType.java │ │ │ │ ├── RemoteTestListener.java │ │ │ │ ├── RemoteTestListener1.java │ │ │ │ ├── SerializedMessageSender.java │ │ │ │ ├── StdoutMessageSender.java │ │ │ │ ├── StringMessageSender.java │ │ │ │ ├── SuiteMessage.java │ │ │ │ ├── TestMessage.java │ │ │ │ └── TestResultMessage.java │ │ │ └── support │ │ │ │ ├── RemoteTestNGFactory.java │ │ │ │ └── ServiceLoaderHelper.java │ │ │ ├── shaded │ │ │ └── osgi │ │ │ │ └── framework │ │ │ │ ├── Version.java │ │ │ │ └── VersionRange.java │ │ │ └── xml │ │ │ ├── ResultContentHandler.java │ │ │ └── ResultXMLParser.java │ └── resources │ │ └── revision.properties │ └── test │ ├── java │ ├── org │ │ └── testng │ │ │ └── remote │ │ │ └── strprotocol │ │ │ ├── JsonMessageTest.java │ │ │ └── TestResultMessageTest.java │ └── test │ │ ├── SimpleBaseTest.java │ │ └── remote │ │ ├── RemoteSampleTest.java │ │ └── RemoteTest.java │ └── resources │ ├── testng-remote.xml │ └── testng.xml ├── remote6_0 ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── testng │ │ └── remote │ │ └── support │ │ ├── RemoteTestNG6_0.java │ │ └── RemoteTestNGFactory6_0.java │ └── test │ └── java │ └── test │ └── remote │ └── Remote6_0_Test.java ├── remote6_10 ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── testng │ │ └── remote │ │ └── support │ │ ├── RemoteTestNG6_10.java │ │ └── RemoteTestNGFactory6_10.java │ └── test │ └── java │ └── test │ └── remote │ └── Remote6_10_Test.java ├── remote6_12 ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── testng │ │ └── remote │ │ └── support │ │ ├── RemoteTestNG6_12.java │ │ └── RemoteTestNGFactory6_12.java │ └── test │ └── java │ └── test │ └── remote │ └── Remote6_12_Test.java ├── remote6_5 ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── testng │ │ └── remote │ │ └── support │ │ ├── RemoteTestNG6_5.java │ │ └── RemoteTestNGFactory6_5.java │ └── test │ └── java │ └── test │ └── remote │ └── Remote6_5_Test.java ├── remote6_9_10 ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── testng │ │ └── remote │ │ └── support │ │ ├── RemoteTestNG6_9_10.java │ │ └── RemoteTestNGFactory6_9_10.java │ └── test │ └── java │ └── test │ └── remote │ └── Remote6_9_10_Test.java ├── remote6_9_7 ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── testng │ │ └── remote │ │ └── support │ │ ├── RemoteTestNG6_9_7.java │ │ └── RemoteTestNGFactory6_9_7.java │ └── test │ └── java │ └── test │ └── remote │ └── Remote6_9_7Test.java ├── remote7_8 ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── testng │ │ └── remote │ │ └── support │ │ ├── RemoteTestNG7_8.java │ │ └── RemoteTestNGFactory7_8.java │ └── test │ └── java │ └── test │ └── remote │ └── Remote7_8_Test.java └── remote7_9 ├── pom.xml └── src ├── main └── java │ └── org │ └── testng │ └── remote │ └── support │ ├── RemoteTestNG7_9.java │ └── RemoteTestNGFactory7_9.java └── test └── java └── test └── remote └── Remote7_9_Test.java /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-ci -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @testng-team/testng -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: org.testng:testng 10 | versions: 11 | - "> 6.5.1" 12 | - package-ecosystem: github-actions 13 | directory: "/" 14 | schedule: 15 | interval: weekly 16 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | schedule: 10 | - cron: "0 0 * * *" 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-22.04 15 | strategy: 16 | matrix: 17 | java: ['11'] 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | - name: Set up JDK 22 | uses: actions/setup-java@v3 23 | with: 24 | java-version: ${{ matrix.java }} 25 | distribution: 'temurin' 26 | java-package: 'jdk' 27 | check-latest: true 28 | server-id: 'ossrh' # must match the serverId configured for the nexus-staging-maven-plugin 29 | server-username: OSSRH_USERNAME # Env var that holds your OSSRH user name 30 | server-password: OSSRH_PASSWORD # Env var that holds your OSSRH user pw 31 | gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} # Substituted with the value stored in the referenced secret 32 | gpg-passphrase: SIGN_KEY_PASS # Env var that holds the key's passphrase 33 | cache: 'maven' 34 | 35 | - name: Build with Maven 36 | run: | 37 | mkdir -p ~/.groovy 38 | ./mvnw --version 39 | cp -f remote-test/src/test/resources/grapeConfig.xml ~/.groovy 40 | # workaround for being failed to download osgi/junit/guice for integration test. 41 | # see: https://alok-mishra.com/2015/10/01/593/ 42 | rm -rf ~/.m2/repository/org/osgi ~/.m2/repository/junit/junit ~/.m2/repository/com/google/inject/guice 43 | ./mvnw -e -DskipIntTest=false clean install jacoco:report 44 | 45 | - name: Publish 46 | # publish snapshot only when push to master branch 47 | if: github.event_name == 'push' && github.ref_name == 'master' 48 | run: ./mvnw -U -B clean -DskipTests deploy -P deploy 49 | env: 50 | SIGN_KEY_PASS: ${{ secrets.GPG_PASSPHRASE }} 51 | OSSRH_USERNAME: ${{ secrets.NEXUS_USERNAME }} 52 | OSSRH_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} 53 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | releaseVersion: 6 | description: 'The release version. Ex: 1.6.0' 7 | required: true 8 | developmentVersion: 9 | description: 'The next development version. Ex: 1.7.0-SNAPSHOT' 10 | required: true 11 | permissions: 12 | contents: write 13 | 14 | jobs: 15 | release: 16 | name: Create Release 17 | runs-on: ubuntu-22.04 18 | steps: 19 | - name: Checkout code 20 | uses: actions/checkout@v3 21 | with: 22 | fetch-depth: 0 23 | # to bypass the branch protection rule for maven-release-plugin 24 | # see https://github.community/t/push-to-restricted-master-branch/18191/2 25 | persist-credentials: false 26 | 27 | - name: Configure Git user 28 | run: | 29 | git config user.email "cibot@testng.org" 30 | git config user.name "CI Bot" 31 | 32 | - name: Set up JDK 33 | uses: actions/setup-java@v3 34 | with: 35 | java-version: '11' 36 | distribution: 'temurin' 37 | java-package: 'jdk' 38 | check-latest: true 39 | server-id: 'ossrh' # must match the serverId configured for the nexus-staging-maven-plugin 40 | server-username: OSSRH_USERNAME # Env var that holds your OSSRH user name 41 | server-password: OSSRH_PASSWORD # Env var that holds your OSSRH user pw 42 | gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} # Substituted with the value stored in the referenced secret 43 | gpg-passphrase: SIGN_KEY_PASS # Env var that holds the key's passphrase 44 | cache: 'maven' 45 | 46 | - name: Release 47 | run: | 48 | ./mvnw -DskipTests -Darguments="-DskipTests" \ 49 | -Dusername=cibot -Dpassword=${{ secrets.GITHUB_TOKEN }} \ 50 | -DdevelopmentVersion=${{ github.event.inputs.developmentVersion }} \ 51 | -DreleaseVersion=${{ github.event.inputs.releaseVersion }} \ 52 | -B release:prepare release:perform -P deploy 53 | env: 54 | SIGN_KEY_PASS: ${{ secrets.GPG_PASSPHRASE }} 55 | OSSRH_USERNAME: ${{ secrets.NEXUS_USERNAME }} 56 | OSSRH_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.war 8 | *.ear 9 | 10 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 11 | hs_err_pid* 12 | target/ 13 | test-output/ 14 | 15 | .settings/ 16 | .classpath 17 | .project 18 | .idea/ 19 | *.iml 20 | .vscode/ 21 | 22 | dependency-reduced-pom.xml 23 | .DS_Store 24 | 25 | kobaltBuild 26 | .kobalt 27 | 28 | local.properties 29 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/testng-team/testng-remote/46bc27ec69e84a2fe6a9ae566f4e9d6d14d9464b/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.2/apache-maven-3.9.2-bin.zip 18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /MAINTAINERS: -------------------------------------------------------------------------------- 1 | missedone 2 | juherr 3 | cbeust 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Remote TestNG 2 | ==== 3 | 4 | [![Build Status](http://img.shields.io/travis/testng-team/testng-remote.svg)](https://travis-ci.org/testng-team/testng-remote) 5 | [![Coverage Status](https://coveralls.io/repos/github/testng-team/testng-remote/badge.svg)](https://coveralls.io/github/testng-team/testng-remote) 6 | 7 | TestNG Remote - the modules for running TestNG remotely. This is normally used by IDE to communicate with TestNG runtime, e.g. receive the Test Result from runtime so that can display them on IDE views. 8 | 9 | ### Current Release Version 10 | 11 | ```xml 12 | 13 | org.testng.testng-remote 14 | testng-remote-dist 15 | 1.7.0 16 | shaded 17 | 18 | ``` 19 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | Release Remote TestNG 2 | ==== 3 | 4 | ### Perform release 5 | 6 | 1. Create a release branch like `release/1.6.0` 7 | 2. Go to https://github.com/testng-team/testng-remote/actions/workflows/release.yml 8 | * Select the `branch` you just created: `release/1.6.0` 9 | * Set `releaseVersion`: the new release version, for example, `1.6.0` 10 | * Set `developmentVersion`: the next development version, for example, `1.6.1-SNAPSHOT` 11 | 3. Merge the release branch without squashing to retain the git tag 12 | -------------------------------------------------------------------------------- /dist/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote-dist 11 | TestNG Remote - Dist 12 | TestNG Remote - Assemble All-in-One Package 13 | 14 | 15 | 16 | org.testng.testng-remote 17 | testng-remote 18 | 19 | 20 | org.testng.testng-remote 21 | testng-remote6_0 22 | 23 | 24 | org.testng.testng-remote 25 | testng-remote6_5 26 | 27 | 28 | org.testng.testng-remote 29 | testng-remote6_9_7 30 | 31 | 32 | org.testng.testng-remote 33 | testng-remote6_9_10 34 | 35 | 36 | org.testng.testng-remote 37 | testng-remote6_10 38 | 39 | 40 | org.testng.testng-remote 41 | testng-remote6_12 42 | 43 | 44 | org.testng.testng-remote 45 | testng-remote7_8 46 | 47 | 48 | org.testng.testng-remote 49 | testng-remote7_9 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.apache.maven.plugins 57 | maven-shade-plugin 58 | 59 | 60 | package 61 | 62 | shade 63 | 64 | 65 | true 66 | 67 | 68 | org.testng.testng-remote:testng-remote 69 | org.testng.testng-remote:testng-remote6_0 70 | org.testng.testng-remote:testng-remote6_5 71 | org.testng.testng-remote:testng-remote6_9_7 72 | org.testng.testng-remote:testng-remote6_9_10 73 | org.testng.testng-remote:testng-remote6_10 74 | org.testng.testng-remote:testng-remote6_12 75 | org.testng.testng-remote:testng-remote7_8 76 | org.testng.testng-remote:testng-remote7_9 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /usr/local/etc/mavenrc ] ; then 40 | . /usr/local/etc/mavenrc 41 | fi 42 | 43 | if [ -f /etc/mavenrc ] ; then 44 | . /etc/mavenrc 45 | fi 46 | 47 | if [ -f "$HOME/.mavenrc" ] ; then 48 | . "$HOME/.mavenrc" 49 | fi 50 | 51 | fi 52 | 53 | # OS specific support. $var _must_ be set to either true or false. 54 | cygwin=false; 55 | darwin=false; 56 | mingw=false 57 | case "`uname`" in 58 | CYGWIN*) cygwin=true ;; 59 | MINGW*) mingw=true;; 60 | Darwin*) darwin=true 61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 63 | if [ -z "$JAVA_HOME" ]; then 64 | if [ -x "/usr/libexec/java_home" ]; then 65 | export JAVA_HOME="`/usr/libexec/java_home`" 66 | else 67 | export JAVA_HOME="/Library/Java/Home" 68 | fi 69 | fi 70 | ;; 71 | esac 72 | 73 | if [ -z "$JAVA_HOME" ] ; then 74 | if [ -r /etc/gentoo-release ] ; then 75 | JAVA_HOME=`java-config --jre-home` 76 | fi 77 | fi 78 | 79 | if [ -z "$M2_HOME" ] ; then 80 | ## resolve links - $0 may be a link to maven's home 81 | PRG="$0" 82 | 83 | # need this for relative symlinks 84 | while [ -h "$PRG" ] ; do 85 | ls=`ls -ld "$PRG"` 86 | link=`expr "$ls" : '.*-> \(.*\)$'` 87 | if expr "$link" : '/.*' > /dev/null; then 88 | PRG="$link" 89 | else 90 | PRG="`dirname "$PRG"`/$link" 91 | fi 92 | done 93 | 94 | saveddir=`pwd` 95 | 96 | M2_HOME=`dirname "$PRG"`/.. 97 | 98 | # make it fully qualified 99 | M2_HOME=`cd "$M2_HOME" && pwd` 100 | 101 | cd "$saveddir" 102 | # echo Using m2 at $M2_HOME 103 | fi 104 | 105 | # For Cygwin, ensure paths are in UNIX format before anything is touched 106 | if $cygwin ; then 107 | [ -n "$M2_HOME" ] && 108 | M2_HOME=`cygpath --unix "$M2_HOME"` 109 | [ -n "$JAVA_HOME" ] && 110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 111 | [ -n "$CLASSPATH" ] && 112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 113 | fi 114 | 115 | # For Mingw, ensure paths are in UNIX format before anything is touched 116 | if $mingw ; then 117 | [ -n "$M2_HOME" ] && 118 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 119 | [ -n "$JAVA_HOME" ] && 120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 121 | fi 122 | 123 | if [ -z "$JAVA_HOME" ]; then 124 | javaExecutable="`which javac`" 125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 126 | # readlink(1) is not available as standard on Solaris 10. 127 | readLink=`which readlink` 128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 129 | if $darwin ; then 130 | javaHome="`dirname \"$javaExecutable\"`" 131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 132 | else 133 | javaExecutable="`readlink -f \"$javaExecutable\"`" 134 | fi 135 | javaHome="`dirname \"$javaExecutable\"`" 136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 137 | JAVA_HOME="$javaHome" 138 | export JAVA_HOME 139 | fi 140 | fi 141 | fi 142 | 143 | if [ -z "$JAVACMD" ] ; then 144 | if [ -n "$JAVA_HOME" ] ; then 145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 146 | # IBM's JDK on AIX uses strange locations for the executables 147 | JAVACMD="$JAVA_HOME/jre/sh/java" 148 | else 149 | JAVACMD="$JAVA_HOME/bin/java" 150 | fi 151 | else 152 | JAVACMD="`\\unset -f command; \\command -v java`" 153 | fi 154 | fi 155 | 156 | if [ ! -x "$JAVACMD" ] ; then 157 | echo "Error: JAVA_HOME is not defined correctly." >&2 158 | echo " We cannot execute $JAVACMD" >&2 159 | exit 1 160 | fi 161 | 162 | if [ -z "$JAVA_HOME" ] ; then 163 | echo "Warning: JAVA_HOME environment variable is not set." 164 | fi 165 | 166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 167 | 168 | # traverses directory structure from process work directory to filesystem root 169 | # first directory with .mvn subdirectory is considered project base directory 170 | find_maven_basedir() { 171 | 172 | if [ -z "$1" ] 173 | then 174 | echo "Path not specified to find_maven_basedir" 175 | return 1 176 | fi 177 | 178 | basedir="$1" 179 | wdir="$1" 180 | while [ "$wdir" != '/' ] ; do 181 | if [ -d "$wdir"/.mvn ] ; then 182 | basedir=$wdir 183 | break 184 | fi 185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 186 | if [ -d "${wdir}" ]; then 187 | wdir=`cd "$wdir/.."; pwd` 188 | fi 189 | # end of workaround 190 | done 191 | echo "${basedir}" 192 | } 193 | 194 | # concatenates all lines of a file 195 | concat_lines() { 196 | if [ -f "$1" ]; then 197 | echo "$(tr -s '\n' ' ' < "$1")" 198 | fi 199 | } 200 | 201 | BASE_DIR=`find_maven_basedir "$(pwd)"` 202 | if [ -z "$BASE_DIR" ]; then 203 | exit 1; 204 | fi 205 | 206 | ########################################################################################## 207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 208 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 209 | ########################################################################################## 210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Found .mvn/wrapper/maven-wrapper.jar" 213 | fi 214 | else 215 | if [ "$MVNW_VERBOSE" = true ]; then 216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 217 | fi 218 | if [ -n "$MVNW_REPOURL" ]; then 219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 220 | else 221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 222 | fi 223 | while IFS="=" read key value; do 224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 225 | esac 226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 227 | if [ "$MVNW_VERBOSE" = true ]; then 228 | echo "Downloading from: $jarUrl" 229 | fi 230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 231 | if $cygwin; then 232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 233 | fi 234 | 235 | if command -v wget > /dev/null; then 236 | if [ "$MVNW_VERBOSE" = true ]; then 237 | echo "Found wget ... using wget" 238 | fi 239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 241 | else 242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 243 | fi 244 | elif command -v curl > /dev/null; then 245 | if [ "$MVNW_VERBOSE" = true ]; then 246 | echo "Found curl ... using curl" 247 | fi 248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 249 | curl -o "$wrapperJarPath" "$jarUrl" -f 250 | else 251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 252 | fi 253 | 254 | else 255 | if [ "$MVNW_VERBOSE" = true ]; then 256 | echo "Falling back to using Java to download" 257 | fi 258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 259 | # For Cygwin, switch paths to Windows format before running javac 260 | if $cygwin; then 261 | javaClass=`cygpath --path --windows "$javaClass"` 262 | fi 263 | if [ -e "$javaClass" ]; then 264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 265 | if [ "$MVNW_VERBOSE" = true ]; then 266 | echo " - Compiling MavenWrapperDownloader.java ..." 267 | fi 268 | # Compiling the Java class 269 | ("$JAVA_HOME/bin/javac" "$javaClass") 270 | fi 271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 272 | # Running the downloader 273 | if [ "$MVNW_VERBOSE" = true ]; then 274 | echo " - Running MavenWrapperDownloader.java ..." 275 | fi 276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 277 | fi 278 | fi 279 | fi 280 | fi 281 | ########################################################################################## 282 | # End of extension 283 | ########################################################################################## 284 | 285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 286 | if [ "$MVNW_VERBOSE" = true ]; then 287 | echo $MAVEN_PROJECTBASEDIR 288 | fi 289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 290 | 291 | # For Cygwin, switch paths to Windows format before running java 292 | if $cygwin; then 293 | [ -n "$M2_HOME" ] && 294 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 295 | [ -n "$JAVA_HOME" ] && 296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 297 | [ -n "$CLASSPATH" ] && 298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 299 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 301 | fi 302 | 303 | # Provide a "standardized" way to retrieve the CLI args that will 304 | # work with both Windows and non-Windows executions. 305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 306 | export MAVEN_CMD_LINE_ARGS 307 | 308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 309 | 310 | exec "$JAVACMD" \ 311 | $MAVEN_OPTS \ 312 | $MAVEN_DEBUG_OPTS \ 313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 314 | "-Dmaven.home=${M2_HOME}" \ 315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 317 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 124 | 125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% ^ 162 | %JVM_CONFIG_MAVEN_PROPS% ^ 163 | %MAVEN_OPTS% ^ 164 | %MAVEN_DEBUG_OPTS% ^ 165 | -classpath %WRAPPER_JAR% ^ 166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 168 | if ERRORLEVEL 1 goto error 169 | goto end 170 | 171 | :error 172 | set ERROR_CODE=1 173 | 174 | :end 175 | @endlocal & set ERROR_CODE=%ERROR_CODE% 176 | 177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 181 | :skipRcPost 182 | 183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 185 | 186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 187 | 188 | cmd /C exit /B %ERROR_CODE% 189 | -------------------------------------------------------------------------------- /remote-test/.gitignore: -------------------------------------------------------------------------------- 1 | /testng-output/ 2 | -------------------------------------------------------------------------------- /remote-test/README.md: -------------------------------------------------------------------------------- 1 | Test for Remote TestNG 2 | ==== 3 | 4 | ## Background 5 | 6 | Since TestNG Eclipse [6.9.11](https://github.com/cbeust/testng-eclipse/blob/master/CHANGES.md#6911), 7 | the plugin does not append any testng.jar to the runtime testng process. Instead, the testng-remote jar is appended, 8 | which is used for communicating between the runtime testng process and the plugin. 9 | 10 | When start the testng process, the testng-remote checks the version of runtime testng 11 | and load the corresponding adapter (aka. version specific) to perform the real testing. 12 | 13 | As we can see there are lots of releases in the past, it's sort of hard to let testng-remote support all the versions, 14 | that's why only testng version >= 6.5.1 are supported. 15 | 16 | However, we still want to have a view of how will testng-remote behave against the older versions. 17 | 18 | ## Usage 19 | 20 | ```bash 21 | cd testng-remote/remote-test 22 | mvn -e -DskipIntTest=false test 23 | ``` 24 | 25 | ## Trouble shooting 26 | 27 | * General error during conversion: Error grabbing Grapes -- \[download failed: org.testng\#testng;6.8.3!testng.jar\] 28 | if we get the above error, we need to clean up the cache of grape and maven: 29 | ``` 30 | rm -r ~/.groovy/grapes/org.testng/testng 31 | rm -r ~/.m2/repository/org/testng/testng 32 | ``` 33 | -------------------------------------------------------------------------------- /remote-test/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote-test 11 | TestNG Remote Test 12 | 13 | 14 | 2.3.11 15 | 2.5.3 16 | true 17 | 18 | 19 | 20 | 21 | integration-tests 22 | 23 | 24 | skipIntTest 25 | false 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.codehaus.mojo 33 | exec-maven-plugin 34 | 3.5.0 35 | 36 | 37 | 38 | java 39 | 40 | test 41 | 42 | 43 | 44 | false 45 | true 46 | groovy.ui.GroovyMain 47 | 48 | ${project.basedir}/src/test/groovy/Tester.groovy 49 | 50 | 51 | 52 | PROJECT_BASEDIR 53 | ${project.basedir} 54 | 55 | 56 | PROJECT_VERSION 57 | ${project.version} 58 | 59 | 60 | GROOVY_VERSION 61 | ${groovy.version} 62 | 63 | 64 | IVY_VERSION 65 | ${ivy.version} 66 | 67 | 68 | testng.eclipse.verbose 69 | true 70 | 71 | 72 | 73 | 74 | 75 | 76 | org.codehaus.groovy 77 | groovy-all 78 | 79 | ${groovy.version} 80 | 81 | 82 | org.apache.ivy 83 | ivy 84 | ${ivy.version} 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | org.codehaus.groovy 95 | groovy-all 96 | 97 | ${groovy.version} 98 | runtime 99 | 100 | 101 | org.apache.ivy 102 | ivy 103 | ${ivy.version} 104 | runtime 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /remote-test/src/test/groovy/TestNGTest.groovy: -------------------------------------------------------------------------------- 1 | import org.testng.remote.RemoteTestNG; 2 | //import org.testng.annotations.BeforeClass; 3 | //import org.testng.annotations.AfterClass; 4 | import org.testng.annotations.Test; 5 | 6 | class SimpleTest { 7 | 8 | // @BeforeClass 9 | // def setUp() { 10 | // println "BeforeClass: setUp" 11 | // } 12 | // 13 | // @AfterClass 14 | // def tearDown() { 15 | // println "AfterClass: tearDown" 16 | // } 17 | 18 | @Test 19 | void testFoo() { 20 | println "testFoo" 21 | } 22 | } 23 | 24 | def DEBUG = false 25 | 26 | if (DEBUG) { 27 | println "===== Classpath BEGIN =====" 28 | // println "root loader:" 29 | // this.class.classLoader.rootLoader.URLs.each { println it } 30 | 31 | println "\nsystem loader:" 32 | ClassLoader.systemClassLoader.URLs.each { println it } 33 | 34 | println "\ncurrent thread loader" 35 | this.class.classLoader.URLs.each { println it } 36 | 37 | println "\n===== Classpath END =====\n" 38 | } 39 | 40 | def protocol = "stdout" 41 | def port = "12345" 42 | 43 | if (args.length == 2) { 44 | protocol = args[0] 45 | port = args[1] 46 | } 47 | 48 | def args = ["-serport", port, "-protocol", protocol, "-d", "./target/testng-output", "./src/test/resources/testng-remote.xml"] as String[] 49 | RemoteTestNG.main(args) 50 | -------------------------------------------------------------------------------- /remote-test/src/test/groovy/Tester.groovy: -------------------------------------------------------------------------------- 1 | @Grab(group = 'org.osgi', module = 'osgi.core', version = '6.0.0') 2 | @Grab(group = 'org.testng.testng-remote', module = 'testng-remote', version = '1.5.1') 3 | 4 | import org.osgi.framework.Version 5 | import org.testng.remote.strprotocol.JsonMessageSender 6 | 7 | // 8 | // global var 9 | // 10 | 11 | // need to download the classifier jar for versions <= 5.11 12 | classifierVer = new Version("5.11") 13 | 14 | groovyVer = System.getProperty("GROOVY_VERSION") ?: "2.3.11" 15 | ivyVer = System.getProperty("IVY_VERSION") ?: "2.3.0" 16 | testngRemoteVer = System.getProperty("PROJECT_VERSION") ?: "1.5.1" 17 | jcmdVer = "1.48" 18 | slf4jVer = "1.7.32" 19 | 20 | workingDir = new File(System.getProperty("user.dir")) 21 | if (System.getProperty("PROJECT_BASEDIR")) { 22 | workingDir = new File(System.getProperty("PROJECT_BASEDIR")) 23 | } 24 | 25 | println "\t:::" 26 | println "\t::: workingDir: ${workingDir}" 27 | println "\t::: testng remote version: ${testngRemoteVer}" 28 | println "\t::: groovy version: ${groovyVer}" 29 | println "\t::: ivy version: ${ivyVer}" 30 | println "\t:::" 31 | 32 | scriptDir = new File(workingDir.absolutePath + "/src/test/groovy") 33 | 34 | mvnRepoDir = System.getenv("HOME") + "/.m2/repository" 35 | 36 | groovyJar = "${mvnRepoDir}/org/codehaus/groovy/groovy-all/${groovyVer}/groovy-all-${groovyVer}.jar" 37 | // ivy is required for groovy @Grab annotation 38 | ivyJar = "${mvnRepoDir}/org/apache/ivy/ivy/${ivyVer}/ivy-${ivyVer}.jar" 39 | 40 | grapeRepoDir = System.getenv("HOME") + "/.groovy/grapes" 41 | 42 | remoteTestngJar = "${grapeRepoDir}/org.testng.testng-remote/testng-remote-dist/jars/testng-remote-dist-${testngRemoteVer}-shaded.jar" 43 | jcmdJar = "${grapeRepoDir}/com.beust/jcommander/jars/jcommander-${jcmdVer}.jar" 44 | slf4jJar = "${grapeRepoDir}/org.slf4j/slf4j-api/jars/slf4j-api-${slf4jVer}.jar" 45 | 46 | resultSet = new HashMap() 47 | 48 | //~~ 49 | 50 | 51 | def startTime = System.currentTimeMillis() 52 | def metadata = new XmlSlurper().parse("https://repo1.maven.org/maven2/org/testng/testng/maven-metadata.xml") 53 | 54 | def versionBlackList = ['6.12', '6.13', '6.14.0-RC2', '6.14.0-RC3', '7.0.0-beta2', '7.0.0-beta4', '7.1.0', '7.1.1'] 55 | if (System.getProperty('java.version').startsWith('1.7')) { 56 | versionBlackList.add('7.*') 57 | } 58 | 59 | metadata.versioning.versions.version.each { version -> 60 | println ">>>>>" 61 | println ">>>>> Testing ${version}" 62 | println ">>>>>" 63 | 64 | // skip invalid testng jar 65 | for (def bver : versionBlackList) { 66 | if (version.toString().matches(bver)) { 67 | println "skip testing ${version} \n" 68 | return 69 | } 70 | } 71 | 72 | def exitValue = runTestNGTest(version) 73 | def rset = resultSet[exitValue] 74 | if (rset == null) { 75 | rset = new ArrayList() 76 | resultSet[exitValue] = rset 77 | } 78 | rset << version 79 | 80 | println "<<<<<" 81 | println ">>>>> Tested ${version}: result=${exitValue}" 82 | println "<<<<<\n" 83 | } 84 | 85 | println "\nCompleted in " + (System.currentTimeMillis() - startTime) + " (ms)" 86 | 87 | 88 | println "\nSummary report:" 89 | resultSet.each { 90 | switch (it.key) { 91 | case 0: 92 | println it.key + " - PASSED:" 93 | break; 94 | case 1: 95 | println it.key + " - unsupported version detected:" 96 | break; 97 | case 2: 98 | println it.key + " - NoClassDefFoundError:" 99 | break; 100 | default: 101 | println it.key + " - OTHERS:" 102 | } 103 | 104 | println "\t" + it.value 105 | } 106 | println "" 107 | 108 | // failed if there's any OTHER failures 109 | assert resultSet[-1] == null 110 | 111 | def minVer = new Version("6.0") 112 | resultSet[1].each { 113 | // no version >= 6.0 will get error 'unsupported version detected' 114 | assert (toVersion(it.toString()).compareTo(minVer) < 0) 115 | } 116 | resultSet[2].each { 117 | // no version >= 6.5.1 will get error 'NoClassDefFoundError' 118 | assert (toVersion(it.toString()).compareTo(minVer) < 0) 119 | } 120 | 121 | /** 122 | * run the testng test with groovy in a separate process 123 | * 124 | * @param ver the testng version 125 | * @return 0 - success; 1 - unsupported version detected; 2 - NoClassDefFoundError; -1 - others; 126 | */ 127 | def runTestNGTest(ver) { 128 | if (downloadTestNG(ver) != 0) { 129 | println "failed to download jars for ${ver}, skip testing" 130 | return -1 131 | } 132 | 133 | def port = 12345 134 | def msgHub = new JsonMessageSender("localhost", port) 135 | Thread.start { 136 | msgHub.initReceiver() 137 | } 138 | 139 | try { 140 | def testngJar = "${grapeRepoDir}/org.testng/testng/jars/testng-${ver}.jar" 141 | if (toVersion(ver.toString()).compareTo(classifierVer) <= 0) { 142 | testngJar = "${grapeRepoDir}/org.testng/testng/jars/testng-${ver}-jdk15.jar" 143 | } 144 | 145 | println "classpath: ${groovyJar}:${ivyJar}:${remoteTestngJar}:${testngJar}:${jcmdJar}:${slf4jJar}\n" 146 | 147 | def scriptFile = new File(scriptDir, "TestNGTest.groovy") 148 | // run the groovy script via Java executable rather than groovy executable, because: 149 | // 1) groovy has RootLoader loads groovy distributed testng jar, which is in prior to our own jar; 150 | // 2) groovy @Grad can't specify the order of the jar on the classpath, 151 | // while testng-remote need to be on front of testng 152 | // (since some older version of testng jar contains older version of RemoteTestNG) 153 | def output = new StringBuilder() 154 | def process = new ProcessBuilder( 155 | "java", 156 | "-classpath", "${groovyJar}:${ivyJar}:${remoteTestngJar}:${testngJar}:${jcmdJar}:${slf4jJar}", 157 | "-Dtestng.eclipse.verbose", 158 | "-Dtestng.eclipse.debug", 159 | "groovy.ui.GroovyMain", 160 | scriptFile.absolutePath, 161 | "json", "" + port) 162 | .directory(workingDir).redirectErrorStream(true).start() 163 | process.inputStream.eachLine { println it; output << it.toString() } 164 | process.waitFor(); 165 | def exitValue = process.exitValue() 166 | if (exitValue == 0) { 167 | return 0 168 | } else { 169 | if (output.contains("is not a supported TestNG version")) { 170 | return 1 171 | } else if (output.contains("java.lang.NoClassDefFoundError")) { 172 | return 2; 173 | } else { 174 | return -1 175 | } 176 | } 177 | } finally { 178 | msgHub.stopReceiver() 179 | } 180 | } 181 | 182 | /** 183 | * start a new process to download the dep jars, 184 | * since @Grad can't specify the order of the jars on the classpath 185 | * while we do want to make testng-remote on front of testng jar 186 | * that's why we not put @Grab in the TestNGTest.groovy 187 | * 188 | * @param ver the testng version 189 | * @return 0 - success, otherwise - failure 190 | */ 191 | def downloadTestNG(ver) { 192 | def grabScriptFile = new File(scriptDir, "grabJar_${ver}.groovy") 193 | 194 | grabScriptFile.withWriter { w -> 195 | w << "@GrabResolver(name = 'jcenter', root = 'http://jcenter.bintray.com/')" + "\n" 196 | 197 | if (toVersion(ver.toString()).compareTo(classifierVer) > 0) { 198 | w << "@Grab(group = 'org.testng', module = 'testng', version = '${ver}')" + "\n" 199 | } else { 200 | w << "@Grab(group = 'org.testng', module = 'testng', version = '${ver}', classifier = 'jdk15')" + "\n" 201 | } 202 | 203 | w << "@GrabExclude('com.google.guava:guava')" + "\n" 204 | 205 | w << "@Grab(group = 'com.beust', module = 'jcommander', version = '${jcmdVer}')" + "\n" 206 | w << "@Grab(group = 'org.slf4j', module = 'slf4j-api', version = '${slf4jVer}')" + "\n" 207 | w << "@Grab(group = 'org.testng.testng-remote', module = 'testng-remote-dist', version = '${testngRemoteVer}', classifier = 'shaded')" + "\n" 208 | 209 | w << "import org.testng.annotations.Test;" + "\n" 210 | } 211 | 212 | try { 213 | def grapeProc = new ProcessBuilder( 214 | "java", 215 | "-classpath", "${groovyJar}:${ivyJar}", 216 | "groovy.ui.GroovyMain", 217 | grabScriptFile.absolutePath) 218 | .directory(workingDir).redirectErrorStream(true).start() 219 | grapeProc.inputStream.eachLine { println it } 220 | grapeProc.waitFor(); 221 | return grapeProc.exitValue() 222 | } finally { 223 | grabScriptFile.delete() 224 | } 225 | } 226 | 227 | def Version toVersion(String ver) { 228 | if ("5.5.m".equals(ver)) { 229 | ver = "5.5" 230 | } 231 | def idx = ver.indexOf("-") 232 | if (idx > 0) { 233 | ver = ver.substring(0, idx) 234 | } 235 | return new Version(ver) 236 | } 237 | -------------------------------------------------------------------------------- /remote-test/src/test/resources/grapeConfig.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /remote-test/src/test/resources/testng-remote.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /remote/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote 11 | TestNG Remote 12 | 13 | 14 | 6.5.1 15 | 16 | 17 | 18 | 19 | org.testng 20 | testng 21 | ${testng.version} 22 | 23 | 24 | com.google.code.gson 25 | gson 26 | 27 | 28 | 29 | 30 | 31 | 32 | src/main/resources 33 | true 34 | 35 | revision.properties 36 | 37 | 38 | 39 | 40 | 41 | 42 | org.apache.maven.plugins 43 | maven-shade-plugin 44 | 45 | 46 | package 47 | 48 | shade 49 | 50 | 51 | true 52 | 53 | 54 | com.google.code.gson:gson 55 | 56 | 57 | 58 | 59 | com.google.gson 60 | org.testng.shaded.com.google.gson 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-jar-plugin 70 | 71 | 72 | 73 | test-jar 74 | 75 | 76 | 77 | 78 | 79 | io.github.git-commit-id 80 | git-commit-id-maven-plugin 81 | 82 | 83 | 84 | revision 85 | 86 | 87 | 88 | 89 | true 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/AbstractRemoteTestNG.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote; 2 | 3 | import org.testng.CommandLineArgs; 4 | import org.testng.ISuite; 5 | import org.testng.ISuiteListener; 6 | import org.testng.ITestNGListener; 7 | import org.testng.ITestRunnerFactory; 8 | import org.testng.TestNG; 9 | import org.testng.remote.strprotocol.*; 10 | import org.testng.xml.XmlSuite; 11 | 12 | /** 13 | * Extension of TestNG registering a remote TestListener. 14 | * 15 | * @author Cedric Beust 16 | */ 17 | public abstract class AbstractRemoteTestNG extends TestNG implements IRemoteTestNG { 18 | private static final String LOCALHOST = "localhost"; 19 | 20 | protected ITestRunnerFactory m_customTestRunnerFactory; 21 | private String m_host; 22 | 23 | /** Port used for the string protocol */ 24 | private Integer m_port = null; 25 | 26 | /** Port used for the serialized protocol */ 27 | private Integer m_serPort = null; 28 | 29 | /** Protocol used for inter-communication */ 30 | private String m_protocol; 31 | 32 | private boolean m_debug; 33 | 34 | private boolean m_dontExit; 35 | 36 | private boolean m_ack; 37 | 38 | @Override 39 | public void dontExit(boolean dontExit) { 40 | m_dontExit = dontExit; 41 | } 42 | 43 | @Override 44 | public void setDebug(boolean debug) { 45 | m_debug = debug; 46 | } 47 | 48 | @Override 49 | public void setAck(boolean ack) { 50 | m_ack = ack; 51 | } 52 | 53 | @Override 54 | public void setHost(String host) { 55 | m_host = defaultIfStringEmpty(host, LOCALHOST); 56 | } 57 | 58 | @Override 59 | public void setSerPort(Integer serPort) { 60 | m_serPort = serPort; 61 | } 62 | 63 | @Override 64 | public void setProtocol(String protocol) { 65 | m_protocol = protocol; 66 | } 67 | 68 | @Override 69 | public void setPort(Integer port) { 70 | m_port = port; 71 | } 72 | 73 | @Override 74 | public void configure(CommandLineArgs cla) { 75 | super.configure(cla); 76 | } 77 | 78 | public static void validateCommandLineParameters(CommandLineArgs args) { 79 | TestNG.validateCommandLineParameters(args); 80 | } 81 | 82 | public static String defaultIfStringEmpty(String s, String defaultValue) { 83 | return isStringEmpty(s) ? defaultValue : s; 84 | } 85 | 86 | public static boolean isStringEmpty(String s) { 87 | return s == null || "".equals(s); 88 | } 89 | 90 | @Override 91 | public void run() { 92 | IMessageSender sender = getMessageSender(); 93 | final MessageHub msh = new MessageHub(sender); 94 | msh.setDebug(m_debug); 95 | try { 96 | msh.connect(); 97 | 98 | initialize(); 99 | 100 | if (canRun()) { 101 | int testCount = 0; 102 | 103 | for (XmlSuite suite : m_suites) { 104 | testCount += suite.getTests().size(); 105 | } 106 | 107 | GenericMessage gm = new GenericMessage(); 108 | gm.setSuiteCount(m_suites.size()); 109 | gm.setTestCount(testCount); 110 | msh.sendMessage(gm); 111 | 112 | super.addListener((ITestNGListener) new RemoteSuiteListener(msh)); 113 | setTestRunnerFactory(createDelegatingTestRunnerFactory(buildTestRunnerFactory(), msh)); 114 | 115 | super.run(); 116 | } 117 | else { 118 | System.err.println("No test suite found. Nothing to run"); 119 | } 120 | } 121 | catch(Throwable cause) { 122 | cause.printStackTrace(System.err); 123 | } 124 | finally { 125 | // System.out.println("RemoteTestNG finishing: " + (getEnd() - getStart()) + " ms"); 126 | msh.shutDown(); 127 | if (! m_debug && ! m_dontExit) { 128 | System.exit(0); 129 | } 130 | } 131 | } 132 | 133 | protected void initialize() { 134 | // We couldn't do this until now in debug mode since the .xml file didn't exist yet. 135 | // Now that we have connected with the Eclipse client, we know that it created the .xml 136 | // file so we can proceed with the initialization 137 | initializeSuitesAndJarFile(); 138 | } 139 | 140 | /** 141 | * run after {@link #initialize()}, tell if it's ready for running the test 142 | * 143 | * @return {@code true} for ready. 144 | */ 145 | protected boolean canRun() { 146 | return m_suites.size() > 0; 147 | } 148 | 149 | private IMessageSender getMessageSender() { 150 | if (m_protocol != null) { 151 | switch (m_protocol) { 152 | case "object": 153 | return new SerializedMessageSender(m_host, m_serPort, m_ack); 154 | case "string": 155 | return new StringMessageSender(m_host, m_port); 156 | case "json": 157 | return new JsonMessageSender(m_host, m_serPort, m_ack); 158 | case "stdout": 159 | return new StdoutMessageSender(); 160 | default: 161 | throw new IllegalArgumentException("unrecognized protocol: " + m_protocol); 162 | } 163 | } 164 | 165 | // fall back to original behaviour 166 | return m_serPort != null 167 | ? new SerializedMessageSender(m_host, m_serPort, m_ack) 168 | : new StringMessageSender(m_host, m_port); 169 | } 170 | 171 | /** 172 | * Override by the plugin if you need to configure differently the TestRunner 173 | * (usually this is needed if different listeners/reporters are needed). 174 | * Note: you don't need to worry about the wiring listener, because it is added 175 | * automatically. 176 | */ 177 | protected abstract ITestRunnerFactory buildTestRunnerFactory(); 178 | 179 | protected String getHost() { 180 | return m_host; 181 | } 182 | 183 | protected int getPort() { 184 | return m_port; 185 | } 186 | 187 | /** A ISuiteListener wiring the results using the internal string-based protocol. */ 188 | private static class RemoteSuiteListener implements ISuiteListener { 189 | private final MessageHub m_messageSender; 190 | 191 | RemoteSuiteListener(MessageHub smsh) { 192 | m_messageSender= smsh; 193 | } 194 | 195 | @Override 196 | public void onFinish(ISuite suite) { 197 | m_messageSender.sendMessage(new SuiteMessage(suite, false /*start*/)); 198 | } 199 | 200 | @Override 201 | public void onStart(ISuite suite) { 202 | m_messageSender.sendMessage(new SuiteMessage(suite, true /*start*/)); 203 | } 204 | } 205 | 206 | protected abstract ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh); 207 | } 208 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/AbstractRemoteTestNGFactory.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote; 2 | 3 | import org.testng.remote.support.RemoteTestNGFactory; 4 | import org.testng.shaded.osgi.framework.Version; 5 | import org.testng.shaded.osgi.framework.VersionRange; 6 | 7 | public abstract class AbstractRemoteTestNGFactory implements RemoteTestNGFactory { 8 | 9 | @Override 10 | public boolean accept(Version version) { 11 | return version == null || getAcceptableVersions().includes(version); 12 | } 13 | 14 | protected abstract VersionRange getAcceptableVersions(); 15 | } 16 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/IRemoteTestNG.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote; 2 | 3 | import org.testng.CommandLineArgs; 4 | 5 | public interface IRemoteTestNG { 6 | 7 | void dontExit(boolean dontExit); 8 | void setDebug(boolean debug); 9 | void setAck(boolean ack); 10 | void configure(CommandLineArgs cla); 11 | void setHost(String host); 12 | void setSerPort(Integer serPort); 13 | void setProtocol(String protocol); 14 | void setPort(Integer port); 15 | void run(); 16 | } 17 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/Orderable.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote; 2 | 3 | public interface Orderable { 4 | 5 | int getOrder(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/RemoteArgs.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote; 2 | 3 | import org.testng.shaded.osgi.framework.Version; 4 | 5 | import com.beust.jcommander.IStringConverter; 6 | import com.beust.jcommander.Parameter; 7 | 8 | public class RemoteArgs { 9 | public static final String DEBUG = "-serdebug"; 10 | @Parameter(names = DEBUG, hidden = true, description = "Used to debug TestNG") 11 | public Boolean debug = Boolean.FALSE; 12 | 13 | public static final String HOST = "-serhost"; 14 | @Parameter(names = HOST, description = "The host", hidden = true) 15 | public String host; 16 | 17 | public static final String PORT = "-serport"; 18 | @Parameter(names = PORT, description = "The port for the serialization protocol") 19 | public Integer serPort; 20 | 21 | public static final String PROTOCOL = "-protocol"; 22 | @Parameter(names = PROTOCOL, description = "The protocol for message inter-communication") 23 | public String protocol; 24 | 25 | public static final String DONT_EXIT= "-dontexit"; 26 | @Parameter(names = DONT_EXIT, description = "Do not exit the JVM once done") 27 | public boolean dontExit = false; 28 | 29 | public static final String ACK = "-ack"; 30 | @Parameter(names = ACK, description = "Use ACK's") 31 | public boolean ack = false; 32 | 33 | public static final String VERSION = "-version"; 34 | @Parameter(names = VERSION, description = "TestNG target version", converter = VersionConverter.class) 35 | public Version version; 36 | 37 | public static class VersionConverter implements IStringConverter { 38 | 39 | @Override 40 | public Version convert(String value) { 41 | if (value == null) { 42 | return null; 43 | } 44 | 45 | return RemoteTestNG.toVersion(value); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/AbstractRemoteTestRunnerClient.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2000, 2004 IBM Corporation and others. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Common Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/cpl-v10.html 7 | * 8 | * Contributors: 9 | * IBM Corporation - initial API and implementation 10 | * Julien Ruaux: jruaux@octo.com 11 | * Vincent Massol: vmassol@octo.com 12 | * 13 | * Adapted by: 14 | * Alexandru Popescu: the_mindstorm@evolva.ro 15 | ******************************************************************************/ 16 | package org.testng.remote.strprotocol; 17 | 18 | 19 | import org.testng.TestNGException; 20 | 21 | import java.io.IOException; 22 | import java.net.ServerSocket; 23 | import java.net.Socket; 24 | 25 | /** 26 | * The client side of the RemoteTestRunner. Handles the 27 | * marshaling of the different messages. 28 | */ 29 | public abstract class AbstractRemoteTestRunnerClient { 30 | /** 31 | * An array of listeners that are informed about test events. 32 | */ 33 | protected IRemoteSuiteListener[] m_suiteListeners; 34 | protected IRemoteTestListener[] m_testListeners; 35 | 36 | /** 37 | * The server socket 38 | */ 39 | private ServerSocket fServerSocket; 40 | private Socket fSocket; 41 | private ServerConnection m_serverConnection; 42 | // private PrintWriter m_outputWriter; 43 | // private BufferedReader m_inputReader; 44 | 45 | /** 46 | * Start listening to a test run. Start a server connection that 47 | * the RemoteTestRunner can connect to. 48 | */ 49 | public synchronized void startListening(IRemoteSuiteListener[] suiteListeners, 50 | IRemoteTestListener[] testListeners, 51 | ServerConnection serverConnection) { 52 | m_suiteListeners= suiteListeners; 53 | m_testListeners= testListeners; 54 | m_serverConnection = serverConnection; 55 | 56 | serverConnection.start(); 57 | } 58 | 59 | public IRemoteSuiteListener[] getSuiteListeners() { 60 | return m_suiteListeners; 61 | } 62 | 63 | public IRemoteTestListener[] getTestListeners() { 64 | return m_testListeners; 65 | } 66 | 67 | private synchronized void shutdown() { 68 | // if(m_outputWriter != null) { 69 | // m_outputWriter.close(); 70 | // m_outputWriter = null; 71 | // } 72 | // try { 73 | // if(m_inputReader != null) { 74 | // m_inputReader.close(); 75 | // m_inputReader = null; 76 | // } 77 | // } 78 | // catch(IOException e) { 79 | // e.printStackTrace(); 80 | // } 81 | try { 82 | if(fSocket != null) { 83 | fSocket.close(); 84 | fSocket = null; 85 | } 86 | } 87 | catch(IOException e) { 88 | e.printStackTrace(); 89 | } 90 | try { 91 | if(fServerSocket != null) { 92 | fServerSocket.close(); 93 | fServerSocket = null; 94 | } 95 | } 96 | catch(IOException e) { 97 | e.printStackTrace(); 98 | } 99 | } 100 | 101 | public boolean isRunning() { 102 | return m_serverConnection.getMessageSender() != null; 103 | } 104 | 105 | /** 106 | * Requests to stop the remote test run. 107 | */ 108 | public synchronized void stopTest() { 109 | if(isRunning()) { 110 | m_serverConnection.getMessageSender().sendStop(); 111 | shutdown(); 112 | } 113 | } 114 | 115 | // private String readMessage(BufferedReader in) throws IOException { 116 | // return in.readLine(); 117 | // } 118 | // 119 | // private void receiveMessage(String message) { 120 | // int messageType = MessageHelper.getMessageType(message); 121 | // 122 | // try { 123 | // if(messageType < MessageHelper.SUITE) { 124 | // // Generic message 125 | // GenericMessage gm = MessageHelper.unmarshallGenericMessage(message); 126 | // notifyStart(gm); 127 | // } 128 | // else if(messageType < MessageHelper.TEST) { 129 | // // Suite message 130 | // SuiteMessage sm = MessageHelper.createSuiteMessage(message); 131 | // notifySuiteEvents(sm); 132 | // } 133 | // else if(messageType < MessageHelper.TEST_RESULT) { 134 | // // Test message 135 | // TestMessage tm = MessageHelper.createTestMessage(message); 136 | // notifyTestEvents(tm); 137 | // } 138 | // else { 139 | // // TestResult message 140 | // TestResultMessage trm = MessageHelper.unmarshallTestResultMessage(message); 141 | // notifyResultEvents(trm); 142 | // } 143 | // } 144 | // finally { 145 | // if(isRunning() && (null != m_outputWriter)) { 146 | // m_outputWriter.println(MessageHelper.ACK_MSG); 147 | // m_outputWriter.flush(); 148 | // } 149 | // } 150 | // } 151 | 152 | protected abstract void notifyStart(final GenericMessage genericMessage); 153 | 154 | protected abstract void notifySuiteEvents(final SuiteMessage suiteMessage); 155 | 156 | protected abstract void notifyTestEvents(final TestMessage testMessage); 157 | 158 | protected abstract void notifyResultEvents(final TestResultMessage testResultMessage); 159 | 160 | 161 | /** 162 | * Reads the message stream from the RemoteTestRunner 163 | */ 164 | public abstract class ServerConnection extends Thread { 165 | private MessageHub m_messageHub; 166 | 167 | public ServerConnection(IMessageSender messageMarshaller) { 168 | super("TestNG - ServerConnection"); //$NON-NLS-1$ 169 | m_messageHub = new MessageHub(messageMarshaller); 170 | } 171 | 172 | IMessageSender getMessageSender() { 173 | return m_messageHub != null ? m_messageHub.getMessageSender() : null; 174 | } 175 | 176 | @Override 177 | public void run() { 178 | try { 179 | IMessage message = m_messageHub.receiveMessage(); 180 | while (message != null) { 181 | switch (message.getType()) { 182 | case GENERIC: 183 | notifyStart((GenericMessage) message); 184 | break; 185 | case SUITE: 186 | notifySuiteEvents((SuiteMessage) message); 187 | break; 188 | case TEST: 189 | notifyTestEvents((TestMessage) message); 190 | break; 191 | case TEST_RESULT: 192 | notifyResultEvents((TestResultMessage) message); 193 | break; 194 | default: 195 | throw new TestNGException("Unknown message type:" + message); 196 | } 197 | // if (isRunning()) { 198 | // m_messageMarshaller.sendAck(); 199 | // } 200 | message = m_messageHub.receiveMessage(); 201 | } 202 | } 203 | finally { 204 | m_messageHub.shutDown(); 205 | m_messageHub = null; 206 | } 207 | // try { 208 | // fServerSocket = new ServerSocket(fServerPort); 209 | // fSocket = fServerSocket.accept(); 210 | // try { 211 | // m_inputReader = new BufferedReader(new InputStreamReader(fSocket.getInputStream(), 212 | // "UTF-8")); //$NON-NLS-1$ 213 | // } 214 | // catch(UnsupportedEncodingException e) { 215 | // m_inputReader = new BufferedReader(new InputStreamReader(fSocket.getInputStream())); 216 | // } 217 | // try { 218 | // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream(), "UTF-8"), 219 | // true); 220 | // } 221 | // catch(UnsupportedEncodingException e1) { 222 | // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream()), true); 223 | // } 224 | // String message; 225 | // while((m_inputReader != null) && ((message = readMessage(m_inputReader)) != null)) { 226 | // receiveMessage(message); 227 | // } 228 | // } 229 | // catch(SocketException e) { 230 | // handleThrowable(e); 231 | // } 232 | // catch(IOException e) { 233 | // handleThrowable(e); 234 | // } 235 | // finally { 236 | // shutdown(); 237 | // } 238 | } 239 | 240 | protected abstract void handleThrowable(Throwable cause); 241 | } 242 | 243 | } 244 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/BaseMessageSender.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.BufferedWriter; 5 | import java.io.Closeable; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStream; 10 | import java.io.OutputStreamWriter; 11 | import java.io.PrintWriter; 12 | import java.io.UnsupportedEncodingException; 13 | import java.net.ConnectException; 14 | import java.net.InetSocketAddress; 15 | import java.net.ServerSocket; 16 | import java.net.Socket; 17 | import java.net.SocketTimeoutException; 18 | 19 | import org.testng.TestNGException; 20 | 21 | import static org.testng.remote.RemoteTestNG.isVerbose; 22 | import static org.testng.remote.RemoteTestNG.isDebug; 23 | 24 | abstract public class BaseMessageSender implements IMessageSender { 25 | protected Socket m_clientSocket; 26 | private String m_host; 27 | private int m_port; 28 | protected Object m_ackLock = new Object(); 29 | 30 | private boolean m_requestStopReceiver; 31 | private ServerSocket m_serverSocket; 32 | /** Outgoing message stream. */ 33 | protected OutputStream m_outStream; 34 | /** Used to send ACK and STOP */ 35 | private PrintWriter m_outWriter; 36 | 37 | /** Incoming message stream. */ 38 | protected volatile InputStream m_inStream; 39 | /** Used to receive ACK and STOP */ 40 | protected volatile BufferedReader m_inReader; 41 | 42 | private ReaderThread m_readerThread; 43 | private boolean m_ack; 44 | // protected InputStream m_receiverInputStream; 45 | 46 | public BaseMessageSender(String host, int port, boolean ack) { 47 | m_host = host; 48 | m_port = port; 49 | m_ack = ack; 50 | } 51 | 52 | /** 53 | * Starts the connection. 54 | * 55 | * @throws TestNGException if an exception occurred while establishing the connection 56 | */ 57 | @Override 58 | public void connect() throws IOException { 59 | p("Waiting for Eclipse client on " + m_host + ":" + m_port); 60 | while (true) { 61 | try { 62 | m_clientSocket = new Socket(); 63 | m_clientSocket.connect(new InetSocketAddress(m_host, m_port), 60 * 1000); 64 | p("Received a connection from Eclipse on " + m_host + ":" + m_port); 65 | 66 | // Output streams 67 | m_outStream = m_clientSocket.getOutputStream(); 68 | m_outWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(m_outStream))); 69 | 70 | // Input streams 71 | m_inStream = m_clientSocket.getInputStream(); 72 | try { 73 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream, 74 | "UTF-8")); //$NON-NLS-1$ 75 | } 76 | catch(UnsupportedEncodingException ueex) { 77 | // Should never happen 78 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream)); 79 | } 80 | 81 | p("Connection established, starting reader thread"); 82 | m_readerThread = new ReaderThread(); 83 | m_readerThread.start(); 84 | return; 85 | } 86 | catch(SocketTimeoutException | ConnectException ex) { 87 | p("connect failed: " + ex.toString()); 88 | // ignore and retry 89 | try { 90 | Thread.sleep(4000); 91 | } 92 | catch(InterruptedException handled) { 93 | Thread.currentThread().interrupt(); 94 | } 95 | } 96 | } 97 | } 98 | 99 | private void sendAdminMessage(String message) { 100 | m_outWriter.println(message); 101 | m_outWriter.flush(); 102 | } 103 | 104 | private int m_serial = 0; 105 | 106 | @Override 107 | public void sendAck() { 108 | p("Sending ACK " + m_serial); 109 | // Note: adding the serial at the end of this message causes a lock up if interacting 110 | // with TestNG 5.14 and older (reported by JetBrains). The following git commit: 111 | // 5730bdfb33ec7a8bf4104852cd4a5f2875ba8267 112 | // changed equals() to startsWith(). 113 | // It's ok to add this serial back for debugging, but don't commit it until JetBrains 114 | // confirms they no longer need backward compatibility with 5.14. 115 | sendAdminMessage(MessageHelper.ACK_MSG); // + m_serial++); 116 | } 117 | 118 | @Override 119 | public void sendStop() { 120 | sendAdminMessage(MessageHelper.STOP_MSG); 121 | } 122 | 123 | @Override 124 | public void initReceiver() throws SocketTimeoutException { 125 | if (m_inStream != null) { 126 | p("Receiver already initialized"); 127 | } 128 | try { 129 | p("initReceiver on port " + m_port); 130 | m_serverSocket = new ServerSocket(m_port); 131 | m_serverSocket.setSoTimeout(5000); 132 | 133 | Socket socket = null; 134 | while (!m_requestStopReceiver) { 135 | try { 136 | if (isDebug()) { 137 | p("polling the client connection"); 138 | } 139 | socket = m_serverSocket.accept(); 140 | // break the loop once the first client connected 141 | break; 142 | } 143 | catch (IOException ioe) { 144 | try { 145 | Thread.sleep(100L); 146 | } 147 | catch (InterruptedException ie) { 148 | // Do nothing. 149 | } 150 | } 151 | } 152 | if (socket != null) { 153 | m_inStream = socket.getInputStream(); 154 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream)); 155 | m_outStream = socket.getOutputStream(); 156 | m_outWriter = new PrintWriter(new OutputStreamWriter(m_outStream)); 157 | } 158 | } 159 | catch(SocketTimeoutException ste) { 160 | throw ste; 161 | } 162 | catch (IOException ioe) { 163 | closeQuietly(m_serverSocket); 164 | } 165 | } 166 | 167 | public void stopReceiver() { 168 | m_requestStopReceiver = true; 169 | try { 170 | if (!m_serverSocket.isClosed()) { 171 | m_serverSocket.close(); 172 | } 173 | } catch (IOException e) { 174 | if (isDebug()) { 175 | e.printStackTrace(); 176 | } 177 | } 178 | p("Stopped receiver"); 179 | } 180 | 181 | @Override 182 | public void shutDown() { 183 | closeQuietly(m_outStream); 184 | m_outStream = null; 185 | 186 | if (null != m_readerThread) { 187 | m_readerThread.interrupt(); 188 | } 189 | 190 | closeQuietly(m_inReader); 191 | m_inReader = null; 192 | 193 | closeQuietly(m_clientSocket); 194 | m_clientSocket = null; 195 | } 196 | 197 | private void closeQuietly(Closeable c) { 198 | if (c != null) { 199 | try { 200 | c.close(); 201 | } catch (IOException e) { 202 | if (isDebug()) { 203 | e.printStackTrace(); 204 | } 205 | } 206 | } 207 | } 208 | 209 | private String m_latestAck; 210 | 211 | protected void waitForAck() { 212 | if (m_ack) { 213 | try { 214 | p("Message sent, waiting for ACK..."); 215 | synchronized(m_ackLock) { 216 | m_ackLock.wait(); 217 | } 218 | p("... ACK received:" + m_latestAck); 219 | } 220 | catch(InterruptedException handled) { 221 | Thread.currentThread().interrupt(); 222 | } 223 | } 224 | } 225 | 226 | private static void p(String msg) { 227 | if (isVerbose()) { 228 | System.out.println("[BaseMessageSender] " + msg); //$NON-NLS-1$ 229 | } 230 | } 231 | 232 | /** 233 | * Reader thread that processes messages from the client. 234 | */ 235 | private class ReaderThread extends Thread { 236 | 237 | public ReaderThread() { 238 | super("ReaderThread"); //$NON-NLS-1$ 239 | } 240 | 241 | @Override 242 | public void run() { 243 | try { 244 | p("ReaderThread waiting for an admin message"); 245 | String message = m_inReader.readLine(); 246 | p("ReaderThread received admin message:" + message); 247 | while (message != null) { 248 | if (isDebug()) { 249 | p("Admin message:" + message); //$NON-NLS-1$ 250 | } 251 | boolean acknowledge = message.startsWith(MessageHelper.ACK_MSG); 252 | boolean stop = MessageHelper.STOP_MSG.equals(message); 253 | if(acknowledge || stop) { 254 | if (acknowledge) { 255 | p("Received ACK:" + message); 256 | m_latestAck = message; 257 | } 258 | synchronized(m_ackLock) { 259 | m_ackLock.notifyAll(); 260 | } 261 | if (stop) { 262 | break; 263 | } 264 | } else { 265 | p("Received unknown message: '" + message + "'"); 266 | } 267 | message = m_inReader != null ? m_inReader.readLine() : null; 268 | } 269 | // while((m_reader != null) && (message = m_reader.readLine()) != null) { 270 | // if (m_debug) { 271 | // p("Admin message:" + message); //$NON-NLS-1$ 272 | // } 273 | // boolean acknowledge = MessageHelper.ACK_MSG.equals(message); 274 | // boolean stop = MessageHelper.STOP_MSG.equals(message); 275 | // if(acknowledge || stop) { 276 | // synchronized(m_lock) { 277 | // m_lock.notifyAll(); 278 | // } 279 | // if (stop) { 280 | // break; 281 | // } 282 | // } 283 | // } 284 | } 285 | catch(IOException ioe) { 286 | if (isVerbose()) { 287 | ioe.printStackTrace(); 288 | } 289 | } 290 | } 291 | } 292 | } 293 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/GenericMessage.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * A generic message to be used with remote listeners. 7 | * It is described by a {@link #m_messageType} and can contain a Map 8 | * or values. 9 | * 10 | * @author Alexandru Popescu 11 | */ 12 | public class GenericMessage implements IStringMessage { 13 | private static final long serialVersionUID = 1440074281953763545L; 14 | // protected Map m_properties; 15 | @SerializedName("messageType") 16 | protected final MessageType m_messageType; 17 | @SerializedName("suiteCount") 18 | private int m_suiteCount; 19 | @SerializedName("testCount") 20 | private int m_testCount; 21 | 22 | public GenericMessage() { 23 | this(MessageType.GENERIC); 24 | } 25 | 26 | public GenericMessage(final MessageType type) { 27 | m_messageType = type; 28 | } 29 | 30 | public int getSuiteCount() { 31 | return m_suiteCount; 32 | } 33 | 34 | public void setSuiteCount(int suiteCount) { 35 | m_suiteCount = suiteCount; 36 | } 37 | 38 | public int getTestCount() { 39 | return m_testCount; 40 | } 41 | 42 | public void setTestCount(int testCount) { 43 | m_testCount = testCount; 44 | } 45 | 46 | @Override 47 | public MessageType getType() { 48 | return m_messageType; 49 | } 50 | 51 | @Override 52 | public String getMessageAsString() { 53 | StringBuffer buf = new StringBuffer(); 54 | 55 | buf.append(getType().getValue()); 56 | buf.append(MessageHelper.DELIMITER).append("testCount").append(getTestCount()) 57 | .append(MessageHelper.DELIMITER).append("suiteCount").append(getSuiteCount()); 58 | 59 | return buf.toString(); 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | StringBuilder sb = new StringBuilder(); 65 | sb.append("[GenericMessage ==> suiteCount:").append(m_suiteCount).append(", testCount:").append(m_testCount).append("]"); 66 | return sb.toString(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/IMessage.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import java.io.Serializable; 4 | 5 | 6 | /** 7 | * Marker interface for messages exchanged between RemoteTestNG and a client. 8 | * 9 | * @author Cedric Beust 10 | */ 11 | public interface IMessage extends Serializable { 12 | 13 | /** 14 | * @return the message type 15 | */ 16 | MessageType getType(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/IMessageSender.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import java.io.IOException; 4 | import java.net.SocketException; 5 | import java.net.SocketTimeoutException; 6 | 7 | public interface IMessageSender { 8 | 9 | void connect() throws IOException; 10 | 11 | /** 12 | * Initialize the receiver. 13 | * the underlying socket server will be polling until a first client connect. 14 | * 15 | * @throws SocketException This exception will be thrown if a connection 16 | * to the remote TestNG instance could not be established after ten 17 | * seconds. 18 | */ 19 | void initReceiver() throws SocketTimeoutException; 20 | 21 | /** 22 | * Stop the receiver. 23 | * it provides a way that allow the API invoker to stop the receiver, 24 | * e.g. break from a dead while loop 25 | */ 26 | void stopReceiver(); 27 | 28 | void sendMessage(IMessage message) throws Exception; 29 | 30 | /** 31 | * Will return null or throw EOFException when the connection has been severed. 32 | */ 33 | IMessage receiveMessage() throws Exception; 34 | 35 | void shutDown(); 36 | 37 | // These two methods should probably be in a separate class since they should all be 38 | // the same for implementers of this interface. 39 | void sendAck(); 40 | 41 | void sendStop(); 42 | } 43 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/IRemoteSuiteListener.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | 4 | 5 | /** 6 | * Interface replicating the ISuiteListener used for remote listeners. 7 | * 8 | * @author Alexandru Popescu 9 | * @see org.testng.ISuiteListener 10 | */ 11 | public interface IRemoteSuiteListener { 12 | /** 13 | * General information about the number of suites to be run. 14 | * This is called once before all suites. 15 | * 16 | * @param genericMessage a message containing the number of suites that will be run 17 | */ 18 | void onInitialization(GenericMessage genericMessage); 19 | 20 | /** 21 | * @see org.testng.ISuiteListener#onStart(org.testng.ISuite) 22 | * 23 | * @param suiteMessage the suite message containing the description of the suite to be run. 24 | */ 25 | void onStart(SuiteMessage suiteMessage); 26 | 27 | /** 28 | * @see org.testng.ISuiteListener#onFinish(org.testng.ISuite) 29 | * 30 | * @param suiteMessage the suite message containing infos about the finished suite. 31 | */ 32 | void onFinish(SuiteMessage suiteMessage); 33 | } 34 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/IRemoteTestListener.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | 4 | 5 | /** 6 | * Interface replicating ITestListener for remote listeners. 7 | * 8 | * @author Alexandru Popescu 9 | * @see org.testng.ITestListener 10 | */ 11 | public interface IRemoteTestListener { 12 | void onStart(TestMessage tm); 13 | 14 | void onFinish(TestMessage tm); 15 | 16 | void onTestStart(TestResultMessage trm); 17 | 18 | void onTestSuccess(TestResultMessage trm); 19 | 20 | void onTestFailure(TestResultMessage trm); 21 | 22 | void onTestSkipped(TestResultMessage trm); 23 | 24 | void onTestFailedButWithinSuccessPercentage(TestResultMessage trm); 25 | } 26 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/IStringMessage.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | 4 | /** 5 | * String based protocol main interface to be used with remote listeners. 6 | * 7 | * @author Alexandru Popescu 8 | */ 9 | public interface IStringMessage extends IMessage { 10 | String getMessageAsString(); 11 | } 12 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/JsonMessageSender.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import static org.testng.remote.RemoteTestNG.isVerbose; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.BufferedWriter; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStreamWriter; 10 | import java.io.StringReader; 11 | import java.io.UnsupportedEncodingException; 12 | 13 | import com.google.gson.Gson; 14 | import com.google.gson.GsonBuilder; 15 | import com.google.gson.stream.JsonReader; 16 | import com.google.gson.stream.JsonWriter; 17 | 18 | public class JsonMessageSender extends BaseMessageSender { 19 | 20 | public JsonMessageSender(String host, int port) { 21 | super(host, port, false); 22 | } 23 | 24 | public JsonMessageSender(String host, int port, boolean ack) { 25 | super(host, port, ack); 26 | } 27 | 28 | @Override 29 | public void sendMessage(IMessage message) throws Exception { 30 | if (m_outStream == null) { 31 | throw new IllegalStateException("Trying to send a message on a shutdown sender"); 32 | } 33 | 34 | synchronized (m_outStream) { 35 | p("Sending message " + message); 36 | 37 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(m_outStream, "UTF-8")); 38 | JsonWriter writer = new JsonWriter(bw); 39 | writeMessage(writer, message); 40 | bw.newLine(); 41 | bw.flush(); 42 | 43 | waitForAck(); 44 | } 45 | } 46 | 47 | void writeMessage(JsonWriter writer, IMessage message) throws IOException { 48 | writer.beginObject(); 49 | 50 | MessageType messageType = message.getType(); 51 | writer.name("type").value(messageType.getValue()); 52 | writer.name("data"); 53 | Gson gson = new GsonBuilder().create(); 54 | gson.toJson(message, message.getClass(), writer); 55 | 56 | writer.endObject(); 57 | } 58 | 59 | @Override 60 | public IMessage receiveMessage() throws Exception { 61 | if (m_inReader == null) { 62 | try { 63 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream, "UTF-8")); 64 | } catch (UnsupportedEncodingException e) { 65 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream)); 66 | } 67 | } 68 | String msg = m_inReader.readLine(); 69 | p("received message: " + msg); 70 | 71 | IMessage message = null; 72 | if (msg != null) { 73 | message = deserializeMessage(msg); 74 | } 75 | 76 | try { 77 | sendAck(); 78 | } catch (Exception e) { 79 | if (isVerbose()) { 80 | System.out.println("sendAck failed with error: " + e.getMessage()); 81 | e.printStackTrace(); 82 | } 83 | } 84 | return message; 85 | } 86 | 87 | IMessage deserializeMessage(String jsonMsg) throws IOException { 88 | try (JsonReader reader = new JsonReader(new StringReader(jsonMsg))) { 89 | reader.beginObject(); 90 | 91 | String name = reader.nextName(); 92 | if (!"type".equals(name)) { 93 | throw new IOException("type node first"); 94 | } 95 | 96 | int msgType = reader.nextInt(); 97 | MessageType type = MessageType.fromValue(msgType); 98 | if (type == null) { 99 | throw new IOException("unknown message type: " + msgType + ", raw json: " + jsonMsg); 100 | } 101 | 102 | name = reader.nextName(); 103 | if (!"data".equals(name)) { 104 | throw new IOException("data node then"); 105 | } 106 | 107 | Gson gson = new GsonBuilder().create(); 108 | IMessage message = null; 109 | switch (type) { 110 | case GENERIC: 111 | message = gson.fromJson(reader, GenericMessage.class); 112 | break; 113 | case SUITE: 114 | message = gson.fromJson(reader, SuiteMessage.class); 115 | break; 116 | case TEST: 117 | message = gson.fromJson(reader, TestMessage.class); 118 | break; 119 | case TEST_RESULT: 120 | message = gson.fromJson(reader, TestResultMessage.class); 121 | break; 122 | default: 123 | throw new IOException("unsupported message type: " + msgType + ", raw json: " + jsonMsg); 124 | } 125 | 126 | reader.endObject(); 127 | 128 | return message; 129 | } 130 | } 131 | 132 | private static void p(String msg) { 133 | if (isVerbose()) { 134 | System.out.println("[JsonMessageSender] " + msg); //$NON-NLS-1$ 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/MessageHelper.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | 4 | import org.testng.ITestResult; 5 | import org.testng.collections.Lists; 6 | 7 | import java.util.List; 8 | import java.util.regex.Pattern; 9 | 10 | 11 | /** 12 | * Marshal/unmarshal tool for IStringMessages. 13 | * 14 | * @author Alexandru Popescu 15 | */ 16 | public class MessageHelper { 17 | public static final char DELIMITER = '\u0001'; 18 | public static final char PARAM_DELIMITER = '\u0004'; 19 | private static final char LINE_SEP_DELIMITER_1 = '\u0002'; 20 | private static final char LINE_SEP_DELIMITER_2 = '\u0003'; 21 | 22 | public static final int GENERIC_SUITE_COUNT = 1; 23 | 24 | public static final int SUITE = 10; 25 | public static final int SUITE_START = 11; 26 | public static final int SUITE_FINISH = 12; 27 | 28 | public static final int TEST = 100; 29 | public static final int TEST_START = 101; 30 | public static final int TEST_FINISH = 102; 31 | 32 | public static final int TEST_RESULT = 1000; 33 | public static final int PASSED_TEST = TEST_RESULT + ITestResult.SUCCESS; 34 | public static final int FAILED_TEST = TEST_RESULT + ITestResult.FAILURE; 35 | public static final int SKIPPED_TEST = TEST_RESULT + ITestResult.SKIP; 36 | public static final int FAILED_ON_PERCENTAGE_TEST = TEST_RESULT + ITestResult.SUCCESS_PERCENTAGE_FAILURE; 37 | public static final int TEST_STARTED = TEST_RESULT + ITestResult.STARTED; 38 | 39 | public static final String STOP_MSG = ">STOP"; 40 | public static final String ACK_MSG = ">ACK"; 41 | 42 | public static int getMessageType(final String message) { 43 | int idx = message.indexOf(DELIMITER); 44 | 45 | return idx == -1 ? Integer.parseInt(message) : Integer.parseInt(message.substring(0, idx)); 46 | } 47 | 48 | public static GenericMessage unmarshallGenericMessage(final String message) { 49 | String[] messageParts = parseMessage(message); 50 | if(messageParts.length == 1) { 51 | return new GenericMessage(MessageType.fromValue(messageParts[0])); 52 | } 53 | else { 54 | GenericMessage result = new GenericMessage(MessageType.fromValue(messageParts[0])); 55 | 56 | for(int i = 1; i < messageParts.length; i+=2) { 57 | if ("testCount".equals(messageParts[i])) { 58 | result.setTestCount(Integer.parseInt(messageParts[i + 1])); 59 | } else if ("suiteCount".equals(messageParts[i])) { 60 | result.setSuiteCount(Integer.parseInt(messageParts[i + 1])); 61 | } 62 | } 63 | 64 | return result; 65 | } 66 | } 67 | 68 | public static SuiteMessage createSuiteMessage(final String message) { 69 | int type = getMessageType(message); 70 | String[] messageParts = parseMessage(message); 71 | 72 | SuiteMessage result = new SuiteMessage(messageParts[1], 73 | MessageHelper.SUITE_START == type, 74 | Integer.parseInt(messageParts[2])); 75 | // Any excluded methods? 76 | if (messageParts.length > 3) { 77 | int count = Integer.parseInt(messageParts[3]); 78 | if (count > 0) { 79 | List methods = Lists.newArrayList(); 80 | int i = 4; 81 | while (count-- > 0) { 82 | methods.add(messageParts[i++]); 83 | } 84 | result.setExcludedMethods(methods); 85 | } 86 | } 87 | 88 | return result; 89 | } 90 | 91 | public static TestMessage createTestMessage(final String message) { 92 | int type = getMessageType(message); 93 | String[] messageParts = parseMessage(message); 94 | 95 | return new TestMessage(MessageHelper.TEST_START == type, 96 | messageParts[1], 97 | messageParts[2], 98 | Integer.parseInt(messageParts[3]), 99 | Integer.parseInt(messageParts[4]), 100 | Integer.parseInt(messageParts[5]), 101 | Integer.parseInt(messageParts[6]), 102 | Integer.parseInt(messageParts[7])); 103 | } 104 | 105 | public static TestResultMessage unmarshallTestResultMessage(final String message) { 106 | String[] messageParts = parseMessage(message); 107 | 108 | String parametersFragment= null; 109 | String startTimestampFragment= null; 110 | String stopTimestampFragment= null; 111 | String stackTraceFragment= null; 112 | String testDescriptor= null; 113 | switch(messageParts.length) { 114 | case 10: 115 | { 116 | parametersFragment= messageParts[5]; 117 | startTimestampFragment= messageParts[6]; 118 | stopTimestampFragment= messageParts[7]; 119 | stackTraceFragment= messageParts[8]; 120 | testDescriptor= messageParts[9]; 121 | } 122 | break; 123 | case 9: 124 | { 125 | parametersFragment= messageParts[5]; 126 | startTimestampFragment= messageParts[6]; 127 | stopTimestampFragment= messageParts[7]; 128 | stackTraceFragment= messageParts[8]; 129 | } 130 | break; 131 | default: 132 | { 133 | // HINT: old protocol without parameters 134 | parametersFragment= null; 135 | startTimestampFragment= messageParts[5]; 136 | stopTimestampFragment= messageParts[6]; 137 | stackTraceFragment= messageParts[7]; 138 | } 139 | } 140 | return new TestResultMessage(Integer.parseInt(messageParts[0]), 141 | messageParts[1], 142 | messageParts[2], 143 | messageParts[3], 144 | messageParts[4], 145 | replaceAsciiCharactersWithUnicode(replaceNewLineReplacer(testDescriptor)), 146 | replaceAsciiCharactersWithUnicode(replaceNewLineReplacer(testDescriptor)), 147 | parseParameters(parametersFragment), 148 | Long.parseLong(startTimestampFragment), 149 | Long.parseLong(stopTimestampFragment), 150 | replaceAsciiCharactersWithUnicode(replaceNewLineReplacer(stackTraceFragment)), 151 | 0, 0 /* invocation counts not supported by this protocol */ 152 | ); 153 | } 154 | 155 | public static String replaceNewLine(String message) { 156 | if(null == message) { 157 | return message; 158 | } 159 | 160 | return message.replace('\n', LINE_SEP_DELIMITER_1).replace('\r', LINE_SEP_DELIMITER_2); 161 | } 162 | 163 | public static String replaceUnicodeCharactersWithAscii(String message) { 164 | if(null == message) { 165 | return message; 166 | } 167 | 168 | return replace( 169 | replace( 170 | replace( 171 | replace(message, "\u0004", "\\u0004"), 172 | "\u0003", "\\u0003"), 173 | "\u0002", "\\u0002"), 174 | "\u0001", "\\u0001"); 175 | } 176 | 177 | public static String replaceAsciiCharactersWithUnicode(String message) { 178 | if(null == message) { 179 | return message; 180 | } 181 | 182 | return replace( 183 | replace( 184 | replace( 185 | replace(message, "\\u0004", "\u0004"), 186 | "\\u0003", "\u0003"), 187 | "\\u0002", "\u0002"), 188 | "\\u0001", "\u0001"); 189 | } 190 | 191 | public static String replaceNewLineReplacer(String message) { 192 | if(null == message) { 193 | return message; 194 | } 195 | 196 | return message.replace(LINE_SEP_DELIMITER_1, '\n').replace(LINE_SEP_DELIMITER_2, '\r'); 197 | } 198 | 199 | private static String[] parseParameters(final String messagePart) { 200 | return tokenize(messagePart, PARAM_DELIMITER); 201 | } 202 | 203 | private static String[] parseMessage(final String message) { 204 | return tokenize(message, DELIMITER); 205 | } 206 | 207 | private static String[] tokenize(final String message, final char separator) { 208 | if(null == message) { 209 | return new String[0]; 210 | } 211 | 212 | List tokens = Lists.newArrayList(); 213 | int start = 0; 214 | for(int i = 0; i < message.length(); i++) { 215 | if(separator == message.charAt(i)) { 216 | tokens.add(message.substring(start, i)); 217 | start = i + 1; 218 | } 219 | } 220 | if(start < message.length()) { 221 | tokens.add(message.substring(start, message.length())); 222 | } 223 | 224 | return tokens.toArray(new String[tokens.size()]); 225 | } 226 | 227 | /** 228 | * Implementation according to JDK5 String.replace(CharSequence,CharSequence) 229 | */ 230 | private static final String replace(String original, CharSequence target, CharSequence replacement) { 231 | return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(original) 232 | .replaceAll(quoteReplacement(replacement.toString())); 233 | } 234 | 235 | /** 236 | * Implementation according to JDK5 String.replace(CharSequence,CharSequence) 237 | */ 238 | private static String quoteReplacement(String s) { 239 | if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1)) { 240 | return s; 241 | } 242 | StringBuffer sb = new StringBuffer(); 243 | for (int i=0; i 13 | */ 14 | public class MessageHub { 15 | 16 | private boolean m_debug = false; 17 | 18 | private IMessageSender m_messageSender; 19 | 20 | public MessageHub(IMessageSender messageSender) { 21 | m_messageSender = messageSender; 22 | } 23 | 24 | /** 25 | * Starts the connection. 26 | * 27 | * @throws TestNGException if an exception occurred while establishing the connection 28 | */ 29 | public void connect() throws IOException { 30 | m_messageSender.connect(); 31 | } 32 | 33 | /** 34 | * Shutsdown the connection to the remote test listener. 35 | */ 36 | public void shutDown() { 37 | m_messageSender.shutDown(); 38 | } 39 | 40 | public void sendMessage(IMessage message) { 41 | try { 42 | m_messageSender.sendMessage(message); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | public IMessage receiveMessage() { 49 | IMessage result = null; 50 | try { 51 | result = m_messageSender.receiveMessage(); 52 | m_messageSender.sendAck(); 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } 56 | return result; 57 | } 58 | 59 | public void setDebug(boolean debug) { 60 | m_debug = debug; 61 | } 62 | 63 | public void initReceiver() throws SocketTimeoutException { 64 | m_messageSender.initReceiver(); 65 | } 66 | 67 | public IMessageSender getMessageSender() { 68 | return m_messageSender; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/MessageType.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | public enum MessageType { 4 | 5 | GENERIC(MessageHelper.GENERIC_SUITE_COUNT), 6 | SUITE(MessageHelper.SUITE), 7 | TEST(MessageHelper.TEST), 8 | TEST_RESULT(MessageHelper.TEST_RESULT); 9 | 10 | private int type; 11 | 12 | MessageType(int type) { 13 | this.type = type; 14 | } 15 | 16 | public int getValue() { 17 | return type; 18 | } 19 | 20 | public static MessageType fromValue(int value) { 21 | for (MessageType type : MessageType.values()) { 22 | if (type.getValue() == value) { 23 | return type; 24 | } 25 | } 26 | return null; 27 | } 28 | 29 | public static MessageType fromValue(String value) { 30 | int val = Integer.parseInt(value); 31 | return fromValue(val); 32 | } 33 | 34 | public static MessageType fromName(String name) { 35 | for (MessageType type : MessageType.values()) { 36 | if (type.name().equals(name)) { 37 | return type; 38 | } 39 | } 40 | return null; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/RemoteTestListener.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import org.testng.ISuite; 4 | import org.testng.ITestResult; 5 | import org.testng.internal.IResultListener2; 6 | import org.testng.xml.XmlTest; 7 | 8 | /** 9 | * A special listener that remote the event with string protocol. 10 | * 11 | * @author Alexandru Popescu 12 | */ 13 | public class RemoteTestListener extends RemoteTestListener1 implements IResultListener2 { 14 | 15 | public RemoteTestListener(ISuite suite, XmlTest test, MessageHub msh) { 16 | super(suite, test, msh); 17 | } 18 | 19 | @Override 20 | public void beforeConfiguration(ITestResult tr) { 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/RemoteTestListener1.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import org.testng.ISuite; 4 | import org.testng.ITestContext; 5 | import org.testng.ITestResult; 6 | import org.testng.internal.IResultListener; 7 | import org.testng.xml.XmlTest; 8 | 9 | /** 10 | * A special listener that remote the event with string protocol. 11 | * 12 | * @author Alexandru Popescu 13 | */ 14 | public class RemoteTestListener1 implements IResultListener { 15 | private final MessageHub m_sender; 16 | private ISuite m_suite; 17 | private XmlTest m_xmlTest; 18 | private ITestContext m_currentTestContext; 19 | 20 | public RemoteTestListener1(ISuite suite, XmlTest test, MessageHub msh) { 21 | m_sender = msh; 22 | m_suite= suite; 23 | m_xmlTest= test; 24 | } 25 | 26 | @Override 27 | public void onStart(ITestContext testCtx) { 28 | m_currentTestContext = testCtx; 29 | m_sender.sendMessage(new TestMessage(testCtx, true /*start*/)); 30 | } 31 | 32 | @Override 33 | public void onFinish(ITestContext testCtx) { 34 | m_sender.sendMessage(new TestMessage(testCtx, false /*end*/)); 35 | m_currentTestContext = null; 36 | } 37 | 38 | @Override 39 | public void onTestStart(ITestResult testResult) { 40 | TestResultMessage trm= null; 41 | 42 | if (null == m_currentTestContext) { 43 | trm= new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult); 44 | } 45 | else { 46 | trm= new TestResultMessage(m_currentTestContext, testResult); 47 | } 48 | 49 | m_sender.sendMessage(trm); 50 | } 51 | 52 | @Override 53 | public void onTestFailedButWithinSuccessPercentage(ITestResult testResult) { 54 | if (null == m_currentTestContext) { 55 | m_sender.sendMessage(new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult)); 56 | } 57 | else { 58 | m_sender.sendMessage(new TestResultMessage(m_currentTestContext, testResult)); 59 | } 60 | } 61 | 62 | @Override 63 | public void onTestFailure(ITestResult testResult) { 64 | if (null == m_currentTestContext) { 65 | m_sender.sendMessage(new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult)); 66 | } 67 | else { 68 | m_sender.sendMessage(new TestResultMessage(m_currentTestContext, testResult)); 69 | } 70 | } 71 | 72 | @Override 73 | public void onTestSkipped(ITestResult testResult) { 74 | if (null == m_currentTestContext) { 75 | m_sender.sendMessage(new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult)); 76 | } 77 | else { 78 | m_sender.sendMessage(new TestResultMessage(m_currentTestContext, testResult)); 79 | } 80 | } 81 | 82 | @Override 83 | public void onTestSuccess(ITestResult testResult) { 84 | if (null == m_currentTestContext) { 85 | m_sender.sendMessage(new TestResultMessage(m_suite.getName(), m_xmlTest.getName(), testResult)); 86 | } 87 | else { 88 | m_sender.sendMessage(new TestResultMessage(m_currentTestContext, testResult)); 89 | } 90 | } 91 | 92 | /** 93 | * @see org.testng.IConfigurationListener#onConfigurationFailure(org.testng.ITestResult) 94 | */ 95 | @Override 96 | public void onConfigurationFailure(ITestResult itr) { 97 | // Show configuration failures in the main view for convenience 98 | onTestFailure(itr); 99 | } 100 | 101 | /** 102 | * @see org.testng.IConfigurationListener#onConfigurationSkip(org.testng.ITestResult) 103 | */ 104 | @Override 105 | public void onConfigurationSkip(ITestResult itr) { 106 | onTestSkipped(itr); 107 | } 108 | 109 | /** 110 | * @see org.testng.IConfigurationListener#onConfigurationSuccess(org.testng.ITestResult) 111 | */ 112 | @Override 113 | public void onConfigurationSuccess(ITestResult itr) { 114 | } 115 | } -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/SerializedMessageSender.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import org.testng.remote.RemoteTestNG; 4 | 5 | import java.io.IOException; 6 | import java.io.ObjectInputStream; 7 | import java.io.ObjectOutputStream; 8 | 9 | 10 | public class SerializedMessageSender extends BaseMessageSender { 11 | 12 | public SerializedMessageSender(String host, int port) { 13 | super(host, port, false /* no ack */); 14 | } 15 | 16 | public SerializedMessageSender(String host, int port, boolean ack) { 17 | super(host, port, ack); 18 | } 19 | 20 | @Override 21 | public void sendMessage(IMessage message) throws IOException { 22 | synchronized(m_outStream) { 23 | p("Sending message " + message); 24 | ObjectOutputStream oos = new ObjectOutputStream(m_outStream); 25 | oos.writeObject(message); 26 | oos.flush(); 27 | 28 | waitForAck(); 29 | } 30 | } 31 | 32 | @Override 33 | public IMessage receiveMessage() throws IOException, ClassNotFoundException { 34 | 35 | IMessage result = null; 36 | try { 37 | ObjectInputStream ios = new ObjectInputStream(m_inStream); 38 | // synchronized(m_input) { 39 | result = (IMessage) ios.readObject(); 40 | p("Received message " + result); 41 | // sendAck(); 42 | // } 43 | } 44 | catch(Exception ex) { 45 | if (RemoteTestNG.isVerbose()) { 46 | ex.printStackTrace(); 47 | } 48 | } 49 | return result; 50 | } 51 | 52 | static void p(String s) { 53 | if (RemoteTestNG.isVerbose()) { 54 | System.out.println("[SerializedMessageSender] " + s); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/StdoutMessageSender.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import java.io.IOException; 4 | import java.net.SocketTimeoutException; 5 | 6 | /** 7 | * this is a dummy IMessageSender implementation for test purpose only. 8 | * 9 | * @author nick 10 | */ 11 | public class StdoutMessageSender implements IMessageSender { 12 | 13 | @Override 14 | public void connect() throws IOException { 15 | // noop 16 | } 17 | 18 | @Override 19 | public void initReceiver() throws SocketTimeoutException { 20 | // noop 21 | } 22 | 23 | @Override 24 | public void stopReceiver() { 25 | // noop 26 | } 27 | 28 | @Override 29 | public void sendMessage(IMessage message) throws Exception { 30 | System.out.println(message); 31 | } 32 | 33 | @Override 34 | public IMessage receiveMessage() throws Exception { 35 | return null; 36 | } 37 | 38 | @Override 39 | public void shutDown() { 40 | // noop 41 | } 42 | 43 | @Override 44 | public void sendAck() { 45 | // noop 46 | } 47 | 48 | @Override 49 | public void sendStop() { 50 | // noop 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/StringMessageSender.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import org.testng.remote.RemoteTestNG; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.BufferedWriter; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStreamWriter; 10 | import java.io.PrintWriter; 11 | import java.io.UnsupportedEncodingException; 12 | 13 | public class StringMessageSender extends BaseMessageSender { 14 | 15 | private PrintWriter writer; 16 | 17 | public StringMessageSender(String host, int port) { 18 | super(host, port, false /* no ack */); 19 | } 20 | 21 | public StringMessageSender(String host, int port, boolean ack) { 22 | super(host, port, ack); 23 | } 24 | 25 | @Override 26 | public void sendMessage(IMessage message) { 27 | if (m_outStream == null) { 28 | throw new IllegalStateException("Trying to send a message on a shutdown sender"); 29 | } 30 | if (writer == null) { 31 | try { 32 | writer = new PrintWriter(new BufferedWriter( 33 | new OutputStreamWriter(m_outStream, "UTF-8")), //$NON-NLS-1$ 34 | false /* autoflush */); 35 | } catch (UnsupportedEncodingException e1) { 36 | writer = new PrintWriter(new BufferedWriter( 37 | new OutputStreamWriter(m_outStream)), 38 | false /* autoflush */); 39 | } 40 | } 41 | 42 | String msg = ((IStringMessage) message).getMessageAsString(); 43 | if (RemoteTestNG.isVerbose()) { 44 | p("Sending message:" + message); 45 | p(" String version:" + msg); 46 | 47 | StringBuffer buf = new StringBuffer(); 48 | for(int i = 0; i < msg.length(); i++) { 49 | if('\u0001' == msg.charAt(i)) { 50 | p(" word:[" + buf.toString() + "]"); 51 | buf.delete(0, buf.length()); 52 | } 53 | else { 54 | buf.append(msg.charAt(i)); 55 | } 56 | } 57 | p(" word:[" + buf.toString() + "]"); 58 | } 59 | 60 | synchronized(m_ackLock) { 61 | writer.println(msg); 62 | writer.flush(); 63 | waitForAck(); 64 | } 65 | } 66 | 67 | private static void p(String msg) { 68 | if (RemoteTestNG.isVerbose()) { 69 | System.out.println("[StringMessageSender] " + msg); //$NON-NLS-1$ 70 | } 71 | } 72 | 73 | @Override 74 | public IMessage receiveMessage() { 75 | IMessage result = null; 76 | 77 | if (m_inReader == null) { 78 | try { 79 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream, "UTF-8")); 80 | } catch (UnsupportedEncodingException e) { 81 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream)); 82 | } 83 | } 84 | try { 85 | // try { 86 | // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream(), "UTF-8"), 87 | // true); 88 | // } 89 | // catch(UnsupportedEncodingException e1) { 90 | // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream()), true); 91 | // } 92 | result = receiveMessage(m_inReader.readLine()); 93 | } catch(IOException e) { 94 | handleThrowable(e); 95 | } 96 | 97 | return result; 98 | // finally { 99 | // shutDown(); 100 | // return null; 101 | // } 102 | } 103 | 104 | protected void handleThrowable(Throwable cause) { 105 | if (RemoteTestNG.isVerbose()) { 106 | cause.printStackTrace(); 107 | } 108 | } 109 | 110 | // private String readMessage(BufferedReader in) throws IOException { 111 | // return in.readLine(); 112 | // } 113 | 114 | private IMessage receiveMessage(String message) { 115 | if (message == null) return null; 116 | IMessage result = null; 117 | 118 | int messageType = MessageHelper.getMessageType(message); 119 | 120 | // try { 121 | if(messageType < MessageHelper.SUITE) { 122 | // Generic message 123 | result = MessageHelper.unmarshallGenericMessage(message); 124 | } 125 | else if(messageType < MessageHelper.TEST) { 126 | // Suite message 127 | result = MessageHelper.createSuiteMessage(message); 128 | } 129 | else if(messageType < MessageHelper.TEST_RESULT) { 130 | // Test message 131 | result = MessageHelper.createTestMessage(message); 132 | } 133 | else { 134 | // TestResult message 135 | result = MessageHelper.unmarshallTestResultMessage(message); 136 | } 137 | // } 138 | // finally { 139 | // if(isRunning() && (null != m_outputWriter)) { 140 | // m_outputWriter.println(MessageHelper.ACK_MSG); 141 | // m_outputWriter.flush(); 142 | // } 143 | // } 144 | 145 | p("receiveMessage() received:" + result); 146 | return result; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/SuiteMessage.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import org.testng.ISuite; 8 | import org.testng.ITestNGMethod; 9 | import org.testng.collections.Lists; 10 | import org.testng.collections.Maps; 11 | 12 | import com.google.gson.annotations.SerializedName; 13 | 14 | 15 | /** 16 | * A IStringMessage implementation for suite running events. 17 | * 18 | * @author Alexandru Popescu 19 | */ 20 | public class SuiteMessage implements IStringMessage { 21 | private static final long serialVersionUID = -4298528261942620419L; 22 | @SerializedName("suiteName") 23 | protected final String m_suiteName; 24 | @SerializedName("methodCount") 25 | protected final int m_testMethodCount; 26 | @SerializedName("startSuiteRun") 27 | protected final boolean m_startSuite; 28 | @SerializedName("excludedMethods") 29 | private List m_excludedMethods = Lists.newArrayList(); 30 | private Map m_descriptions; 31 | 32 | public SuiteMessage(final String suiteName, final boolean startSuiteRun, final int methodCount) { 33 | m_suiteName = suiteName; 34 | m_startSuite = startSuiteRun; 35 | m_testMethodCount = methodCount; 36 | } 37 | 38 | public SuiteMessage(final ISuite suite, final boolean startSuiteRun) { 39 | m_suiteName = suite.getName(); 40 | m_testMethodCount =suite.getAllInvokedMethods().size(); 41 | m_startSuite = startSuiteRun; 42 | Collection excludedMethods = suite.getExcludedMethods(); 43 | if (excludedMethods != null && excludedMethods.size() > 0) { 44 | m_excludedMethods = Lists.newArrayList(); 45 | m_descriptions = Maps.newHashMap(); 46 | for (ITestNGMethod m : excludedMethods) { 47 | String methodName = m.getTestClass().getName() + "." + m.getMethodName(); 48 | m_excludedMethods.add(methodName); 49 | if (m.getDescription() != null) m_descriptions.put(methodName, m.getDescription()); 50 | } 51 | } 52 | } 53 | 54 | public void setExcludedMethods(List methods) { 55 | m_excludedMethods = Lists.newArrayList(); 56 | m_excludedMethods.addAll(methods); 57 | } 58 | 59 | public List getExcludedMethods() { 60 | return m_excludedMethods; 61 | } 62 | 63 | public String getDescriptionForMethod(String methodName) { 64 | return m_descriptions.get(methodName); 65 | } 66 | 67 | public boolean isMessageOnStart() { 68 | return m_startSuite; 69 | } 70 | 71 | public String getSuiteName() { 72 | return m_suiteName; 73 | } 74 | 75 | public int getTestMethodCount() { 76 | return m_testMethodCount; 77 | } 78 | 79 | @Override 80 | public String getMessageAsString() { 81 | StringBuffer buf = new StringBuffer(); 82 | 83 | buf.append(m_startSuite ? MessageHelper.SUITE_START : MessageHelper.SUITE_FINISH) 84 | .append(MessageHelper.DELIMITER) 85 | .append(m_suiteName) 86 | .append(MessageHelper.DELIMITER) 87 | .append(m_testMethodCount) 88 | ; 89 | 90 | if (m_excludedMethods != null && m_excludedMethods.size() > 0) { 91 | buf.append(MessageHelper.DELIMITER); 92 | buf.append(m_excludedMethods.size()); 93 | for (String method : m_excludedMethods) { 94 | buf.append(MessageHelper.DELIMITER); 95 | buf.append(method); 96 | } 97 | } 98 | return buf.toString(); 99 | } 100 | 101 | @Override 102 | public MessageType getType() { 103 | return MessageType.SUITE; 104 | } 105 | 106 | @Override 107 | public String toString() { 108 | StringBuilder sb = new StringBuilder(); 109 | sb.append("[SuiteMessage ==> suite:").append(m_suiteName) 110 | .append(m_startSuite ? ", starting" : ", ending") 111 | .append(", methodCount:" + m_testMethodCount) 112 | .append("]"); 113 | return sb.toString(); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/strprotocol/TestMessage.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import org.testng.ITestContext; 4 | 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | 8 | /** 9 | * An IStringMessage implementation for test events. 10 | * 11 | * @author Alexandru Popescu 12 | */ 13 | public class TestMessage implements IStringMessage { 14 | private static final long serialVersionUID = -5039267143570559640L; 15 | @SerializedName("testStart") 16 | protected final boolean m_testStart; 17 | @SerializedName("suiteName") 18 | protected final String m_suiteName; 19 | @SerializedName("testName") 20 | protected final String m_testName; 21 | @SerializedName("testMethodCount") 22 | protected final int m_testMethodCount; 23 | @SerializedName("passedTestCount") 24 | protected final int m_passedTestCount; 25 | @SerializedName("failedTestCount") 26 | protected final int m_failedTestCount; 27 | @SerializedName("skippedTestCount") 28 | protected final int m_skippedTestCount; 29 | @SerializedName("successPercentageFailedTestCount") 30 | protected final int m_successPercentageFailedTestCount; 31 | 32 | public TestMessage(final boolean isTestStart, 33 | final String suiteName, 34 | final String testName, 35 | final int methodCount, 36 | final int passedCount, 37 | final int failedCount, 38 | final int skippedCount, 39 | final int percentageCount) { 40 | m_testStart = isTestStart; 41 | m_suiteName = suiteName; 42 | m_testName = testName; 43 | m_testMethodCount = methodCount; 44 | m_passedTestCount = passedCount; 45 | m_failedTestCount = failedCount; 46 | m_skippedTestCount = skippedCount; 47 | m_successPercentageFailedTestCount = percentageCount; 48 | } 49 | 50 | public TestMessage(final ITestContext testContext, final boolean isTestStart) { 51 | this(isTestStart, 52 | testContext.getSuite().getName(), 53 | testContext.getCurrentXmlTest().getName(), 54 | testContext.getAllTestMethods().length, 55 | testContext.getPassedTests().size(), 56 | testContext.getFailedTests().size(), 57 | testContext.getSkippedTests().size(), 58 | testContext.getFailedButWithinSuccessPercentageTests().size()); 59 | } 60 | 61 | public boolean isMessageOnStart() { 62 | return m_testStart; 63 | } 64 | 65 | @Override 66 | public String getMessageAsString() { 67 | StringBuffer buf = new StringBuffer(); 68 | 69 | buf.append(m_testStart ? MessageHelper.TEST_START : MessageHelper.TEST_FINISH) 70 | .append(MessageHelper.DELIMITER) 71 | .append(m_suiteName) 72 | .append(MessageHelper.DELIMITER) 73 | .append(m_testName) 74 | .append(MessageHelper.DELIMITER) 75 | .append(m_testMethodCount) 76 | .append(MessageHelper.DELIMITER) 77 | .append(m_passedTestCount) 78 | .append(MessageHelper.DELIMITER) 79 | .append(m_failedTestCount) 80 | .append(MessageHelper.DELIMITER) 81 | .append(m_skippedTestCount) 82 | .append(MessageHelper.DELIMITER) 83 | .append(m_successPercentageFailedTestCount) 84 | ; 85 | 86 | return buf.toString(); 87 | } 88 | 89 | public String getSuiteName() { 90 | return m_suiteName; 91 | } 92 | 93 | public String getTestName() { 94 | return m_testName; 95 | } 96 | 97 | public boolean isTestStart() { 98 | return m_testStart; 99 | } 100 | public int getTestMethodCount() { 101 | return m_testMethodCount; 102 | } 103 | public int getSuccessPercentageFailedTestCount() { 104 | return m_successPercentageFailedTestCount; 105 | } 106 | public int getFailedTestCount() { 107 | return m_failedTestCount; 108 | } 109 | public int getPassedTestCount() { 110 | return m_passedTestCount; 111 | } 112 | public int getSkippedTestCount() { 113 | return m_skippedTestCount; 114 | } 115 | 116 | @Override 117 | public MessageType getType() { 118 | return MessageType.TEST; 119 | } 120 | 121 | @Override 122 | public String toString() { 123 | StringBuilder sb = new StringBuilder(); 124 | sb.append("[TestMessage ==> suite:").append(m_suiteName).append(", testName:").append(m_testName) 125 | .append(", passed:").append(m_passedTestCount).append(", failed:").append(m_failedTestCount) 126 | .append("]"); 127 | return sb.toString(); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/support/RemoteTestNGFactory.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.remote.IRemoteTestNG; 4 | import org.testng.remote.Orderable; 5 | import org.testng.shaded.osgi.framework.Version; 6 | 7 | public interface RemoteTestNGFactory extends Orderable { 8 | 9 | boolean accept(Version version); 10 | IRemoteTestNG createRemoteTestNG(); 11 | } 12 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/remote/support/ServiceLoaderHelper.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import java.io.*; 4 | import java.net.URL; 5 | import java.net.URLClassLoader; 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.Comparator; 9 | import java.util.List; 10 | import java.util.ServiceConfigurationError; 11 | import java.util.ServiceLoader; 12 | import java.util.jar.JarEntry; 13 | import java.util.jar.JarFile; 14 | 15 | import org.testng.TestNGException; 16 | import org.testng.remote.RemoteTestNG; 17 | import org.testng.shaded.osgi.framework.Version; 18 | 19 | public final class ServiceLoaderHelper { 20 | 21 | private ServiceLoaderHelper() {} 22 | 23 | public static RemoteTestNGFactory getFirst(Version version) { 24 | List factories = new ArrayList<>(); 25 | for (RemoteTestNGFactory factory : ServiceLoader.load(RemoteTestNGFactory.class)) { 26 | if (factory.accept(version)) { 27 | factories.add(factory); 28 | } 29 | } 30 | if (factories.isEmpty()) { 31 | throw new TestNGException(version + " is not a supported TestNG version"); 32 | } 33 | if (factories.size() > 1) { 34 | System.err.println("[ServiceLoaderHelper] More than one working implementation for '" + version + "', we will use the first one"); 35 | } 36 | 37 | Collections.sort(factories, new Comparator() { 38 | @Override 39 | public int compare(RemoteTestNGFactory o1, RemoteTestNGFactory o2) { 40 | // the newest first 41 | return o2.getOrder() - o1.getOrder(); 42 | } 43 | }); 44 | 45 | return factories.get(0); 46 | } 47 | 48 | public static RemoteTestNGFactory getFirstQuietly(String version) { 49 | return getFirstQuietly(Version.parseVersion(version)); 50 | } 51 | 52 | /** 53 | * Get the first RemoteTestNGFactory on classpath. 54 | *

55 | * this implementation is diff with {@link #getFirst(Version)} that 56 | * it scans the JARs on the classpath, and parse the services file manually. 57 | *

58 | * @param version 59 | * @return 60 | * @throws TestNGException if not found 61 | */ 62 | public static RemoteTestNGFactory getFirstQuietly(Version version) { 63 | ClassLoader cl = RemoteTestNGFactory.class.getClassLoader(); 64 | if (cl instanceof URLClassLoader) { 65 | for (URL url : ((URLClassLoader) cl).getURLs()) { 66 | File f = new File(url.getFile()); 67 | // only check for jar file name starts with 'testng-remote' 68 | if (f.isFile() && f.getName().startsWith("testng-remote")) { 69 | try (JarFile jarFile = new JarFile(f)) { 70 | JarEntry entry = jarFile.getJarEntry("META-INF/services/" + RemoteTestNGFactory.class.getName()); 71 | if (entry != null) { 72 | ArrayList names = new ArrayList<>(); 73 | 74 | try (BufferedReader r = new BufferedReader( 75 | new InputStreamReader(jarFile.getInputStream(entry), "utf-8"))) { 76 | int lc = 1; 77 | while ((lc = parseLine(RemoteTestNGFactory.class, url, r, lc, names)) >= 0) { 78 | // noop 79 | } 80 | 81 | for (String name : names) { 82 | Class c = Class.forName(name, false, cl); 83 | RemoteTestNGFactory factory = (RemoteTestNGFactory) c.newInstance(); 84 | if (factory.accept(version)) { 85 | return factory; 86 | } 87 | } 88 | } 89 | } 90 | } catch (TestNGException ex) { 91 | throw ex; 92 | } catch (Exception ex) { 93 | if (RemoteTestNG.isDebug()) { 94 | ex.printStackTrace(); 95 | } 96 | } 97 | } 98 | } 99 | } 100 | 101 | throw new TestNGException(version + " is not a supported TestNG version"); 102 | } 103 | 104 | // Parse a single line from the given configuration file, adding the name 105 | // on the line to the names list. 106 | // 107 | private static int parseLine(Class service, URL u, BufferedReader r, int lc, List names) 108 | throws IOException, ServiceConfigurationError { 109 | String ln = r.readLine(); 110 | if (ln == null) { 111 | return -1; 112 | } 113 | int ci = ln.indexOf('#'); 114 | if (ci >= 0) { 115 | ln = ln.substring(0, ci); 116 | } 117 | ln = ln.trim(); 118 | int n = ln.length(); 119 | if (n != 0) { 120 | if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) { 121 | fail(service, u, lc, "Illegal configuration-file syntax"); 122 | } 123 | int cp = ln.codePointAt(0); 124 | if (!Character.isJavaIdentifierStart(cp)) { 125 | fail(service, u, lc, "Illegal provider-class name: " + ln); 126 | } 127 | for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) { 128 | cp = ln.codePointAt(i); 129 | if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) { 130 | fail(service, u, lc, "Illegal provider-class name: " + ln); 131 | } 132 | } 133 | if (!names.contains(ln)) { 134 | names.add(ln); 135 | } 136 | } 137 | return lc + 1; 138 | } 139 | 140 | private static void fail(Class service, String msg) throws ServiceConfigurationError { 141 | throw new ServiceConfigurationError(service.getName() + ": " + msg); 142 | } 143 | 144 | private static void fail(Class service, URL u, int line, String msg) throws ServiceConfigurationError { 145 | fail(service, u + ":" + line + ": " + msg); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/xml/ResultContentHandler.java: -------------------------------------------------------------------------------- 1 | package org.testng.xml; 2 | 3 | import static org.testng.reporters.XMLReporterConfig.ATTR_DESC; 4 | import static org.testng.reporters.XMLReporterConfig.ATTR_DURATION_MS; 5 | import static org.testng.reporters.XMLReporterConfig.ATTR_NAME; 6 | import static org.testng.reporters.XMLReporterConfig.ATTR_STATUS; 7 | import static org.testng.reporters.XMLReporterConfig.TAG_CLASS; 8 | import static org.testng.reporters.XMLReporterConfig.TAG_PARAMS; 9 | import static org.testng.reporters.XMLReporterConfig.TAG_SUITE; 10 | import static org.testng.reporters.XMLReporterConfig.TAG_TEST; 11 | import static org.testng.reporters.XMLReporterConfig.TAG_TEST_METHOD; 12 | 13 | import java.util.List; 14 | 15 | import org.testng.ITestResult; 16 | import org.testng.collections.Lists; 17 | import org.testng.remote.strprotocol.GenericMessage; 18 | import org.testng.remote.strprotocol.IRemoteSuiteListener; 19 | import org.testng.remote.strprotocol.IRemoteTestListener; 20 | import org.testng.remote.strprotocol.SuiteMessage; 21 | import org.testng.remote.strprotocol.TestMessage; 22 | import org.testng.remote.strprotocol.TestResultMessage; 23 | import org.testng.reporters.XMLReporterConfig; 24 | import org.xml.sax.Attributes; 25 | import org.xml.sax.helpers.DefaultHandler; 26 | 27 | /** 28 | * Parses testng-result.xml, create TestResultMessages and send them back to the listener 29 | * as we encounter them. 30 | * 31 | * @author Cedric Beust 32 | */ 33 | public class ResultContentHandler extends DefaultHandler { 34 | private int m_suiteMethodCount = 0; 35 | private int m_testMethodCount = 0; 36 | private SuiteMessage m_currentSuite; 37 | private TestMessage m_currentTest; 38 | private String m_className; 39 | private int m_passed; 40 | private int m_failed; 41 | private int m_skipped; 42 | private int m_invocationCount; 43 | private int m_currentInvocationCount; 44 | private TestResultMessage m_currentTestResult; 45 | private IRemoteSuiteListener m_suiteListener; 46 | private IRemoteTestListener m_testListener; 47 | private List m_params = null; 48 | 49 | public ResultContentHandler(IRemoteSuiteListener suiteListener, 50 | IRemoteTestListener testListener, boolean resolveClasses /* ignored */) { 51 | m_suiteListener = suiteListener; 52 | m_testListener = testListener; 53 | } 54 | 55 | @Override 56 | public void startElement (String uri, String localName, 57 | String qName, Attributes attributes) { 58 | p("Start " + qName); 59 | if (TAG_SUITE.equals(qName)) { 60 | m_suiteListener.onInitialization(new GenericMessage()); 61 | m_suiteMethodCount = 0; 62 | m_currentSuite = new SuiteMessage(attributes.getValue(ATTR_NAME), 63 | true /* start */, m_suiteMethodCount); 64 | m_suiteListener.onStart(m_currentSuite); 65 | } else if (TAG_TEST.equals(qName)) { 66 | m_passed = m_failed = m_skipped = 0; 67 | m_currentTest = new TestMessage(true /* start */, m_currentSuite.getSuiteName(), 68 | attributes.getValue(ATTR_NAME), m_testMethodCount, 69 | m_passed, m_failed, m_skipped, 0); 70 | m_testListener.onStart(m_currentTest); 71 | } else if (TAG_CLASS.equals(qName)) { 72 | m_className = attributes.getValue(ATTR_NAME); 73 | } else if (TAG_TEST_METHOD.equals(qName)) { 74 | Integer status = XMLReporterConfig.getStatus(attributes.getValue(ATTR_STATUS)); 75 | m_currentTestResult = new TestResultMessage(status, m_currentSuite.getSuiteName(), 76 | m_currentTest.getTestName(), m_className, attributes.getValue(ATTR_NAME), 77 | attributes.getValue(ATTR_DESC), 78 | attributes.getValue(ATTR_DESC), 79 | new String[0], /* no parameters, filled later */ 80 | 0, Long.parseLong(attributes.getValue(ATTR_DURATION_MS)), 81 | "" /* stack trace, filled later */, 82 | m_invocationCount, m_currentInvocationCount); 83 | m_suiteMethodCount++; 84 | m_testMethodCount++; 85 | if (status == ITestResult.SUCCESS) m_passed++; 86 | else if (status == ITestResult.FAILURE) m_failed++; 87 | else if (status == ITestResult.SKIP) m_skipped++; 88 | } else if (TAG_PARAMS.equals(qName)) { 89 | m_params = Lists.newArrayList(); 90 | } 91 | } 92 | 93 | @Override 94 | public void characters(char[] ch, int start, int length) { 95 | if (m_params != null) { 96 | String string = new String(ch, start, length); 97 | String parameter = string; 98 | if (parameter.trim().length() != 0) { 99 | m_params.add(parameter); 100 | } 101 | } 102 | } 103 | 104 | @Override 105 | public void endElement (String uri, String localName, String qName) { 106 | if (TAG_SUITE.equals(qName)) { 107 | m_suiteListener.onFinish(new SuiteMessage(null, false /* end */, m_suiteMethodCount)); 108 | m_currentSuite = null; 109 | } else if (TAG_TEST.equals(qName)) { 110 | m_currentTest = new TestMessage(false /* start */, m_currentSuite.getSuiteName(), 111 | null, m_testMethodCount, 112 | m_passed, m_failed, m_skipped, 0); 113 | m_testMethodCount = 0; 114 | m_testListener.onFinish(m_currentTest); 115 | } else if (TAG_CLASS.equals(qName)) { 116 | m_className = null; 117 | } else if (TAG_TEST_METHOD.equals(qName)) { 118 | switch(m_currentTestResult.getResult()) { 119 | case ITestResult.SUCCESS: 120 | m_testListener.onTestSuccess(m_currentTestResult); 121 | break; 122 | case ITestResult.FAILURE: 123 | m_testListener.onTestFailure(m_currentTestResult); 124 | break; 125 | case ITestResult.SKIP: 126 | m_testListener.onTestSkipped(m_currentTestResult); 127 | break; 128 | default: 129 | p("Ignoring test status:" + m_currentTestResult.getResult()); 130 | } 131 | } 132 | else if (TAG_PARAMS.equals(qName)) { 133 | String[] params = new String[m_params.size()]; 134 | for (int i = 0; i < m_params.size(); i++) { 135 | // The parameters are encoded as type:value. Since we only care about the 136 | // value (and we don't receive the type anyway), use a dummy character in 137 | // its place 138 | params[i] = "@:" + m_params.get(i); 139 | } 140 | m_currentTestResult.setParameters(params); 141 | m_params = null; 142 | } 143 | } 144 | 145 | private static void p(String string) { 146 | if (false) { 147 | System.out.println("[ResultContentHandler] " + string); 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /remote/src/main/java/org/testng/xml/ResultXMLParser.java: -------------------------------------------------------------------------------- 1 | package org.testng.xml; 2 | 3 | import java.io.InputStream; 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.Method; 6 | 7 | import org.testng.TestNGException; 8 | import org.testng.remote.strprotocol.IRemoteSuiteListener; 9 | import org.testng.remote.strprotocol.IRemoteTestListener; 10 | import org.xml.sax.helpers.DefaultHandler; 11 | 12 | /** 13 | * Parses testng-result.xml. 14 | * 15 | * @see ResultContentHandler 16 | * 17 | * @author Cedric Beust 18 | */ 19 | public class ResultXMLParser extends XMLParser { 20 | private IRemoteTestListener m_testListener; 21 | private IRemoteSuiteListener m_suiteListener; 22 | 23 | public ResultXMLParser(IRemoteSuiteListener suiteListener, IRemoteTestListener testListener) { 24 | m_suiteListener = suiteListener; 25 | m_testListener = testListener; 26 | } 27 | 28 | public void parse() { 29 | } 30 | 31 | @Override 32 | public Object parse(String currentFile, InputStream inputStream, boolean loadClasses) { 33 | ResultContentHandler handler = new ResultContentHandler(m_suiteListener, m_testListener, 34 | loadClasses); 35 | 36 | try { 37 | boolean invoked = false; 38 | try { 39 | // try with testng >= 6.8.11 40 | invoked = invokeParseWithReflection(this, inputStream, handler); 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | } 44 | if (!invoked) { 45 | // otherwise, try with testng < 6.8.11 46 | Field parserField = ResultXMLParser.class.getDeclaredField("m_saxParser"); 47 | parserField.setAccessible(true); 48 | Object parser = parserField.get(this); 49 | invokeParseWithReflection(parser, inputStream, handler); 50 | } 51 | 52 | return null; 53 | } catch (Exception e) { 54 | throw new TestNGException(e); 55 | } 56 | } 57 | 58 | private boolean invokeParseWithReflection(Object obj, InputStream inputStream, DefaultHandler handler) throws Exception { 59 | Method parseMethod = obj.getClass().getMethod("parse", InputStream.class, DefaultHandler.class); 60 | if (parseMethod != null) { 61 | parseMethod.invoke(this, inputStream, handler); 62 | return true; 63 | } 64 | return false; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /remote/src/main/resources/revision.properties: -------------------------------------------------------------------------------- 1 | git.branch=${git.branch} 2 | git.commit.id=${git.commit.id.abbrev} 3 | git.build.version=${git.build.version} 4 | -------------------------------------------------------------------------------- /remote/src/test/java/org/testng/remote/strprotocol/JsonMessageTest.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import static org.testng.Assert.assertEquals; 4 | import static org.testng.Assert.assertTrue; 5 | 6 | import java.io.StringWriter; 7 | 8 | import org.testng.annotations.Test; 9 | 10 | import com.google.gson.Gson; 11 | import com.google.gson.GsonBuilder; 12 | import com.google.gson.stream.JsonWriter; 13 | 14 | public class JsonMessageTest { 15 | 16 | @Test 17 | public void jsonGenericMessage() throws Exception { 18 | Gson gson = new GsonBuilder().create(); 19 | GenericMessage genMsg = new GenericMessage(); 20 | genMsg.setSuiteCount(2); 21 | genMsg.setTestCount(3); 22 | 23 | String jsonStrSuiteMsg = gson.toJson(genMsg); 24 | System.out.println("unmarshall to json: "); 25 | System.out.println(jsonStrSuiteMsg); 26 | 27 | GenericMessage genMsg2 = gson.fromJson(jsonStrSuiteMsg, GenericMessage.class); 28 | System.out.println("marshall to object: "); 29 | System.out.println(genMsg2); 30 | assertEquals(genMsg2.getType(), MessageType.GENERIC); 31 | } 32 | 33 | @Test 34 | public void jsonSuiteMessage() throws Exception { 35 | Gson gson = new GsonBuilder().create(); 36 | SuiteMessage suiteMsg = new SuiteMessage("testSuite", true, 0); 37 | 38 | String jsonStrSuiteMsg = gson.toJson(suiteMsg); 39 | System.out.println("unmarshall to json: "); 40 | System.out.println(jsonStrSuiteMsg); 41 | 42 | SuiteMessage suiteMsg2 = gson.fromJson(jsonStrSuiteMsg, SuiteMessage.class); 43 | System.out.println("marshall to object: "); 44 | System.out.println(suiteMsg2); 45 | assertEquals(suiteMsg2.getType(), MessageType.SUITE); 46 | } 47 | 48 | @Test 49 | public void jsonMessageStream() throws Exception { 50 | // dummy constructor parameters since the UT only verify message 51 | // marshalling/unmarshalling 52 | JsonMessageSender ms = new JsonMessageSender("localhost", -1); 53 | 54 | GenericMessage genMsg = new GenericMessage(); 55 | genMsg.setSuiteCount(2); 56 | genMsg.setTestCount(3); 57 | StringWriter sWriter = new StringWriter(); 58 | JsonWriter writer = new JsonWriter(sWriter); 59 | ms.writeMessage(writer, genMsg); 60 | String jsonMsg = sWriter.toString(); 61 | System.out.println("unmarshall to json: "); 62 | System.out.println(jsonMsg); 63 | 64 | IMessage message = ms.deserializeMessage(jsonMsg); 65 | assertTrue(message instanceof GenericMessage); 66 | assertEquals(message.getType(), MessageType.GENERIC); 67 | System.out.println("marshall to object: "); 68 | System.out.println(message); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /remote/src/test/java/org/testng/remote/strprotocol/TestResultMessageTest.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.strprotocol; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import org.testng.Assert; 7 | import org.testng.annotations.DataProvider; 8 | import org.testng.annotations.Test; 9 | 10 | public class TestResultMessageTest { 11 | 12 | private TestResultMessage testResultMessage = new TestResultMessage(0, 13 | "suiteName", "testName", "className", "methodName", 14 | "testDescriptor", "testinstanceName", new String[] {}, 0, 0, 15 | "stackTrace", 1, 0); 16 | 17 | @DataProvider(name = "testGen") 18 | private Object[][] getP() { 19 | return new Object[][] { 20 | { null, new Class[] { null }, Arrays.asList() }, 21 | { new Object[] { new byte[] { 1 } }, 22 | new Class[] { byte[].class }, Arrays.asList("[1]") }, 23 | { new Object[] { new short[] { 1 } }, 24 | new Class[] { short[].class }, Arrays.asList("[1]") }, 25 | { new Object[] { new long[] { 1 } }, 26 | new Class[] { long[].class }, Arrays.asList("[1]") }, 27 | { new Object[] { new int[] { 1, 2, 3 } }, 28 | new Class[] { int[].class }, Arrays.asList("[1,2,3]") }, 29 | { new Object[] { new boolean[] { true, false } }, 30 | new Class[] { boolean[].class }, 31 | Arrays.asList("[true,false]") }, 32 | { new Object[] { new char[] { 'a', 'b', 'c' } }, 33 | new Class[] { int[].class }, Arrays.asList("[a,b,c]") }, 34 | { new Object[] { new float[] { 1.1f, 2.2f, 3.3f } }, 35 | new Class[] { float[].class }, 36 | Arrays.asList("[1.1,2.2,3.3]") }, 37 | { new Object[] { new double[] { 1.1, 2.2, 3.3 } }, 38 | new Class[] { double[].class }, 39 | Arrays.asList("[1.1,2.2,3.3]") }, 40 | { new Object[] { new Object[] { "this is a string", false } }, 41 | new Class[] { String.class, Boolean.class }, 42 | Arrays.asList("[this is a string,false]") }, 43 | { new Object[] { new Object[] { null, "" } }, 44 | new Class[] { String.class, Boolean.class }, 45 | Arrays.asList("[null,\"\"]") }, }; 46 | } 47 | 48 | @Test(dataProvider = "testGen") 49 | public void toStringTest(Object[] objects, Class[] objectClasses, 50 | List expectedResults) throws Exception { 51 | String[] results = testResultMessage.toString(objects, objectClasses); 52 | Assert.assertEquals(Arrays.asList(results), expectedResults); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /remote/src/test/java/test/SimpleBaseTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import org.testng.Assert; 4 | import org.testng.ITestResult; 5 | import org.testng.TestListenerAdapter; 6 | import org.testng.TestNG; 7 | import org.testng.collections.Lists; 8 | import org.testng.xml.XmlClass; 9 | import org.testng.xml.XmlInclude; 10 | import org.testng.xml.XmlSuite; 11 | import org.testng.xml.XmlTest; 12 | 13 | import java.io.File; 14 | import java.util.Arrays; 15 | import java.util.Iterator; 16 | import java.util.List; 17 | 18 | public class SimpleBaseTest { 19 | // System property specifying where the resources (e.g. xml files) can be found 20 | private static final String TEST_RESOURCES_DIR = "test.resources.dir"; 21 | 22 | public static TestNG create() { 23 | TestNG result = new TestNG(); 24 | result.setUseDefaultListeners(false); 25 | result.setVerbose(0); 26 | return result; 27 | } 28 | 29 | public static TestNG create(Class... testClasses) { 30 | TestNG result = create(); 31 | result.setTestClasses(testClasses); 32 | return result; 33 | } 34 | 35 | protected TestNG create(XmlSuite... suites) { 36 | TestNG result = create(); 37 | result.setXmlSuites(Arrays.asList(suites)); 38 | return result; 39 | } 40 | 41 | protected TestNG createTests(String suiteName, Class... testClasses) { 42 | XmlSuite suite = createXmlSuite(suiteName); 43 | int i=0; 44 | for (Class testClass : testClasses) { 45 | createXmlTest(suite, testClass.getName() + i, testClass); 46 | i++; 47 | } 48 | return create(suite); 49 | } 50 | 51 | protected XmlSuite createXmlSuite(String name) { 52 | XmlSuite result = new XmlSuite(); 53 | result.setName(name); 54 | return result; 55 | } 56 | 57 | protected XmlTest createXmlTest(XmlSuite suite, String name, Class clazz, Class... classes) { 58 | XmlTest result = new XmlTest(suite); 59 | int index = 0; 60 | result.setName(name); 61 | XmlClass xc = new XmlClass(clazz.getName(), index++, true /* load classes */); 62 | result.getXmlClasses().add(xc); 63 | for (Class c : classes) { 64 | xc = new XmlClass(c.getName(), index++, true /* load classes */); 65 | result.getXmlClasses().add(xc); 66 | } 67 | 68 | return result; 69 | } 70 | 71 | protected XmlTest createXmlTest(XmlSuite suite, String name, String... classes) { 72 | XmlTest result = new XmlTest(suite); 73 | int index = 0; 74 | result.setName(name); 75 | for (String c : classes) { 76 | XmlClass xc = new XmlClass(c, index++, true /* load classes */); 77 | result.getXmlClasses().add(xc); 78 | } 79 | 80 | return result; 81 | } 82 | 83 | protected void addMethods(XmlClass cls, String... methods) { 84 | int index = 0; 85 | for (String m : methods) { 86 | XmlInclude include = new XmlInclude(m, index++); 87 | cls.getIncludedMethods().add(include); 88 | } 89 | } 90 | 91 | public static String getPathToResource(String fileName) { 92 | String result = System.getProperty(TEST_RESOURCES_DIR); 93 | if (result == null) { 94 | throw new IllegalArgumentException("System property " + TEST_RESOURCES_DIR + " was not defined."); 95 | } 96 | return result + File.separatorChar + fileName; 97 | } 98 | 99 | protected void verifyPassedTests(TestListenerAdapter tla, String... methodNames) { 100 | Iterator it = tla.getPassedTests().iterator(); 101 | Assert.assertEquals(tla.getPassedTests().size(), methodNames.length); 102 | 103 | int i = 0; 104 | while (it.hasNext()) { 105 | Assert.assertEquals(it.next().getName(), methodNames[i++]); 106 | } 107 | } 108 | 109 | /** 110 | * Compare a list of ITestResult with a list of String method names, 111 | */ 112 | public static void assertTestResultsEqual(List results, List methods) { 113 | List resultMethods = Lists.newArrayList(); 114 | for (ITestResult r : results) { 115 | resultMethods.add(r.getMethod().getMethodName()); 116 | } 117 | Assert.assertEquals(resultMethods, methods); 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /remote/src/test/java/test/remote/RemoteSampleTest.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | /** 6 | * Used by RemoteTest to test RemoteTestNG. 7 | * 8 | * @author Cedric Beust 9 | * 10 | */ 11 | public class RemoteSampleTest { 12 | 13 | @Test 14 | public void f1() {} 15 | 16 | @Test 17 | public void f2() {} 18 | } 19 | -------------------------------------------------------------------------------- /remote/src/test/java/test/remote/RemoteTest.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | import org.testng.Assert; 4 | import org.testng.annotations.Test; 5 | import org.testng.collections.Lists; 6 | import org.testng.remote.RemoteArgs; 7 | import org.testng.remote.RemoteTestNG; 8 | import org.testng.remote.strprotocol.IMessage; 9 | import org.testng.remote.strprotocol.IMessageSender; 10 | import org.testng.remote.strprotocol.JsonMessageSender; 11 | import org.testng.remote.strprotocol.MessageHub; 12 | import org.testng.remote.strprotocol.SerializedMessageSender; 13 | import org.testng.remote.strprotocol.StringMessageSender; 14 | 15 | import test.SimpleBaseTest; 16 | 17 | import java.net.SocketTimeoutException; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | /** 22 | * A simple client that launches RemoteTestNG and then talks to it via the 23 | * two supported protocols, String and Serialized. 24 | * 25 | * @author Cedric Beust 26 | */ 27 | public abstract class RemoteTest extends SimpleBaseTest { 28 | 29 | private static final boolean DEBUG = true; 30 | 31 | protected abstract String getTestNGVersion(); 32 | 33 | // Note: don't use the ports used by the plug-in or the RemoteTestNG processes 34 | // launched in this test will interfere with the plug-in. 35 | private static final int PORT1 = 1243; 36 | private static final int PORT2 = 1242; 37 | private static final int PORT3 = 1244; 38 | private static final List EXPECTED_MESSAGES = new ArrayList() {{ 39 | add("GenericMessage"); // method and test counts 40 | add("SuiteMessage"); // suite started 41 | add("TestMessage"); // test started 42 | add("TestResultMessage"); // status: started 43 | add("TestResultMessage"); // status: success 44 | add("TestResultMessage"); // status: started 45 | add("TestResultMessage"); // status: success 46 | add("TestMessage"); // test finished 47 | add("SuiteMessage"); // suite finished 48 | }}; 49 | 50 | @Test 51 | public void testSerialized() { 52 | runTest("-serport", PORT1, new SerializedMessageSender("localhost", PORT1)); 53 | } 54 | 55 | @Test 56 | public void testJson() { 57 | runTest("-serport", PORT3, new JsonMessageSender("localhost", PORT3)); 58 | } 59 | 60 | @Test 61 | public void testString() { 62 | runTest("-port", PORT2, new StringMessageSender("localhost", PORT2)); 63 | } 64 | 65 | private void launchRemoteTestNG(final String portArg, final int portValue, final String protocol) { 66 | new Thread(() -> { 67 | List args = new ArrayList<>(); 68 | args.add(portArg); 69 | args.add(Integer.toString(portValue)); 70 | args.add(RemoteArgs.VERSION); 71 | args.add(getTestNGVersion()); 72 | if (protocol != null) { 73 | args.add(RemoteArgs.PROTOCOL); 74 | args.add(protocol); 75 | } 76 | args.add("-dontexit"); 77 | args.add(getPathToResource("testng-remote.xml")); 78 | RemoteTestNG.main(args.toArray(new String[0])); 79 | }).start(); 80 | } 81 | 82 | private void runTest(String arg, int portValue, IMessageSender sms) { 83 | p("Launching RemoteTestNG on port " + portValue); 84 | String protocol = null; 85 | if (sms instanceof JsonMessageSender) { 86 | protocol = "json"; 87 | } 88 | launchRemoteTestNG(arg, portValue, protocol); 89 | MessageHub mh = new MessageHub(sms); 90 | List received = Lists.newArrayList(); 91 | try { 92 | mh.initReceiver(); 93 | IMessage message = mh.receiveMessage(); 94 | while (message != null) { 95 | received.add(message.getClass().getSimpleName()); 96 | message = mh.receiveMessage(); 97 | } 98 | 99 | Assert.assertEquals(received, EXPECTED_MESSAGES); 100 | } 101 | catch(SocketTimeoutException ex) { 102 | Assert.fail("Time out"); 103 | } 104 | } 105 | 106 | private static void p(String s) { 107 | if (DEBUG) { 108 | System.out.println("[RemoteTest] " + s); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /remote/src/test/resources/testng-remote.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /remote/src/test/resources/testng.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /remote6_0/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote6_0 11 | TestNG Remote for version [6.0, 6.5.1) 12 | 13 | 14 | 6.0 15 | 16 | 17 | 18 | 19 | org.testng.testng-remote 20 | testng-remote 21 | 22 | 23 | org.testng 24 | testng 25 | ${testng.version} 26 | provided 27 | 28 | 29 | com.google.auto.service 30 | auto-service 31 | true 32 | 33 | 34 | org.testng.testng-remote 35 | testng-remote 36 | test-jar 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 46 | 47 | ${basedir}/../remote/target/test-classes 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /remote6_0/src/main/java/org/testng/remote/support/RemoteTestNG6_0.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import java.util.List; 4 | 5 | import org.testng.IInvokedMethodListener; 6 | import org.testng.ISuite; 7 | import org.testng.ITestRunnerFactory; 8 | import org.testng.TestRunner; 9 | import org.testng.remote.AbstractRemoteTestNG; 10 | import org.testng.remote.strprotocol.MessageHub; 11 | import org.testng.remote.strprotocol.RemoteTestListener1; 12 | import org.testng.reporters.JUnitXMLReporter; 13 | import org.testng.reporters.TestHTMLReporter; 14 | import org.testng.xml.XmlTest; 15 | 16 | public class RemoteTestNG6_0 extends AbstractRemoteTestNG { 17 | 18 | @Override 19 | protected ITestRunnerFactory buildTestRunnerFactory() { 20 | if(null == m_customTestRunnerFactory) { 21 | m_customTestRunnerFactory= new ITestRunnerFactory() { 22 | @Override 23 | public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, 24 | List listeners) { 25 | TestRunner runner = 26 | new TestRunner(getConfiguration(), suite, xmlTest, 27 | false /*skipFailedInvocationCounts */, 28 | listeners); 29 | if (m_useDefaultListeners) { 30 | runner.addListener(new TestHTMLReporter()); 31 | runner.addListener(new JUnitXMLReporter()); 32 | } 33 | 34 | return runner; 35 | } 36 | }; 37 | } 38 | 39 | return m_customTestRunnerFactory; 40 | } 41 | 42 | @Override 43 | protected ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 44 | return new DelegatingTestRunnerFactory(trf, smsh); 45 | } 46 | 47 | private static class DelegatingTestRunnerFactory implements ITestRunnerFactory { 48 | private final ITestRunnerFactory m_delegateFactory; 49 | private final MessageHub m_messageSender; 50 | 51 | DelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 52 | m_delegateFactory= trf; 53 | m_messageSender= smsh; 54 | } 55 | 56 | @Override 57 | public TestRunner newTestRunner(ISuite suite, XmlTest test, 58 | List listeners) { 59 | TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners); 60 | tr.addListener(new RemoteTestListener1(suite, test, m_messageSender)); 61 | return tr; 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /remote6_0/src/main/java/org/testng/remote/support/RemoteTestNGFactory6_0.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.remote.AbstractRemoteTestNGFactory; 4 | import org.testng.remote.IRemoteTestNG; 5 | import org.testng.shaded.osgi.framework.VersionRange; 6 | 7 | import com.google.auto.service.AutoService; 8 | 9 | @AutoService(RemoteTestNGFactory.class) 10 | public class RemoteTestNGFactory6_0 extends AbstractRemoteTestNGFactory { 11 | 12 | private static final VersionRange RANGE = new VersionRange("[6.0,6.5.1)"); 13 | 14 | @Override 15 | public IRemoteTestNG createRemoteTestNG() { 16 | return new RemoteTestNG6_0(); 17 | } 18 | 19 | @Override 20 | protected VersionRange getAcceptableVersions() { 21 | return RANGE; 22 | } 23 | 24 | @Override 25 | public int getOrder() { 26 | return 1; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /remote6_0/src/test/java/test/remote/Remote6_0_Test.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | public class Remote6_0_Test extends RemoteTest { 4 | 5 | @Override 6 | protected String getTestNGVersion() { 7 | return "6.0"; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /remote6_10/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote6_10 11 | TestNG Remote for version [6.10, 6.12) 12 | 13 | 14 | 6.10 15 | 16 | 17 | 18 | 19 | org.testng.testng-remote 20 | testng-remote 21 | 22 | 23 | org.testng 24 | testng 25 | ${testng.version} 26 | provided 27 | 28 | 29 | com.google.auto.service 30 | auto-service 31 | true 32 | 33 | 34 | org.testng.testng-remote 35 | testng-remote 36 | test-jar 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 46 | 47 | ${basedir}/../remote/target/test-classes 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /remote6_10/src/main/java/org/testng/remote/support/RemoteTestNG6_10.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.IClassListener; 4 | import org.testng.IInvokedMethodListener; 5 | import org.testng.ISuite; 6 | import org.testng.ITestRunnerFactory; 7 | import org.testng.TestRunner; 8 | import org.testng.remote.AbstractRemoteTestNG; 9 | import org.testng.remote.strprotocol.MessageHub; 10 | import org.testng.remote.strprotocol.RemoteTestListener; 11 | import org.testng.reporters.JUnitXMLReporter; 12 | import org.testng.reporters.TestHTMLReporter; 13 | import org.testng.xml.XmlTest; 14 | 15 | import java.util.Collection; 16 | import java.util.List; 17 | 18 | public class RemoteTestNG6_10 extends AbstractRemoteTestNG { 19 | 20 | @Override 21 | protected ITestRunnerFactory buildTestRunnerFactory() { 22 | if(null == m_customTestRunnerFactory) { 23 | m_customTestRunnerFactory= new ITestRunnerFactory() { 24 | @Override 25 | public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, 26 | Collection listeners, List classListeners) { 27 | TestRunner runner = 28 | new TestRunner(getConfiguration(), suite, xmlTest, 29 | false /*skipFailedInvocationCounts */, 30 | listeners, classListeners); 31 | if (m_useDefaultListeners) { 32 | runner.addListener(new TestHTMLReporter()); 33 | runner.addListener(new JUnitXMLReporter()); 34 | } 35 | 36 | return runner; 37 | } 38 | }; 39 | } 40 | 41 | return m_customTestRunnerFactory; 42 | } 43 | 44 | @Override 45 | protected ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 46 | return new DelegatingTestRunnerFactory(trf, smsh); 47 | } 48 | 49 | private static class DelegatingTestRunnerFactory implements ITestRunnerFactory { 50 | private final ITestRunnerFactory m_delegateFactory; 51 | private final MessageHub m_messageSender; 52 | 53 | DelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 54 | m_delegateFactory= trf; 55 | m_messageSender= smsh; 56 | } 57 | 58 | @Override 59 | public TestRunner newTestRunner(ISuite suite, XmlTest test, 60 | Collection listeners, List classListeners) { 61 | TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners, classListeners); 62 | tr.addListener(new RemoteTestListener(suite, test, m_messageSender)); 63 | return tr; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /remote6_10/src/main/java/org/testng/remote/support/RemoteTestNGFactory6_10.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.remote.AbstractRemoteTestNGFactory; 4 | import org.testng.remote.IRemoteTestNG; 5 | import org.testng.shaded.osgi.framework.VersionRange; 6 | 7 | import com.google.auto.service.AutoService; 8 | 9 | @AutoService(RemoteTestNGFactory.class) 10 | public class RemoteTestNGFactory6_10 extends AbstractRemoteTestNGFactory { 11 | 12 | private static final VersionRange RANGE = new VersionRange("[6.10,6.12)"); 13 | 14 | @Override 15 | public IRemoteTestNG createRemoteTestNG() { 16 | return new RemoteTestNG6_10(); 17 | } 18 | 19 | @Override 20 | protected VersionRange getAcceptableVersions() { 21 | return RANGE; 22 | } 23 | 24 | @Override 25 | public int getOrder() { 26 | return 5; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /remote6_10/src/test/java/test/remote/Remote6_10_Test.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | import org.testng.internal.Version; 4 | 5 | public class Remote6_10_Test extends RemoteTest { 6 | 7 | @Override 8 | protected String getTestNGVersion() { 9 | return Version.VERSION; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /remote6_12/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote6_12 11 | TestNG Remote for version [6.12, 7.8) 12 | 13 | 14 | 6.13.1 15 | 16 | 17 | 18 | 19 | org.testng.testng-remote 20 | testng-remote 21 | 22 | 23 | org.testng 24 | testng 25 | ${testng.version} 26 | provided 27 | 28 | 29 | com.google.auto.service 30 | auto-service 31 | true 32 | 33 | 34 | org.testng.testng-remote 35 | testng-remote 36 | test-jar 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 46 | 47 | ${basedir}/../remote/target/test-classes 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /remote6_12/src/main/java/org/testng/remote/support/RemoteTestNG6_12.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.IClassListener; 4 | import org.testng.IInvokedMethodListener; 5 | import org.testng.ISuite; 6 | import org.testng.ITestRunnerFactory; 7 | import org.testng.TestRunner; 8 | import org.testng.remote.AbstractRemoteTestNG; 9 | import org.testng.remote.strprotocol.MessageHub; 10 | import org.testng.remote.strprotocol.RemoteTestListener; 11 | import org.testng.reporters.JUnitXMLReporter; 12 | import org.testng.reporters.TestHTMLReporter; 13 | import org.testng.xml.XmlTest; 14 | 15 | import java.util.Collection; 16 | import java.util.List; 17 | 18 | public class RemoteTestNG6_12 extends AbstractRemoteTestNG { 19 | 20 | @Override 21 | protected void initialize() { 22 | initializeEverything(); 23 | } 24 | 25 | @Override 26 | protected ITestRunnerFactory buildTestRunnerFactory() { 27 | if(null == m_customTestRunnerFactory) { 28 | m_customTestRunnerFactory= new ITestRunnerFactory() { 29 | @Override 30 | public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, 31 | Collection listeners, List classListeners) { 32 | TestRunner runner = 33 | new TestRunner(getConfiguration(), suite, xmlTest, 34 | false /*skipFailedInvocationCounts */, 35 | listeners, classListeners); 36 | if (m_useDefaultListeners) { 37 | runner.addListener(new TestHTMLReporter()); 38 | runner.addListener(new JUnitXMLReporter()); 39 | } 40 | 41 | return runner; 42 | } 43 | }; 44 | } 45 | 46 | return m_customTestRunnerFactory; 47 | } 48 | 49 | @Override 50 | protected ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 51 | return new DelegatingTestRunnerFactory(trf, smsh); 52 | } 53 | 54 | private static class DelegatingTestRunnerFactory implements ITestRunnerFactory { 55 | private final ITestRunnerFactory m_delegateFactory; 56 | private final MessageHub m_messageSender; 57 | 58 | DelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 59 | m_delegateFactory= trf; 60 | m_messageSender= smsh; 61 | } 62 | 63 | @Override 64 | public TestRunner newTestRunner(ISuite suite, XmlTest test, 65 | Collection listeners, List classListeners) { 66 | TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners, classListeners); 67 | tr.addListener(new RemoteTestListener(suite, test, m_messageSender)); 68 | return tr; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /remote6_12/src/main/java/org/testng/remote/support/RemoteTestNGFactory6_12.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.remote.AbstractRemoteTestNGFactory; 4 | import org.testng.remote.IRemoteTestNG; 5 | import org.testng.shaded.osgi.framework.VersionRange; 6 | 7 | import com.google.auto.service.AutoService; 8 | 9 | @AutoService(RemoteTestNGFactory.class) 10 | public class RemoteTestNGFactory6_12 extends AbstractRemoteTestNGFactory { 11 | 12 | private static final VersionRange RANGE = new VersionRange("[6.12,7.8)"); 13 | 14 | @Override 15 | public IRemoteTestNG createRemoteTestNG() { 16 | return new RemoteTestNG6_12(); 17 | } 18 | 19 | @Override 20 | protected VersionRange getAcceptableVersions() { 21 | return RANGE; 22 | } 23 | 24 | @Override 25 | public int getOrder() { 26 | return 6; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /remote6_12/src/test/java/test/remote/Remote6_12_Test.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | import org.testng.internal.Version; 4 | 5 | public class Remote6_12_Test extends RemoteTest { 6 | 7 | @Override 8 | protected String getTestNGVersion() { 9 | return Version.VERSION; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /remote6_5/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote6_5 11 | TestNG Remote for version [6.5.1, 6.9.7) 12 | 13 | 14 | 6.5.1 15 | 16 | 17 | 18 | 19 | org.testng.testng-remote 20 | testng-remote 21 | 22 | 23 | org.testng 24 | testng 25 | ${testng.version} 26 | provided 27 | 28 | 29 | com.google.auto.service 30 | auto-service 31 | true 32 | 33 | 34 | org.testng.testng-remote 35 | testng-remote 36 | test-jar 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 46 | 47 | ${basedir}/../remote/target/test-classes 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /remote6_5/src/main/java/org/testng/remote/support/RemoteTestNG6_5.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import java.util.List; 4 | 5 | import org.testng.IConfigurationListener; 6 | import org.testng.IInvokedMethodListener; 7 | import org.testng.ISuite; 8 | import org.testng.ITestRunnerFactory; 9 | import org.testng.TestRunner; 10 | import org.testng.remote.AbstractRemoteTestNG; 11 | import org.testng.remote.strprotocol.MessageHub; 12 | import org.testng.remote.strprotocol.RemoteTestListener; 13 | import org.testng.reporters.JUnitXMLReporter; 14 | import org.testng.reporters.TestHTMLReporter; 15 | import org.testng.xml.XmlTest; 16 | 17 | public class RemoteTestNG6_5 extends AbstractRemoteTestNG { 18 | 19 | @Override 20 | protected ITestRunnerFactory buildTestRunnerFactory() { 21 | if(null == m_customTestRunnerFactory) { 22 | m_customTestRunnerFactory= new ITestRunnerFactory() { 23 | @Override 24 | public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, 25 | List listeners) { 26 | TestRunner runner = 27 | new TestRunner(getConfiguration(), suite, xmlTest, 28 | false /*skipFailedInvocationCounts */, 29 | listeners); 30 | if (m_useDefaultListeners) { 31 | runner.addListener(new TestHTMLReporter()); 32 | runner.addListener(new JUnitXMLReporter()); 33 | } 34 | for (IConfigurationListener cl : getConfiguration().getConfigurationListeners()) { 35 | runner.addListener(cl); 36 | } 37 | 38 | return runner; 39 | } 40 | }; 41 | } 42 | 43 | return m_customTestRunnerFactory; 44 | } 45 | 46 | @Override 47 | protected ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 48 | return new DelegatingTestRunnerFactory(trf, smsh); 49 | } 50 | 51 | private static class DelegatingTestRunnerFactory implements ITestRunnerFactory { 52 | private final ITestRunnerFactory m_delegateFactory; 53 | private final MessageHub m_messageSender; 54 | 55 | DelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 56 | m_delegateFactory= trf; 57 | m_messageSender= smsh; 58 | } 59 | 60 | @Override 61 | public TestRunner newTestRunner(ISuite suite, XmlTest test, 62 | List listeners) { 63 | TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners); 64 | tr.addListener(new RemoteTestListener(suite, test, m_messageSender)); 65 | return tr; 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /remote6_5/src/main/java/org/testng/remote/support/RemoteTestNGFactory6_5.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.remote.AbstractRemoteTestNGFactory; 4 | import org.testng.remote.IRemoteTestNG; 5 | import org.testng.shaded.osgi.framework.VersionRange; 6 | 7 | import com.google.auto.service.AutoService; 8 | 9 | @AutoService(RemoteTestNGFactory.class) 10 | public class RemoteTestNGFactory6_5 extends AbstractRemoteTestNGFactory { 11 | 12 | private static final VersionRange RANGE = new VersionRange("[6.5.1,6.9.7)"); 13 | 14 | @Override 15 | public IRemoteTestNG createRemoteTestNG() { 16 | return new RemoteTestNG6_5(); 17 | } 18 | 19 | @Override 20 | protected VersionRange getAcceptableVersions() { 21 | return RANGE; 22 | } 23 | 24 | @Override 25 | public int getOrder() { 26 | return 2; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /remote6_5/src/test/java/test/remote/Remote6_5_Test.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | public class Remote6_5_Test extends RemoteTest { 4 | 5 | @Override 6 | protected String getTestNGVersion() { 7 | return "6.5.1"; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /remote6_9_10/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote6_9_10 11 | TestNG Remote for version [6.9.10, 6.10) 12 | 13 | 14 | 6.9.10 15 | 16 | 17 | 18 | 19 | org.testng.testng-remote 20 | testng-remote 21 | 22 | 23 | org.testng 24 | testng 25 | ${testng.version} 26 | provided 27 | 28 | 29 | com.google.auto.service 30 | auto-service 31 | true 32 | 33 | 34 | org.testng.testng-remote 35 | testng-remote 36 | test-jar 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 46 | 47 | ${basedir}/../remote/target/test-classes 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /remote6_9_10/src/main/java/org/testng/remote/support/RemoteTestNG6_9_10.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.IClassListener; 4 | import org.testng.IConfigurationListener; 5 | import org.testng.IInvokedMethodListener; 6 | import org.testng.ISuite; 7 | import org.testng.ITestRunnerFactory; 8 | import org.testng.TestRunner; 9 | import org.testng.remote.AbstractRemoteTestNG; 10 | import org.testng.remote.strprotocol.MessageHub; 11 | import org.testng.remote.strprotocol.RemoteTestListener; 12 | import org.testng.reporters.JUnitXMLReporter; 13 | import org.testng.reporters.TestHTMLReporter; 14 | import org.testng.xml.XmlTest; 15 | 16 | import java.util.Collection; 17 | import java.util.List; 18 | 19 | public class RemoteTestNG6_9_10 extends AbstractRemoteTestNG { 20 | 21 | @Override 22 | protected ITestRunnerFactory buildTestRunnerFactory() { 23 | if(null == m_customTestRunnerFactory) { 24 | m_customTestRunnerFactory= new ITestRunnerFactory() { 25 | @Override 26 | public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, 27 | Collection listeners, List classListeners) { 28 | TestRunner runner = 29 | new TestRunner(getConfiguration(), suite, xmlTest, 30 | false /*skipFailedInvocationCounts */, 31 | listeners, classListeners); 32 | if (m_useDefaultListeners) { 33 | runner.addListener(new TestHTMLReporter()); 34 | runner.addListener(new JUnitXMLReporter()); 35 | } 36 | for (IConfigurationListener cl : getConfiguration().getConfigurationListeners()) { 37 | runner.addListener(cl); 38 | } 39 | 40 | return runner; 41 | } 42 | }; 43 | } 44 | 45 | return m_customTestRunnerFactory; 46 | } 47 | 48 | @Override 49 | protected ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 50 | return new DelegatingTestRunnerFactory(trf, smsh); 51 | } 52 | 53 | private static class DelegatingTestRunnerFactory implements ITestRunnerFactory { 54 | private final ITestRunnerFactory m_delegateFactory; 55 | private final MessageHub m_messageSender; 56 | 57 | DelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 58 | m_delegateFactory= trf; 59 | m_messageSender= smsh; 60 | } 61 | 62 | @Override 63 | public TestRunner newTestRunner(ISuite suite, XmlTest test, 64 | Collection listeners, List classListeners) { 65 | TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners, classListeners); 66 | tr.addListener(new RemoteTestListener(suite, test, m_messageSender)); 67 | return tr; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /remote6_9_10/src/main/java/org/testng/remote/support/RemoteTestNGFactory6_9_10.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.remote.AbstractRemoteTestNGFactory; 4 | import org.testng.remote.IRemoteTestNG; 5 | import org.testng.shaded.osgi.framework.VersionRange; 6 | 7 | import com.google.auto.service.AutoService; 8 | 9 | @AutoService(RemoteTestNGFactory.class) 10 | public class RemoteTestNGFactory6_9_10 extends AbstractRemoteTestNGFactory { 11 | 12 | private static final VersionRange RANGE = new VersionRange("[6.9.10,6.10)"); 13 | 14 | @Override 15 | public IRemoteTestNG createRemoteTestNG() { 16 | return new RemoteTestNG6_9_10(); 17 | } 18 | 19 | @Override 20 | protected VersionRange getAcceptableVersions() { 21 | return RANGE; 22 | } 23 | 24 | @Override 25 | public int getOrder() { 26 | return 4; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /remote6_9_10/src/test/java/test/remote/Remote6_9_10_Test.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | import org.testng.internal.Version; 4 | 5 | public class Remote6_9_10_Test extends RemoteTest { 6 | 7 | @Override 8 | protected String getTestNGVersion() { 9 | return Version.VERSION; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /remote6_9_7/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote6_9_7 11 | TestNG Remote for version [6.9.7, 6.9.10) 12 | 13 | 14 | 6.9.9 15 | 16 | 17 | 18 | 19 | org.testng.testng-remote 20 | testng-remote 21 | 22 | 23 | org.testng 24 | testng 25 | ${testng.version} 26 | provided 27 | 28 | 29 | com.google.auto.service 30 | auto-service 31 | true 32 | 33 | 34 | org.testng.testng-remote 35 | testng-remote 36 | test-jar 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 46 | 47 | ${basedir}/../remote/target/test-classes 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /remote6_9_7/src/main/java/org/testng/remote/support/RemoteTestNG6_9_7.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.IConfigurationListener; 4 | import org.testng.IInvokedMethodListener; 5 | import org.testng.ISuite; 6 | import org.testng.ITestRunnerFactory; 7 | import org.testng.TestRunner; 8 | import org.testng.remote.AbstractRemoteTestNG; 9 | import org.testng.remote.strprotocol.MessageHub; 10 | import org.testng.remote.strprotocol.RemoteTestListener; 11 | import org.testng.reporters.JUnitXMLReporter; 12 | import org.testng.reporters.TestHTMLReporter; 13 | import org.testng.xml.XmlTest; 14 | 15 | import java.util.Collection; 16 | 17 | public class RemoteTestNG6_9_7 extends AbstractRemoteTestNG { 18 | 19 | @Override 20 | protected ITestRunnerFactory buildTestRunnerFactory() { 21 | if(null == m_customTestRunnerFactory) { 22 | m_customTestRunnerFactory= new ITestRunnerFactory() { 23 | @Override 24 | public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, 25 | Collection listeners) { 26 | TestRunner runner = 27 | new TestRunner(getConfiguration(), suite, xmlTest, 28 | false /*skipFailedInvocationCounts */, 29 | listeners); 30 | if (m_useDefaultListeners) { 31 | runner.addListener(new TestHTMLReporter()); 32 | runner.addListener(new JUnitXMLReporter()); 33 | } 34 | for (IConfigurationListener cl : getConfiguration().getConfigurationListeners()) { 35 | runner.addListener(cl); 36 | } 37 | 38 | return runner; 39 | } 40 | }; 41 | } 42 | 43 | return m_customTestRunnerFactory; 44 | } 45 | 46 | @Override 47 | protected ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 48 | return new DelegatingTestRunnerFactory(trf, smsh); 49 | } 50 | 51 | private static class DelegatingTestRunnerFactory implements ITestRunnerFactory { 52 | private final ITestRunnerFactory m_delegateFactory; 53 | private final MessageHub m_messageSender; 54 | 55 | DelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 56 | m_delegateFactory= trf; 57 | m_messageSender= smsh; 58 | } 59 | 60 | @Override 61 | public TestRunner newTestRunner(ISuite suite, XmlTest test, 62 | Collection listeners) { 63 | TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners); 64 | tr.addListener(new RemoteTestListener(suite, test, m_messageSender)); 65 | return tr; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /remote6_9_7/src/main/java/org/testng/remote/support/RemoteTestNGFactory6_9_7.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.remote.AbstractRemoteTestNGFactory; 4 | import org.testng.remote.IRemoteTestNG; 5 | import org.testng.shaded.osgi.framework.VersionRange; 6 | 7 | import com.google.auto.service.AutoService; 8 | 9 | @AutoService(RemoteTestNGFactory.class) 10 | public class RemoteTestNGFactory6_9_7 extends AbstractRemoteTestNGFactory { 11 | 12 | private static final VersionRange RANGE = new VersionRange("[6.9.7,6.9.10)"); 13 | 14 | @Override 15 | public IRemoteTestNG createRemoteTestNG() { 16 | return new RemoteTestNG6_9_7(); 17 | } 18 | 19 | @Override 20 | protected VersionRange getAcceptableVersions() { 21 | return RANGE; 22 | } 23 | 24 | @Override 25 | public int getOrder() { 26 | return 3; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /remote6_9_7/src/test/java/test/remote/Remote6_9_7Test.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | import org.testng.internal.Version; 4 | 5 | public class Remote6_9_7Test extends RemoteTest { 6 | 7 | @Override 8 | protected String getTestNGVersion() { 9 | return Version.VERSION; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /remote7_8/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote7_8 11 | TestNG Remote for version [7.8.0, 7.9.0) 12 | 13 | 14 | 7.8.0 15 | 16 | 17 | 18 | 19 | org.testng.testng-remote 20 | testng-remote 21 | 22 | 23 | org.testng 24 | testng 25 | ${testng.version} 26 | provided 27 | 28 | 29 | com.google.auto.service 30 | auto-service 31 | true 32 | 33 | 34 | org.testng.testng-remote 35 | testng-remote 36 | test-jar 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 46 | 47 | ${basedir}/../remote/target/test-classes 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /remote7_8/src/main/java/org/testng/remote/support/RemoteTestNG7_8.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.IClassListener; 4 | import org.testng.IInvokedMethodListener; 5 | import org.testng.ISuite; 6 | import org.testng.ITestRunnerFactory; 7 | import org.testng.SuiteRunner; 8 | import org.testng.TestRunner; 9 | import org.testng.remote.AbstractRemoteTestNG; 10 | import org.testng.remote.strprotocol.MessageHub; 11 | import org.testng.remote.strprotocol.RemoteTestListener; 12 | import org.testng.reporters.JUnitXMLReporter; 13 | import org.testng.reporters.TestHTMLReporter; 14 | import org.testng.xml.XmlTest; 15 | 16 | import java.util.Collection; 17 | import java.util.List; 18 | 19 | public class RemoteTestNG7_8 extends AbstractRemoteTestNG { 20 | 21 | @Override 22 | protected void initialize() { 23 | initializeEverything(); 24 | } 25 | 26 | @Override 27 | protected ITestRunnerFactory buildTestRunnerFactory() { 28 | if(null == m_customTestRunnerFactory) { 29 | m_customTestRunnerFactory= new ITestRunnerFactory() { 30 | @Override 31 | public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, 32 | Collection listeners, List classListeners) { 33 | TestRunner runner = 34 | new TestRunner(getConfiguration(), suite, xmlTest, 35 | false /*skipFailedInvocationCounts */, 36 | listeners, classListeners, (SuiteRunner) suite); 37 | if (m_useDefaultListeners) { 38 | runner.addListener(new TestHTMLReporter()); 39 | runner.addListener(new JUnitXMLReporter()); 40 | } 41 | 42 | return runner; 43 | } 44 | }; 45 | } 46 | 47 | return m_customTestRunnerFactory; 48 | } 49 | 50 | @Override 51 | protected ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 52 | return new DelegatingTestRunnerFactory(trf, smsh); 53 | } 54 | 55 | private static class DelegatingTestRunnerFactory implements ITestRunnerFactory { 56 | private final ITestRunnerFactory m_delegateFactory; 57 | private final MessageHub m_messageSender; 58 | 59 | DelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 60 | m_delegateFactory= trf; 61 | m_messageSender= smsh; 62 | } 63 | 64 | @Override 65 | public TestRunner newTestRunner(ISuite suite, XmlTest test, 66 | Collection listeners, List classListeners) { 67 | TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners, classListeners); 68 | tr.addListener(new RemoteTestListener(suite, test, m_messageSender)); 69 | return tr; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /remote7_8/src/main/java/org/testng/remote/support/RemoteTestNGFactory7_8.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.remote.AbstractRemoteTestNGFactory; 4 | import org.testng.remote.IRemoteTestNG; 5 | import org.testng.shaded.osgi.framework.VersionRange; 6 | 7 | import com.google.auto.service.AutoService; 8 | 9 | @AutoService(RemoteTestNGFactory.class) 10 | public class RemoteTestNGFactory7_8 extends AbstractRemoteTestNGFactory { 11 | 12 | private static final VersionRange RANGE = new VersionRange("[7.8,7.9)"); 13 | 14 | @Override 15 | public IRemoteTestNG createRemoteTestNG() { 16 | return new RemoteTestNG7_8(); 17 | } 18 | 19 | @Override 20 | protected VersionRange getAcceptableVersions() { 21 | return RANGE; 22 | } 23 | 24 | @Override 25 | public int getOrder() { 26 | return 7; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /remote7_8/src/test/java/test/remote/Remote7_8_Test.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | import org.testng.internal.Version; 4 | 5 | public class Remote7_8_Test extends RemoteTest { 6 | 7 | @Override 8 | protected String getTestNGVersion() { 9 | return Version.VERSION; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /remote7_9/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | 5 | org.testng.testng-remote 6 | testng-remote-parent 7 | 1.8.0-SNAPSHOT 8 | 9 | 10 | testng-remote7_9 11 | TestNG Remote for version [7.9.0, -) 12 | 13 | 14 | 7.9.0 15 | 16 | 17 | 18 | 19 | org.testng.testng-remote 20 | testng-remote 21 | 22 | 23 | org.testng 24 | testng 25 | ${testng.version} 26 | provided 27 | 28 | 29 | com.google.auto.service 30 | auto-service 31 | true 32 | 33 | 34 | org.testng.testng-remote 35 | testng-remote 36 | test-jar 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 46 | 47 | ${basedir}/../remote/target/test-classes 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /remote7_9/src/main/java/org/testng/remote/support/RemoteTestNG7_9.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.IClassListener; 4 | import org.testng.IInvokedMethodListener; 5 | import org.testng.ISuite; 6 | import org.testng.ISuiteRunnerListener; 7 | import org.testng.ITestRunnerFactory; 8 | import org.testng.SuiteRunner; 9 | import org.testng.TestRunner; 10 | import org.testng.remote.AbstractRemoteTestNG; 11 | import org.testng.remote.strprotocol.MessageHub; 12 | import org.testng.remote.strprotocol.RemoteTestListener; 13 | import org.testng.reporters.JUnitXMLReporter; 14 | import org.testng.reporters.TestHTMLReporter; 15 | import org.testng.xml.XmlTest; 16 | 17 | import java.util.Collection; 18 | import java.util.List; 19 | 20 | public class RemoteTestNG7_9 extends AbstractRemoteTestNG { 21 | 22 | @Override 23 | protected void initialize() { 24 | initializeEverything(); 25 | } 26 | 27 | @Override 28 | protected ITestRunnerFactory buildTestRunnerFactory() { 29 | if(null == m_customTestRunnerFactory) { 30 | m_customTestRunnerFactory= new ITestRunnerFactory() { 31 | @Override 32 | public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest, 33 | Collection listeners, List classListeners) { 34 | TestRunner runner = 35 | new TestRunner(getConfiguration(), suite, xmlTest, 36 | false /*skipFailedInvocationCounts */, 37 | listeners, classListeners, (ISuiteRunnerListener) suite); 38 | if (m_useDefaultListeners) { 39 | runner.addListener(new TestHTMLReporter()); 40 | runner.addListener(new JUnitXMLReporter()); 41 | } 42 | 43 | return runner; 44 | } 45 | }; 46 | } 47 | 48 | return m_customTestRunnerFactory; 49 | } 50 | 51 | @Override 52 | protected ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 53 | return new DelegatingTestRunnerFactory(trf, smsh); 54 | } 55 | 56 | private static class DelegatingTestRunnerFactory implements ITestRunnerFactory { 57 | private final ITestRunnerFactory m_delegateFactory; 58 | private final MessageHub m_messageSender; 59 | 60 | DelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh) { 61 | m_delegateFactory= trf; 62 | m_messageSender= smsh; 63 | } 64 | 65 | @Override 66 | public TestRunner newTestRunner(ISuite suite, XmlTest test, 67 | Collection listeners, List classListeners) { 68 | TestRunner tr = m_delegateFactory.newTestRunner(suite, test, listeners, classListeners); 69 | tr.addListener(new RemoteTestListener(suite, test, m_messageSender)); 70 | return tr; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /remote7_9/src/main/java/org/testng/remote/support/RemoteTestNGFactory7_9.java: -------------------------------------------------------------------------------- 1 | package org.testng.remote.support; 2 | 3 | import org.testng.remote.AbstractRemoteTestNGFactory; 4 | import org.testng.remote.IRemoteTestNG; 5 | import org.testng.shaded.osgi.framework.VersionRange; 6 | 7 | import com.google.auto.service.AutoService; 8 | 9 | @AutoService(RemoteTestNGFactory.class) 10 | public class RemoteTestNGFactory7_9 extends AbstractRemoteTestNGFactory { 11 | 12 | private static final VersionRange RANGE = new VersionRange("7.9"); 13 | 14 | @Override 15 | public IRemoteTestNG createRemoteTestNG() { 16 | return new RemoteTestNG7_9(); 17 | } 18 | 19 | @Override 20 | protected VersionRange getAcceptableVersions() { 21 | return RANGE; 22 | } 23 | 24 | @Override 25 | public int getOrder() { 26 | return 7; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /remote7_9/src/test/java/test/remote/Remote7_9_Test.java: -------------------------------------------------------------------------------- 1 | package test.remote; 2 | 3 | import org.testng.internal.Version; 4 | 5 | public class Remote7_9_Test extends RemoteTest { 6 | 7 | @Override 8 | protected String getTestNGVersion() { 9 | return Version.VERSION; 10 | } 11 | 12 | } 13 | --------------------------------------------------------------------------------