├── .gitignore ├── LICENSE.txt ├── README.md ├── pom.xml └── src ├── main ├── java │ └── net │ │ └── unit8 │ │ └── jmeter │ │ └── protocol │ │ └── websocket │ │ ├── control │ │ └── gui │ │ │ └── WebSocketSamplerGui.java │ │ └── sampler │ │ └── WebSocketSampler.java └── resources │ └── net │ └── unit8 │ └── jmeter │ └── protocol │ └── websocket │ └── sampler │ ├── WebSocketSamplerResources.properties │ └── WebSocketSamplerResources_ja.properties └── test ├── java └── net │ └── unit8 │ └── jmeter │ └── protocol │ └── websocket │ └── sampler │ └── WebSocketSamplerTest.java ├── resources ├── jmeter.properties ├── saveservice.properties └── users.csv └── scripts └── chat.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | target 4 | *.iml 5 | *.class 6 | *.log 7 | *-log 8 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2013 kawasima1016@gmail.com 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ApacheJmeter websocket 2 | ====================== 3 | 4 | This is the jmeter plugin for WebSocket protocol. -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | net.unit8.jmeter 8 | ApacheJmeter_websocket 9 | 0.1.0-SNAPSHOT 10 | ApacheJmeter_websocket 11 | 12 | 13 | 2.9 14 | 8.1.9.v20130131 15 | 16 | 17 | 18 | 19 | 20 | org.apache.maven.plugins 21 | maven-shade-plugin 22 | 2.0 23 | 24 | target/${project.name}-dist-${project.version}.jar 25 | 26 | 27 | 28 | package 29 | 30 | shade 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | org.apache.jmeter 41 | ApacheJMeter 42 | ${jmeterVersion} 43 | provided 44 | 45 | 46 | org.apache.jmeter 47 | ApacheJMeter_http 48 | ${jmeterVersion} 49 | provided 50 | 51 | 52 | org.apache.jmeter 53 | ApacheJMeter_functions 54 | ${jmeterVersion} 55 | provided 56 | 57 | 58 | org.eclipse.jetty 59 | jetty-websocket 60 | ${jettyVersion} 61 | 62 | 63 | junit 64 | junit 65 | 4.11 66 | test 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/net/unit8/jmeter/protocol/websocket/control/gui/WebSocketSamplerGui.java: -------------------------------------------------------------------------------- 1 | package net.unit8.jmeter.protocol.websocket.control.gui; 2 | 3 | import net.unit8.jmeter.protocol.websocket.sampler.WebSocketSampler; 4 | import org.apache.jmeter.config.Arguments; 5 | import org.apache.jmeter.gui.util.HorizontalPanel; 6 | import org.apache.jmeter.gui.util.VerticalPanel; 7 | import org.apache.jmeter.protocol.http.gui.HTTPArgumentsPanel; 8 | import org.apache.jmeter.protocol.http.util.HTTPArgument; 9 | import org.apache.jmeter.samplers.gui.AbstractSamplerGui; 10 | import org.apache.jmeter.testelement.TestElement; 11 | import org.apache.jmeter.testelement.property.TestElementProperty; 12 | import org.apache.jmeter.util.JMeterUtils; 13 | import org.apache.jorphan.logging.LoggingManager; 14 | import org.apache.log.Logger; 15 | 16 | import javax.swing.*; 17 | import java.awt.*; 18 | import java.util.Locale; 19 | import java.util.MissingResourceException; 20 | import java.util.ResourceBundle; 21 | 22 | /** 23 | * GUI for WebSocetSampler 24 | * 25 | * @author kawasima 26 | */ 27 | public class WebSocketSamplerGui extends AbstractSamplerGui { 28 | private static final Logger log = LoggingManager.getLoggerForClass(); 29 | 30 | private JTextField domain; 31 | private JTextField port; 32 | private JTextField protocol; 33 | private JTextField contentEncoding; 34 | private JTextField path; 35 | private JTextArea sendMessage; 36 | private JTextArea recvMessage; 37 | private HTTPArgumentsPanel argsPanel; 38 | 39 | private boolean displayName = true; 40 | private static final ResourceBundle resources; 41 | 42 | static { 43 | Locale loc = JMeterUtils.getLocale(); 44 | resources = ResourceBundle.getBundle(WebSocketSampler.class.getName() + "Resources", loc); 45 | log.info("Resource " + WebSocketSampler.class.getName() + //$NON-NLS-1$ 46 | " is loaded for locale " + loc); //$NON-NLS-1$ 47 | } 48 | 49 | public WebSocketSamplerGui() { 50 | this(true); 51 | } 52 | 53 | public WebSocketSamplerGui(boolean displayName) { 54 | this.displayName = displayName; 55 | init(); 56 | } 57 | 58 | @Override 59 | public String getLabelResource() { 60 | throw new IllegalStateException("This shouldn't be called"); //$NON-NLS-1$ 61 | } 62 | 63 | @Override 64 | public String getStaticLabel() { 65 | return getResString("websocket_testing_title"); //$NON-NLS-1$ 66 | } 67 | @Override 68 | public void configure(TestElement element) { 69 | super.configure(element); 70 | domain.setText(element.getPropertyAsString(WebSocketSampler.DOMAIN)); 71 | port.setText(element.getPropertyAsString(WebSocketSampler.PORT)); 72 | protocol.setText(element.getPropertyAsString(WebSocketSampler.PROTOCOL)); 73 | path.setText(element.getPropertyAsString(WebSocketSampler.PATH)); 74 | contentEncoding.setText(element.getPropertyAsString(WebSocketSampler.CONTENT_ENCODING)); 75 | 76 | Arguments arguments = (Arguments) element.getProperty(WebSocketSampler.ARGUMENTS).getObjectValue(); 77 | argsPanel.configure(arguments); 78 | 79 | sendMessage.setText(element.getPropertyAsString(WebSocketSampler.SEND_MESSAGE)); 80 | recvMessage.setText(element.getPropertyAsString(WebSocketSampler.RECV_MESSAGE)); 81 | } 82 | 83 | @Override 84 | public TestElement createTestElement() { 85 | WebSocketSampler element = new WebSocketSampler(); 86 | 87 | element.setName(getName()); 88 | element.setProperty(TestElement.GUI_CLASS, this.getClass().getName()); 89 | element.setProperty(TestElement.TEST_CLASS, element.getClass().getName()); 90 | 91 | modifyTestElement(element); 92 | return element; 93 | } 94 | 95 | @Override 96 | public void modifyTestElement(TestElement element) { 97 | configureTestElement(element); 98 | element.setProperty(WebSocketSampler.DOMAIN, domain.getText()); 99 | element.setProperty(WebSocketSampler.PATH, path.getText()); 100 | element.setProperty(WebSocketSampler.PORT, port.getText()); 101 | element.setProperty(WebSocketSampler.PROTOCOL, protocol.getText()); 102 | element.setProperty(WebSocketSampler.CONTENT_ENCODING, contentEncoding.getText()); 103 | 104 | Arguments args = (Arguments) argsPanel.createTestElement(); 105 | HTTPArgument.convertArgumentsToHTTP(args); 106 | element.setProperty(new TestElementProperty(WebSocketSampler.ARGUMENTS, args)); 107 | 108 | element.setProperty(WebSocketSampler.SEND_MESSAGE, sendMessage.getText()); 109 | element.setProperty(WebSocketSampler.RECV_MESSAGE, recvMessage.getText()); 110 | } 111 | 112 | private JPanel getDomainPanel() { 113 | domain = new JTextField(20); 114 | 115 | JLabel label = new JLabel(JMeterUtils.getResString("web_server_domain")); // $NON-NLS-1$ 116 | label.setLabelFor(domain); 117 | 118 | JPanel panel = new JPanel(new BorderLayout(5, 0)); 119 | panel.add(label, BorderLayout.WEST); 120 | panel.add(domain, BorderLayout.CENTER); 121 | return panel; 122 | } 123 | 124 | private JPanel getPortPanel() { 125 | port = new JTextField(4); 126 | 127 | JLabel label = new JLabel(JMeterUtils.getResString("web_server_port")); // $NON-NLS-1$ 128 | label.setLabelFor(port); 129 | 130 | JPanel panel = new JPanel(new BorderLayout(5, 0)); 131 | panel.add(label, BorderLayout.WEST); 132 | panel.add(port, BorderLayout.CENTER); 133 | 134 | return panel; 135 | } 136 | 137 | protected Component getProtocolAndPathPanel() { 138 | // PATH 139 | path = new JTextField(15); 140 | JLabel pathLabel = new JLabel(JMeterUtils.getResString("path")); //$NON-NLS-1$ 141 | pathLabel.setLabelFor(path); 142 | 143 | // PROTOCOL 144 | protocol = new JTextField(4); 145 | JLabel protocolLabel = new JLabel(JMeterUtils.getResString("protocol")); // $NON-NLS-1$ 146 | protocolLabel.setLabelFor(protocol); 147 | 148 | // CONTENT_ENCODING 149 | contentEncoding = new JTextField(10); 150 | JLabel contentEncodingLabel = new JLabel(JMeterUtils.getResString("content_encoding")); // $NON-NLS-1$ 151 | contentEncodingLabel.setLabelFor(contentEncoding); 152 | 153 | JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 154 | panel.add(pathLabel); 155 | panel.add(path); 156 | panel.add(Box.createHorizontalStrut(5)); 157 | 158 | panel.add(protocolLabel); 159 | panel.add(protocol); 160 | panel.add(Box.createHorizontalStrut(5)); 161 | 162 | panel.add(contentEncodingLabel); 163 | panel.add(contentEncoding); 164 | panel.setMinimumSize(panel.getPreferredSize()); 165 | 166 | return panel; 167 | } 168 | 169 | private JPanel getSendMessagePanel() { 170 | JLabel sendMessageLabel = new JLabel(getResString("websocket_send_message")); // $NON-NLS-1$ 171 | sendMessage = new JTextArea(3, 0); 172 | sendMessage.setLineWrap(true); 173 | sendMessageLabel.setLabelFor(sendMessage); 174 | 175 | JPanel sendMessagePanel = new JPanel(new BorderLayout(5, 0)); 176 | sendMessagePanel.add(sendMessageLabel, BorderLayout.WEST); 177 | sendMessagePanel.add(sendMessage, BorderLayout.CENTER); 178 | return sendMessagePanel; 179 | } 180 | 181 | private JPanel getRecvMessagePanel() { 182 | JLabel recvMessageLabel = new JLabel(getResString("websocket_recv_message")); // $NON-NLS-1$ 183 | recvMessage = new JTextArea(3, 0); 184 | recvMessage.setLineWrap(true); 185 | recvMessageLabel.setLabelFor(recvMessage); 186 | 187 | JPanel recvMessagePanel = new JPanel(new BorderLayout(5, 0)); 188 | recvMessagePanel.add(recvMessageLabel, BorderLayout.WEST); 189 | recvMessagePanel.add(recvMessage, BorderLayout.CENTER); 190 | return recvMessagePanel; 191 | } 192 | 193 | private void init() { 194 | setLayout(new BorderLayout(0, 5)); 195 | 196 | if (displayName) { 197 | setBorder(makeBorder()); 198 | add(makeTitlePanel(), BorderLayout.NORTH); 199 | } 200 | 201 | // MAIN PANEL 202 | VerticalPanel mainPanel = new VerticalPanel(); 203 | JPanel webRequestPanel = new HorizontalPanel(); 204 | JPanel serverPanel = new JPanel(); 205 | serverPanel.setLayout(new BoxLayout(serverPanel, BoxLayout.X_AXIS)); 206 | serverPanel.add(getDomainPanel()); 207 | serverPanel.add(getPortPanel()); 208 | 209 | webRequestPanel.add(serverPanel, BorderLayout.NORTH); 210 | JPanel northPanel = new JPanel(); 211 | northPanel.setLayout(new BoxLayout(northPanel, BoxLayout.Y_AXIS)); 212 | northPanel.add(getProtocolAndPathPanel()); 213 | 214 | webRequestPanel.add(northPanel, BorderLayout.CENTER); 215 | argsPanel = new HTTPArgumentsPanel(); 216 | webRequestPanel.add(argsPanel, BorderLayout.SOUTH); 217 | 218 | mainPanel.add(webRequestPanel); 219 | mainPanel.add(getSendMessagePanel()); 220 | mainPanel.add(getRecvMessagePanel()); 221 | add(mainPanel, BorderLayout.CENTER); 222 | } 223 | 224 | /** 225 | * Gets the resource string for this key. 226 | * 227 | * If the resource is not found, a warning is logged 228 | * 229 | * @param key 230 | * the key in the resource file 231 | * @return the resource string if the key is found; otherwise, return 232 | * "[res_key="+key+"]" 233 | */ 234 | public static String getResString(String key) { 235 | return getResStringDefault(key, RES_KEY_PFX + key + "]"); //$NON-NLS-1$ 236 | } 237 | 238 | public static final String RES_KEY_PFX = "[res_key="; //$NON-NLS-1$ 239 | 240 | /* 241 | * Helper method to do the actual work of fetching resources; allows 242 | * getResString(S,S) to be deprecated without affecting getResString(S); 243 | */ 244 | private static String getResStringDefault(String key, String defaultValue) { 245 | if (key == null) { 246 | return null; 247 | } 248 | // Resource keys cannot contain spaces 249 | key = key.replace(' ', '_'); // $NON-NLS-1$ // $NON-NLS-2$ 250 | key = key.toLowerCase(java.util.Locale.ENGLISH); 251 | String resString = null; 252 | try { 253 | resString = resources.getString(key); 254 | } catch (MissingResourceException mre) { 255 | log.warn("ERROR! Resource string not found: [" + //$NON-NLS-1$ 256 | key + "]", mre); //$NON-NLS-1$ 257 | resString = defaultValue; 258 | } 259 | return resString; 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /src/main/java/net/unit8/jmeter/protocol/websocket/sampler/WebSocketSampler.java: -------------------------------------------------------------------------------- 1 | package net.unit8.jmeter.protocol.websocket.sampler; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.apache.jmeter.config.Argument; 5 | import org.apache.jmeter.config.Arguments; 6 | import org.apache.jmeter.config.ConfigTestElement; 7 | import org.apache.jmeter.protocol.http.util.EncoderCache; 8 | import org.apache.jmeter.protocol.http.util.HTTPArgument; 9 | import org.apache.jmeter.protocol.http.util.HTTPConstants; 10 | import org.apache.jmeter.samplers.AbstractSampler; 11 | import org.apache.jmeter.samplers.Entry; 12 | import org.apache.jmeter.samplers.SampleResult; 13 | import org.apache.jmeter.testelement.TestElement; 14 | import org.apache.jmeter.testelement.TestStateListener; 15 | import org.apache.jmeter.testelement.property.*; 16 | import org.apache.jmeter.threads.JMeterContextService; 17 | import org.apache.jorphan.logging.LoggingManager; 18 | import org.apache.jorphan.util.JOrphanUtils; 19 | import org.apache.log.Logger; 20 | import org.eclipse.jetty.util.ConcurrentHashSet; 21 | import org.eclipse.jetty.websocket.WebSocket; 22 | import org.eclipse.jetty.websocket.WebSocketClient; 23 | import org.eclipse.jetty.websocket.WebSocketClientFactory; 24 | 25 | import java.io.UnsupportedEncodingException; 26 | import java.net.URI; 27 | import java.net.URISyntaxException; 28 | import java.util.Arrays; 29 | import java.util.HashSet; 30 | import java.util.Set; 31 | import java.util.concurrent.Future; 32 | import java.util.concurrent.TimeoutException; 33 | import java.util.regex.Pattern; 34 | 35 | /** 36 | * The sampler for WebSocket. 37 | 38 | * @author kawasima 39 | */ 40 | public class WebSocketSampler extends AbstractSampler implements TestStateListener { 41 | 42 | private static final Logger log = LoggingManager.getLoggerForClass(); 43 | 44 | private static final Set APPLIABLE_CONFIG_CLASSES = new HashSet( 45 | Arrays.asList(new String[]{ 46 | "net.unit8.jmeter.protocol.websocket.control.gui.WebSocketSamplerGui", 47 | "org.apache.jmeter.config.gui.SimpleConfigGui"})); 48 | 49 | private static final String ARG_VAL_SEP = "="; // $NON-NLS-1$ 50 | private static final String QRY_SEP = "&"; // $NON-NLS-1$ 51 | private static final String QRY_PFX = "?"; // $NON-NLS-1$ 52 | 53 | private static final String WS_PREFIX = "ws://"; // $NON-NLS-1$ 54 | private static final String WSS_PREFIX = "wss://"; // $NON-NLS-1$ 55 | private static final String DEFAULT_PROTOCOL = "ws"; 56 | private static final int UNSPECIFIED_PORT = 0; 57 | private static final String UNSPECIFIED_PORT_AS_STRING = "0"; // $NON-NLS-1$ 58 | private static final int URL_UNSPECIFIED_PORT = -1; 59 | 60 | 61 | private WebSocket.Connection connection = null; 62 | private static final ConcurrentHashSet samplerConnections 63 | = new ConcurrentHashSet(); 64 | 65 | private boolean initialized = false; 66 | private String responseMessage; 67 | 68 | public static final String DOMAIN = "WebSocketSampler.domain"; 69 | public static final String PORT = "WebSocketSampler.port"; 70 | public static final String PATH = "WebSocketSampler.path"; 71 | public static final String PROTOCOL = "WebSocketSampler.protocol"; 72 | public static final String CONTENT_ENCODING = "WebSocketSampler.contentEncoding"; 73 | public static final String ARGUMENTS = "WebSocketSampler.arguments"; 74 | public static final String SEND_MESSAGE = "WebSocketSampler.sendMessage"; 75 | public static final String RECV_MESSAGE = "WebSocketSampler.recvMessage"; 76 | public static final String RECV_TIMEOUT = "WebSocketSampler.recvTimeout"; 77 | 78 | private static WebSocketClientFactory webSocketClientFactory = new WebSocketClientFactory(); 79 | 80 | 81 | public WebSocketSampler() { 82 | setArguments(new Arguments()); 83 | } 84 | 85 | public void initialize() throws Exception { 86 | URI uri = getUri(); 87 | WebSocketClient webSocketClient = webSocketClientFactory.newWebSocketClient(); 88 | final WebSocketSampler parent = this; 89 | final String threadName = JMeterContextService.getContext().getThread().getThreadName(); 90 | final Pattern regex = (getRecvMessage() != null) ? Pattern.compile(getRecvMessage()) : null; 91 | Future futureConnection = webSocketClient.open(uri, new WebSocket.OnTextMessage() { 92 | 93 | @Override 94 | public void onMessage(String s) { 95 | synchronized (parent) { 96 | if (regex == null || regex.matcher(s).find()) { 97 | responseMessage = s; 98 | parent.notify(); 99 | } 100 | } 101 | } 102 | 103 | @Override 104 | public void onOpen(Connection connection) { 105 | log.debug("Connect " + threadName); 106 | } 107 | 108 | @Override 109 | public void onClose(int i, String s) { 110 | log.debug("Disconnect " + threadName); 111 | } 112 | }); 113 | connection = futureConnection.get(); 114 | samplerConnections.add(connection); 115 | initialized = true; 116 | } 117 | @Override 118 | public SampleResult sample(Entry entry) { 119 | SampleResult res = new SampleResult(); 120 | res.setSampleLabel(getName()); 121 | 122 | boolean isOK = false; 123 | if (!initialized) { 124 | try { 125 | initialize(); 126 | } catch (Exception e) { 127 | res.setResponseMessage(e.getMessage()); 128 | res.setSuccessful(false); 129 | return res; 130 | } 131 | } 132 | String message = getPropertyAsString(SEND_MESSAGE, "default message"); 133 | res.setSamplerData(message); 134 | res.sampleStart(); 135 | try { 136 | if (connection.isOpen()) { 137 | res.setDataEncoding(getContentEncoding()); 138 | connection.sendMessage(message); 139 | } else { 140 | initialize(); 141 | } 142 | synchronized (this) { 143 | wait(getRecvTimeout()); 144 | } 145 | if (responseMessage == null) { 146 | res.setResponseCode("204"); 147 | throw new TimeoutException("No content (probably timeout)."); 148 | } 149 | res.setResponseCodeOK(); 150 | res.setResponseData(responseMessage, getContentEncoding()); 151 | isOK = true; 152 | } catch (Exception e) { 153 | log.debug(e.getMessage()); 154 | res.setResponseMessage(e.getMessage()); 155 | } 156 | res.sampleEnd(); 157 | res.setSuccessful(isOK); 158 | 159 | return res; 160 | } 161 | 162 | 163 | @Override 164 | public void setName(String name) { 165 | if (name != null) 166 | setProperty(TestElement.NAME, name); 167 | } 168 | 169 | @Override 170 | public String getName() { 171 | return getPropertyAsString(TestElement.NAME); 172 | } 173 | 174 | @Override 175 | public void setComment(String comment){ 176 | setProperty(new StringProperty(TestElement.COMMENTS, comment)); 177 | } 178 | 179 | @Override 180 | public String getComment(){ 181 | return getProperty(TestElement.COMMENTS).getStringValue(); 182 | } 183 | 184 | public URI getUri() throws URISyntaxException { 185 | String path = this.getPath(); 186 | // Hack to allow entire URL to be provided in host field 187 | if (path.startsWith(WS_PREFIX) 188 | || path.startsWith(WSS_PREFIX)){ 189 | return new URI(path); 190 | } 191 | String domain = getDomain(); 192 | String protocol = getProtocol(); 193 | // HTTP URLs must be absolute, allow file to be relative 194 | if (!path.startsWith("/")){ // $NON-NLS-1$ 195 | path = "/" + path; // $NON-NLS-1$ 196 | } 197 | 198 | String queryString = getQueryString(getContentEncoding()); 199 | if(isProtocolDefaultPort()) { 200 | return new URI(protocol, null, domain, -1, path, queryString, null); 201 | } 202 | return new URI(protocol, null, domain, getPort(), path, queryString, null); 203 | } 204 | 205 | public void setPath(String path, String contentEncoding) { 206 | boolean fullUrl = path.startsWith(WS_PREFIX) || path.startsWith(WSS_PREFIX); 207 | if (!fullUrl) { 208 | int index = path.indexOf(QRY_PFX); 209 | if (index > -1) { 210 | setProperty(PATH, path.substring(0, index)); 211 | // Parse the arguments in querystring, assuming specified encoding for values 212 | parseArguments(path.substring(index + 1), contentEncoding); 213 | } else { 214 | setProperty(PATH, path); 215 | } 216 | } else { 217 | setProperty(PATH, path); 218 | } 219 | } 220 | 221 | public String getPath() { 222 | String p = getPropertyAsString(PATH); 223 | return encodeSpaces(p); 224 | } 225 | 226 | public void setPort(int value) { 227 | setProperty(new IntegerProperty(PORT, value)); 228 | } 229 | 230 | public static int getDefaultPort(String protocol,int port){ 231 | if (port==URL_UNSPECIFIED_PORT){ 232 | return 233 | protocol.equalsIgnoreCase(HTTPConstants.PROTOCOL_HTTP) ? HTTPConstants.DEFAULT_HTTP_PORT : 234 | protocol.equalsIgnoreCase(HTTPConstants.PROTOCOL_HTTPS) ? HTTPConstants.DEFAULT_HTTPS_PORT : 235 | port; 236 | } 237 | return port; 238 | } 239 | 240 | /** 241 | * Get the port number from the port string, allowing for trailing blanks. 242 | * 243 | * @return port number or UNSPECIFIED_PORT (== 0) 244 | */ 245 | public int getPortIfSpecified() { 246 | String port_s = getPropertyAsString(PORT, UNSPECIFIED_PORT_AS_STRING); 247 | try { 248 | return Integer.parseInt(port_s.trim()); 249 | } catch (NumberFormatException e) { 250 | return UNSPECIFIED_PORT; 251 | } 252 | } 253 | 254 | /** 255 | * Tell whether the default port for the specified protocol is used 256 | * 257 | * @return true if the default port number for the protocol is used, false otherwise 258 | */ 259 | public boolean isProtocolDefaultPort() { 260 | final int port = getPortIfSpecified(); 261 | final String protocol = getProtocol(); 262 | return port == UNSPECIFIED_PORT || 263 | ("ws".equalsIgnoreCase(protocol) && port == HTTPConstants.DEFAULT_HTTP_PORT) || 264 | ("wss".equalsIgnoreCase(protocol) && port == HTTPConstants.DEFAULT_HTTPS_PORT); 265 | } 266 | 267 | public int getPort() { 268 | final int port = getPortIfSpecified(); 269 | if (port == UNSPECIFIED_PORT) { 270 | String prot = getProtocol(); 271 | if ("wss".equalsIgnoreCase(prot)) { 272 | return HTTPConstants.DEFAULT_HTTPS_PORT; 273 | } 274 | if (!"ws".equalsIgnoreCase(prot)) { 275 | log.warn("Unexpected protocol: "+prot); 276 | // TODO - should this return something else? 277 | } 278 | return HTTPConstants.DEFAULT_HTTP_PORT; 279 | } 280 | return port; 281 | } 282 | 283 | 284 | public void setDomain(String value) { 285 | setProperty(DOMAIN, value); 286 | } 287 | 288 | public String getDomain() { 289 | return getPropertyAsString(DOMAIN); 290 | } 291 | public void setProtocol(String value) { 292 | setProperty(PROTOCOL, value.toLowerCase(java.util.Locale.ENGLISH)); 293 | } 294 | 295 | public String getProtocol() { 296 | String protocol = getPropertyAsString(PROTOCOL); 297 | if (protocol == null || protocol.length() == 0 ) { 298 | return DEFAULT_PROTOCOL; 299 | } 300 | return protocol; 301 | } 302 | 303 | public void setContentEncoding(String charsetName) { 304 | setProperty(CONTENT_ENCODING, charsetName); 305 | } 306 | public String getContentEncoding() { 307 | return getPropertyAsString(CONTENT_ENCODING); 308 | } 309 | 310 | public String getQueryString(String contentEncoding) { 311 | // Check if the sampler has a specified content encoding 312 | if(JOrphanUtils.isBlank(contentEncoding)) { 313 | // We use the encoding which should be used according to the HTTP spec, which is UTF-8 314 | contentEncoding = EncoderCache.URL_ARGUMENT_ENCODING; 315 | } 316 | StringBuilder buf = new StringBuilder(); 317 | PropertyIterator iter = getArguments().iterator(); 318 | boolean first = true; 319 | while (iter.hasNext()) { 320 | HTTPArgument item = null; 321 | Object objectValue = iter.next().getObjectValue(); 322 | try { 323 | item = (HTTPArgument) objectValue; 324 | } catch (ClassCastException e) { 325 | item = new HTTPArgument((Argument) objectValue); 326 | } 327 | final String encodedName = item.getEncodedName(); 328 | if (encodedName.length() == 0) { 329 | continue; // Skip parameters with a blank name (allows use of optional variables in parameter lists) 330 | } 331 | if (!first) { 332 | buf.append(QRY_SEP); 333 | } else { 334 | first = false; 335 | } 336 | buf.append(encodedName); 337 | if (item.getMetaData() == null) { 338 | buf.append(ARG_VAL_SEP); 339 | } else { 340 | buf.append(item.getMetaData()); 341 | } 342 | 343 | // Encode the parameter value in the specified content encoding 344 | try { 345 | buf.append(item.getEncodedValue(contentEncoding)); 346 | } 347 | catch(UnsupportedEncodingException e) { 348 | log.warn("Unable to encode parameter in encoding " + contentEncoding + ", parameter value not included in query string"); 349 | } 350 | } 351 | return buf.toString(); 352 | } 353 | 354 | public void setSendMessage(String value) { 355 | setProperty(SEND_MESSAGE, value); 356 | } 357 | 358 | public String getSendMessage() { 359 | return getPropertyAsString(SEND_MESSAGE); 360 | } 361 | 362 | public void setRecvMessage(String value) { 363 | setProperty(RECV_MESSAGE, value); 364 | } 365 | 366 | public String getRecvMessage() { 367 | return getPropertyAsString(RECV_MESSAGE); 368 | } 369 | 370 | public void setRecvTimeout(long value) { 371 | setProperty(new LongProperty(RECV_TIMEOUT, value)); 372 | } 373 | 374 | public long getRecvTimeout() { 375 | return getPropertyAsLong(RECV_TIMEOUT, 20000L); 376 | } 377 | 378 | public void setArguments(Arguments value) { 379 | setProperty(new TestElementProperty(ARGUMENTS, value)); 380 | } 381 | 382 | 383 | public Arguments getArguments() { 384 | return (Arguments) getProperty(ARGUMENTS).getObjectValue(); 385 | } 386 | 387 | protected String encodeSpaces(String path) { 388 | return JOrphanUtils.replaceAllChars(path, ' ', "%20"); // $NON-NLS-1$ 389 | } 390 | 391 | public void parseArguments(String queryString, String contentEncoding) { 392 | String[] args = JOrphanUtils.split(queryString, QRY_SEP); 393 | for (int i = 0; i < args.length; i++) { 394 | // need to handle four cases: 395 | // - string contains name=value 396 | // - string contains name= 397 | // - string contains name 398 | // - empty string 399 | 400 | String metaData; // records the existance of an equal sign 401 | String name; 402 | String value; 403 | int length = args[i].length(); 404 | int endOfNameIndex = args[i].indexOf(ARG_VAL_SEP); 405 | if (endOfNameIndex != -1) {// is there a separator? 406 | // case of name=value, name= 407 | metaData = ARG_VAL_SEP; 408 | name = args[i].substring(0, endOfNameIndex); 409 | value = args[i].substring(endOfNameIndex + 1, length); 410 | } else { 411 | metaData = ""; 412 | name=args[i]; 413 | value=""; 414 | } 415 | if (name.length() > 0) { 416 | // If we know the encoding, we can decode the argument value, 417 | // to make it easier to read for the user 418 | if(!StringUtils.isEmpty(contentEncoding)) { 419 | addEncodedArgument(name, value, metaData, contentEncoding); 420 | } 421 | else { 422 | // If we do not know the encoding, we just use the encoded value 423 | // The browser has already done the encoding, so save the values as is 424 | addNonEncodedArgument(name, value, metaData); 425 | } 426 | } 427 | } 428 | } 429 | public void addEncodedArgument(String name, String value, String metaData, String contentEncoding) { 430 | if (log.isDebugEnabled()){ 431 | log.debug("adding argument: name: " + name + " value: " + value + " metaData: " + metaData + " contentEncoding: " + contentEncoding); 432 | } 433 | 434 | HTTPArgument arg = null; 435 | final boolean nonEmptyEncoding = !StringUtils.isEmpty(contentEncoding); 436 | if(nonEmptyEncoding) { 437 | arg = new HTTPArgument(name, value, metaData, true, contentEncoding); 438 | } 439 | else { 440 | arg = new HTTPArgument(name, value, metaData, true); 441 | } 442 | 443 | // Check if there are any difference between name and value and their encoded name and value 444 | String valueEncoded = null; 445 | if(nonEmptyEncoding) { 446 | try { 447 | valueEncoded = arg.getEncodedValue(contentEncoding); 448 | } 449 | catch (UnsupportedEncodingException e) { 450 | log.warn("Unable to get encoded value using encoding " + contentEncoding); 451 | valueEncoded = arg.getEncodedValue(); 452 | } 453 | } 454 | else { 455 | valueEncoded = arg.getEncodedValue(); 456 | } 457 | // If there is no difference, we mark it as not needing encoding 458 | if (arg.getName().equals(arg.getEncodedName()) && arg.getValue().equals(valueEncoded)) { 459 | arg.setAlwaysEncoded(false); 460 | } 461 | this.getArguments().addArgument(arg); 462 | } 463 | 464 | public void addEncodedArgument(String name, String value, String metaData) { 465 | this.addEncodedArgument(name, value, metaData, null); 466 | } 467 | 468 | public void addNonEncodedArgument(String name, String value, String metadata) { 469 | HTTPArgument arg = new HTTPArgument(name, value, metadata, false); 470 | arg.setAlwaysEncoded(false); 471 | this.getArguments().addArgument(arg); 472 | } 473 | 474 | public void addArgument(String name, String value) { 475 | this.getArguments().addArgument(new HTTPArgument(name, value)); 476 | } 477 | 478 | public void addArgument(String name, String value, String metadata) { 479 | this.getArguments().addArgument(new HTTPArgument(name, value, metadata)); 480 | } 481 | 482 | public boolean hasArguments() { 483 | return getArguments().getArgumentCount() > 0; 484 | } 485 | 486 | @Override 487 | public void testStarted() { 488 | testStarted(""); 489 | } 490 | 491 | @Override 492 | public void testStarted(String host) { 493 | try { 494 | webSocketClientFactory.start(); 495 | } catch(Exception e) { 496 | log.error("Can't start WebSocketClientFactory", e); 497 | } 498 | } 499 | 500 | @Override 501 | public void testEnded() { 502 | testEnded(""); 503 | } 504 | 505 | @Override 506 | public void testEnded(String host) { 507 | try { 508 | for(WebSocket.Connection connection : samplerConnections) { 509 | connection.close(); 510 | } 511 | webSocketClientFactory.stop(); 512 | } catch (Exception e) { 513 | log.error("sampler error when close.", e); 514 | } 515 | } 516 | 517 | /** 518 | * @see org.apache.jmeter.samplers.AbstractSampler#applies(org.apache.jmeter.config.ConfigTestElement) 519 | */ 520 | @Override 521 | public boolean applies(ConfigTestElement configElement) { 522 | String guiClass = configElement.getProperty(TestElement.GUI_CLASS).getStringValue(); 523 | return APPLIABLE_CONFIG_CLASSES.contains(guiClass); 524 | } 525 | 526 | } 527 | -------------------------------------------------------------------------------- /src/main/resources/net/unit8/jmeter/protocol/websocket/sampler/WebSocketSamplerResources.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | displayName=WebSocket Sampler 17 | websocket_sample_title=WebSocket Sampler 18 | websocket_testing_title=WebSocket Sampler 19 | websocket_send_message=Send message 20 | websocket_recv_message=Received message 21 | -------------------------------------------------------------------------------- /src/main/resources/net/unit8/jmeter/protocol/websocket/sampler/WebSocketSamplerResources_ja.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | displayName=WebSocket Sampler 17 | websocket_testing_title=WebSocket\u30B5\u30F3\u30D7\u30E9 18 | websocket_send_message=\u9001\u4FE1\u30E1\u30C3\u30BB\u30FC\u30B8 19 | websocket_recv_message=\u53D7\u4FE1\u30E1\u30C3\u30BB\u30FC\u30B8 20 | websocket_sample_title=WebSocket\u30B5\u30F3\u30D7\u30E9\u30FC 21 | -------------------------------------------------------------------------------- /src/test/java/net/unit8/jmeter/protocol/websocket/sampler/WebSocketSamplerTest.java: -------------------------------------------------------------------------------- 1 | package net.unit8.jmeter.protocol.websocket.sampler; 2 | 3 | import net.unit8.jmeter.protocol.websocket.sampler.WebSocketSampler; 4 | import org.apache.jmeter.config.Arguments; 5 | import org.apache.jmeter.config.CSVDataSet; 6 | import org.apache.jmeter.control.LoopController; 7 | import org.apache.jmeter.control.OnceOnlyController; 8 | import org.apache.jmeter.control.ReplaceableController; 9 | import org.apache.jmeter.control.gui.TestPlanGui; 10 | import org.apache.jmeter.engine.JMeterEngine; 11 | import org.apache.jmeter.engine.StandardJMeterEngine; 12 | import org.apache.jmeter.gui.tree.JMeterTreeModel; 13 | import org.apache.jmeter.gui.tree.JMeterTreeNode; 14 | import org.apache.jmeter.reporters.ResultCollector; 15 | import org.apache.jmeter.reporters.Summariser; 16 | import org.apache.jmeter.testelement.TestElement; 17 | import org.apache.jmeter.testelement.TestPlan; 18 | import org.apache.jmeter.testelement.property.BooleanProperty; 19 | import org.apache.jmeter.testelement.property.StringProperty; 20 | import org.apache.jmeter.testelement.property.TestElementProperty; 21 | import org.apache.jmeter.threads.ThreadGroup; 22 | import org.apache.jmeter.timers.UniformRandomTimer; 23 | import org.apache.jmeter.util.JMeterUtils; 24 | import org.apache.jorphan.collections.HashTree; 25 | import org.apache.jorphan.collections.ListedHashTree; 26 | import org.apache.jorphan.logging.LoggingManager; 27 | import org.apache.jorphan.util.HeapDumper; 28 | import org.apache.log.Logger; 29 | 30 | import javax.xml.transform.Result; 31 | import java.net.DatagramPacket; 32 | import java.net.DatagramSocket; 33 | import java.net.InetAddress; 34 | import java.net.SocketException; 35 | import java.util.ArrayList; 36 | import java.util.LinkedList; 37 | import java.util.List; 38 | import java.util.Locale; 39 | 40 | /** 41 | * Tests of WebSocketSampler 42 | * 43 | * @author kawasima 44 | */ 45 | public class WebSocketSamplerTest { 46 | private static final Logger log = LoggingManager.getLoggerForClass(); 47 | 48 | public static void main(String[] args) throws Exception { 49 | JMeterUtils.setJMeterHome("src/test/resources/"); 50 | JMeterUtils.loadJMeterProperties("src/test/resources/jmeter.properties"); 51 | JMeterUtils.setProperty("saveservice_properties", "saveservice.properties"); 52 | JMeterUtils.setProperty("search_paths", "ApacheJMeter_functions-2.9.jar"); 53 | JMeterUtils.setLocale(Locale.JAPAN); 54 | 55 | JMeterEngine engine = new StandardJMeterEngine(); 56 | HashTree config = new ListedHashTree(); 57 | TestPlan testPlan = new TestPlan("websocket test"); 58 | testPlan.setFunctionalMode(false); 59 | testPlan.setSerialized(false); 60 | testPlan.setProperty(new BooleanProperty(TestElement.ENABLED, true)); 61 | testPlan.setUserDefinedVariables(new Arguments()); 62 | 63 | ThreadGroup threadGroup = new ThreadGroup(); 64 | threadGroup.setNumThreads(300); 65 | threadGroup.setRampUp(20); 66 | threadGroup.setDelay(0); 67 | threadGroup.setDuration(0); 68 | threadGroup.setProperty(new StringProperty(ThreadGroup.ON_SAMPLE_ERROR, "continue")); 69 | threadGroup.setScheduler(false); 70 | threadGroup.setName("Group1"); 71 | threadGroup.setProperty(new BooleanProperty(TestElement.ENABLED, true)); 72 | 73 | LoopController controller = new LoopController(); 74 | controller.setLoops(10); 75 | controller.setContinueForever(false); 76 | controller.setProperty(new BooleanProperty(TestElement.ENABLED, true)); 77 | threadGroup.setProperty(new TestElementProperty(ThreadGroup.MAIN_CONTROLLER, controller)); 78 | 79 | CSVDataSet csvDataSet = new CSVDataSet(); 80 | csvDataSet.setProperty(new StringProperty("filename", "src/test/resources/users.csv")); 81 | csvDataSet.setProperty(new StringProperty("variableNames", "USER_NAME")); 82 | csvDataSet.setProperty(new StringProperty("delimiter", ",")); 83 | csvDataSet.setProperty(new StringProperty("shareMode", "shareMode.all")); 84 | csvDataSet.setProperty("quoted", false); 85 | csvDataSet.setProperty("recycle", true); 86 | csvDataSet.setProperty("stopThread", false); 87 | 88 | WebSocketSampler sampler = new WebSocketSampler(); 89 | sampler.setName("WebSocket Test"); 90 | sampler.setProperty(new BooleanProperty(TestElement.ENABLED, true)); 91 | sampler.addNonEncodedArgument("name", "${USER_NAME}", "="); 92 | sampler.setContentEncoding("UTF-8"); 93 | sampler.setProtocol("ws"); 94 | sampler.setDomain("localhost"); 95 | sampler.setPort(9090); 96 | sampler.setPath("/", "UTF-8"); 97 | sampler.setSendMessage("${__RandomString(50,ABCDEFGHIJKLMNOPQRSTUVWXYZ)}"); 98 | sampler.setRecvMessage("\"name\":\"${USER_NAME}\""); 99 | 100 | OnceOnlyController onceOnlyController = new OnceOnlyController(); 101 | 102 | Summariser summariser = new Summariser(); 103 | 104 | HashTree tpConfig = config.add(testPlan); 105 | HashTree tgConfig = tpConfig.add(threadGroup); 106 | HashTree oocConfig = tgConfig.add(onceOnlyController); 107 | oocConfig.add(csvDataSet); 108 | 109 | UniformRandomTimer randomTimer = new UniformRandomTimer(); 110 | randomTimer.setRange(3000); 111 | HashTree samplerConfig = tgConfig.add(sampler); 112 | samplerConfig.add(summariser); 113 | tgConfig.add(randomTimer); 114 | 115 | engine.configure(config); 116 | engine.runTest(); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/test/resources/jmeter.properties: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Apache JMeter Property file 3 | ################################################################################ 4 | 5 | ## Licensed to the Apache Software Foundation (ASF) under one or more 6 | ## contributor license agreements. See the NOTICE file distributed with 7 | ## this work for additional information regarding copyright ownership. 8 | ## The ASF licenses this file to You under the Apache License, Version 2.0 9 | ## (the "License"); you may not use this file except in compliance with 10 | ## the License. You may obtain a copy of the License at 11 | ## 12 | ## http://www.apache.org/licenses/LICENSE-2.0 13 | ## 14 | ## Unless required by applicable law or agreed to in writing, software 15 | ## distributed under the License is distributed on an "AS IS" BASIS, 16 | ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | ## See the License for the specific language governing permissions and 18 | ## limitations under the License. 19 | 20 | 21 | #Preferred GUI language. Comment out to use the JVM default locale's language. 22 | #language=en 23 | 24 | # Additional locale(s) to add to the displayed list. 25 | # The current default list is: en, fr, de, no, es, tr, ja, zh_CN, zh_TW, pl, pt_BR 26 | # [see JMeterMenuBar#makeLanguageMenu()] 27 | # The entries are a comma-separated list of language names 28 | #locales.add=zu 29 | 30 | # Netscape HTTP Cookie file 31 | cookies=cookies 32 | 33 | #--------------------------------------------------------------------------- 34 | # File format configuration for JMX and JTL files 35 | #--------------------------------------------------------------------------- 36 | 37 | # Properties: 38 | # file_format - affects both JMX and JTL files 39 | # file_format.testplan - affects JMX files only 40 | # file_format.testlog - affects JTL files only 41 | # 42 | # Possible values are: 43 | # 2.1 - initial format using XStream 44 | # 2.2 - updated format using XStream, with shorter names 45 | 46 | # N.B. format 2.0 (Avalon) is no longer supported 47 | 48 | #--------------------------------------------------------------------------- 49 | # XML Parser 50 | #--------------------------------------------------------------------------- 51 | 52 | # XML Reader(Parser) - Must implement SAX 2 specs 53 | xml.parser=org.apache.xerces.parsers.SAXParser 54 | 55 | # Path to a Properties file containing Namespace mapping in the form 56 | # prefix=Namespace 57 | # Example: 58 | # ns=http://biz.aol.com/schema/2006-12-18 59 | #xpath.namespace.config= 60 | 61 | #--------------------------------------------------------------------------- 62 | # SSL configuration 63 | #--------------------------------------------------------------------------- 64 | 65 | ## SSL System properties are now in system.properties 66 | 67 | # JMeter no longer converts javax.xxx property entries in this file into System properties. 68 | # These must now be defined in the system.properties file or on the command-line. 69 | # The system.properties file gives more flexibility. 70 | 71 | # By default, SSL session contexts are now created per-thread, rather than being shared. 72 | # The original behaviour can be enabled by setting the JMeter property: 73 | #https.sessioncontext.shared=true 74 | 75 | # Default HTTPS protocol level: 76 | #https.default.protocol=TLS 77 | # This may need to be changed here (or in user.properties) to: 78 | #https.default.protocol=SSLv3 79 | 80 | # List of protocols to enable (unlikely to be needed): 81 | #https.socket.protocols=SSLv2Hello SSLv3 TLSv1 82 | 83 | # Control if we allow reuse of cached SSL context between iterations 84 | # set the value to 'false' to reset the SSL context each iteration 85 | #https.use.cached.ssl.context=true 86 | 87 | # Start and end index to be used with keystores with many entries 88 | # The default is to use entry 0, i.e. the first 89 | #https.keyStoreStartIndex=0 90 | #https.keyStoreEndIndex=0 91 | 92 | #--------------------------------------------------------------------------- 93 | # Look and Feel configuration 94 | #--------------------------------------------------------------------------- 95 | 96 | #Classname of the Swing default UI 97 | # 98 | # The LAF classnames that are available are now displayed as ToolTip text 99 | # when hovering over the Options/Look and Feel selection list. 100 | # 101 | # You can either use a full class name, as shown above, 102 | # or one of the strings "System" or "CrossPlatform" which means 103 | # JMeter will use the corresponding string returned by UIManager.getLookAndFeelClassName() 104 | 105 | # LAF can be overridden by os.name (lowercased, spaces replaced by '_') 106 | # Sample os.name LAF: 107 | #jmeter.laf.windows_xp=javax.swing.plaf.metal.MetalLookAndFeel 108 | 109 | # Failing that, the OS family = os.name, but only up to first space: 110 | # Sample OS family LAF: 111 | #jmeter.laf.windows=com.sun.java.swing.plaf.windows.WindowsLookAndFeel 112 | 113 | # Mac apparently looks better with the System LAF 114 | jmeter.laf.mac=System 115 | 116 | # Failing that, the JMeter default laf can be defined: 117 | #jmeter.laf=System 118 | 119 | # If none of the above jmeter.laf properties are defined, JMeter uses the CrossPlatform LAF. 120 | # This is because the CrossPlatform LAF generally looks better than the System LAF. 121 | # See https://issues.apache.org/bugzilla/show_bug.cgi?id=52026 for details 122 | # N.B. the laf can be defined in user.properties. 123 | 124 | # LoggerPanel display 125 | # default to false 126 | #jmeter.loggerpanel.display=false 127 | 128 | # Error/Fatal Log count display 129 | # defaults to true 130 | #jmeter.errorscounter.display=true 131 | 132 | # Max characters kept in LoggerPanel, default to 80000 chars 133 | # O means no limit 134 | #jmeter.loggerpanel.maxlength=80000 135 | 136 | # Toolbar display 137 | # default: 138 | #jmeter.toolbar.display=true 139 | # Toolbar icon definitions 140 | #jmeter.toolbar.icons=org/apache/jmeter/images/toolbar/icons-toolbar.properties 141 | # Toolbar list 142 | #jmeter.toolbar=new,open,close,save,save_as_testplan,|,cut,copy,paste,|,expand,collapse,toggle,|,test_start,test_stop,test_shutdown,|,test_start_remote_all,test_stop_remote_all,test_shutdown_remote_all,|,test_clear,test_clear_all,|,search,search_reset,|,function_helper,help 143 | 144 | # Icon definitions 145 | # default: 146 | #jmeter.icons=org/apache/jmeter/images/icon.properties 147 | # alternate: 148 | #jmeter.icons=org/apache/jmeter/images/icon_1.properties 149 | 150 | #Components to not display in JMeter GUI (GUI class name or static label) 151 | # These elements are deprecated: HTML Parameter Mask,HTTP User Parameter Modifier 152 | not_in_menu=HTML Parameter Mask,HTTP User Parameter Modifier 153 | 154 | #--------------------------------------------------------------------------- 155 | # Remote hosts and RMI configuration 156 | #--------------------------------------------------------------------------- 157 | 158 | # Remote Hosts - comma delimited 159 | remote_hosts=127.0.0.1 160 | #remote_hosts=localhost:1099,localhost:2010 161 | 162 | # RMI port to be used by the server (must start rmiregistry with same port) 163 | #server_port=1099 164 | 165 | # To change the port to (say) 1234: 166 | # On the server(s) 167 | # - set server_port=1234 168 | # - start rmiregistry with port 1234 169 | # On Windows this can be done by: 170 | # SET SERVER_PORT=1234 171 | # JMETER-SERVER 172 | # 173 | # On Unix: 174 | # SERVER_PORT=1234 jmeter-server 175 | # 176 | # On the client: 177 | # - set remote_hosts=server:1234 178 | 179 | # Parameter that controls the RMI port used by the RemoteSampleListenerImpl 180 | # Default value is 0 which means port is randomly assigned 181 | #client.rmi.localport=0 182 | 183 | # To change the default port (1099) used to access the server: 184 | #server.rmi.port=1234 185 | 186 | # To use a specific port for the JMeter server engine, define 187 | # the following property before starting the server: 188 | #server.rmi.localport=4000 189 | 190 | # From JMeter 2.3.1, the jmeter server creates the RMI registry as part of the server process. 191 | # To stop the server creating the RMI registry: 192 | #server.rmi.create=false 193 | 194 | # From JMeter 2.3.1, define the following property to cause JMeter to exit after the first test 195 | #server.exitaftertest=true 196 | 197 | # Prefix used by IncludeController when building file name 198 | #includecontroller.prefix= 199 | 200 | #--------------------------------------------------------------------------- 201 | # Logging Configuration 202 | #--------------------------------------------------------------------------- 203 | 204 | # Note: JMeter uses Avalon (Excalibur) LogKit 205 | 206 | # Logging Format 207 | # see http://excalibur.apache.org/apidocs/org/apache/log/format/PatternFormatter.html 208 | 209 | # 210 | # Default format: 211 | #log_format=%{time:yyyy/MM/dd HH:mm:ss} %5.5{priority} - %{category}: %{message} %{throwable} 212 | # \n is automatically added to the end of the string 213 | # 214 | # Predefined formats in the JMeter LoggingManager: 215 | #log_format_type=default 216 | #log_format_type=thread_prefix 217 | #log_format_type=thread_suffix 218 | # default is as above 219 | # thread_prefix adds the thread name as a prefix to the category 220 | # thread_suffix adds the thread name as a suffix to the category 221 | # Note that thread name is not included by default, as it requires extra processing. 222 | # 223 | # To change the logging format, define either log_format_type or log_format 224 | # If both are defined, the type takes precedence 225 | # Note that these properties cannot be defined using the -J or -D JMeter 226 | # command-line flags, as the format will have already been determined by then 227 | # However, they can be defined as JVM properties 228 | 229 | #Logging levels for the logging categories in JMeter. Correct values are FATAL_ERROR, ERROR, WARN, INFO, and DEBUG 230 | # To set the log level for a package or individual class, use: 231 | # log_level.[package_name].[classname]=[PRIORITY_LEVEL] 232 | # But omit "org.apache" from the package name. The classname is optional. Further examples below. 233 | 234 | log_level.jmeter=INFO 235 | log_level.jmeter.junit=DEBUG 236 | #log_level.jmeter.control=DEBUG 237 | #log_level.jmeter.testbeans=DEBUG 238 | #log_level.jmeter.engine=DEBUG 239 | #log_level.jmeter.threads=DEBUG 240 | #log_level.jmeter.gui=WARN 241 | #log_level.jmeter.testelement=DEBUG 242 | #log_level.jmeter.util=WARN 243 | #log_level.jmeter.util.classfinder=WARN 244 | #log_level.jmeter.test=DEBUG 245 | #log_level.jmeter.protocol.http=DEBUG 246 | # For CookieManager, AuthManager etc: 247 | #log_level.jmeter.protocol.http.control=DEBUG 248 | #log_level.jmeter.protocol.ftp=WARN 249 | #log_level.jmeter.protocol.jdbc=DEBUG 250 | #log_level.jmeter.protocol.java=WARN 251 | #log_level.jmeter.testelements.property=DEBUG 252 | log_level.jorphan=INFO 253 | 254 | 255 | #Log file for log messages. 256 | # You can specify a different log file for different categories via: 257 | # log_file.[category]=[filename] 258 | # category is equivalent to the package/class names described above 259 | 260 | # Combined log file (for jmeter and jorphan) 261 | #log_file=jmeter.log 262 | # To redirect logging to standard output, try the following: 263 | # (it will probably report an error, but output will be to stdout) 264 | #log_file= 265 | 266 | # Or define separate logs if required: 267 | #log_file.jorphan=jorphan.log 268 | #log_file.jmeter=jmeter.log 269 | 270 | # If the filename contains paired single-quotes, then the name is processed 271 | # as a SimpleDateFormat format applied to the current date, for example: 272 | #log_file='jmeter_'yyyyMMddHHmmss'.tmp' 273 | 274 | # N.B. When JMeter starts, it sets the system property: 275 | # org.apache.commons.logging.Log 276 | # to 277 | # org.apache.commons.logging.impl.LogKitLogger 278 | # if not already set. This causes Apache and Commons HttpClient to use the same logging as JMeter 279 | 280 | # Further logging configuration 281 | # Excalibur logging provides the facility to configure logging using 282 | # configuration files written in XML. This allows for such features as 283 | # log file rotation which are not supported directly by JMeter. 284 | # 285 | # If such a file specified, it will be applied to the current logging 286 | # hierarchy when that has been created. 287 | # 288 | #log_config=logkit.xml 289 | 290 | #--------------------------------------------------------------------------- 291 | # HTTP Java configuration 292 | #--------------------------------------------------------------------------- 293 | 294 | # Number of connection retries performed by HTTP Java sampler before giving up 295 | #http.java.sampler.retries=10 296 | # 0 now means don't retry connection (in 2.3 and before it meant no tries at all!) 297 | 298 | #--------------------------------------------------------------------------- 299 | # Commons HTTPClient configuration 300 | #--------------------------------------------------------------------------- 301 | 302 | # define a properties file for overriding Commons HttpClient parameters 303 | # See: http://hc.apache.org/httpclient-3.x/preference-api.html 304 | #httpclient.parameters.file=httpclient.parameters 305 | 306 | 307 | # define a properties file for overriding Apache HttpClient parameters 308 | # See: TBA 309 | #hc.parameters.file=hc.parameters 310 | 311 | # Following properties apply to both Commons and Apache HttpClient 312 | 313 | # set the socket timeout (or use the parameter http.socket.timeout) 314 | # Value is in milliseconds 315 | #httpclient.timeout=0 316 | # 0 == no timeout 317 | 318 | # Set the http version (defaults to 1.1) 319 | #httpclient.version=1.0 (or use the parameter http.protocol.version) 320 | 321 | # Define characters per second > 0 to emulate slow connections 322 | #httpclient.socket.http.cps=0 323 | #httpclient.socket.https.cps=0 324 | 325 | #Enable loopback protocol 326 | #httpclient.loopback=true 327 | 328 | # Define the local host address to be used for multi-homed hosts 329 | #httpclient.localaddress=1.2.3.4 330 | 331 | # Sample logging levels for Commons HttpClient 332 | # 333 | # Commons HttpClient Logging information can be found at: 334 | # http://hc.apache.org/httpclient-3.x/logging.html 335 | 336 | # Note that full category names are used, i.e. must include the org.apache. 337 | # Info level produces no output: 338 | #log_level.org.apache.commons.httpclient=debug 339 | # Might be useful: 340 | #log_level.org.apache.commons.httpclient.Authenticator=trace 341 | 342 | # Show headers only 343 | #log_level.httpclient.wire.header=debug 344 | 345 | # Full wire debug produces a lot of output; consider using separate file: 346 | #log_level.httpclient.wire=debug 347 | #log_file.httpclient=httpclient.log 348 | 349 | 350 | # Apache Commons HttpClient logging examples 351 | # 352 | # Enable header wire + context logging - Best for Debugging 353 | #log_level.org.apache.http=DEBUG 354 | #log_level.org.apache.http.wire=ERROR 355 | 356 | # Enable full wire + context logging 357 | #log_level.org.apache.http=DEBUG 358 | 359 | # Enable context logging for connection management 360 | #log_level.org.apache.http.impl.conn=DEBUG 361 | 362 | # Enable context logging for connection management / request execution 363 | #log_level.org.apache.http.impl.conn=DEBUG 364 | #log_level.org.apache.http.impl.client=DEBUG 365 | #log_level.org.apache.http.client=DEBUG 366 | 367 | #--------------------------------------------------------------------------- 368 | # Apache HttpComponents HTTPClient configuration (HTTPClient4) 369 | #--------------------------------------------------------------------------- 370 | 371 | # Number of retries to attempt (default 1) 372 | #httpclient4.retrycount=1 373 | 374 | # Number of retries to attempt (default 1) 375 | #httpclient3.retrycount=1 376 | 377 | #--------------------------------------------------------------------------- 378 | # Results file configuration 379 | #--------------------------------------------------------------------------- 380 | 381 | # This section helps determine how result data will be saved. 382 | # The commented out values are the defaults. 383 | 384 | # legitimate values: xml, csv, db. Only xml and csv are currently supported. 385 | #jmeter.save.saveservice.output_format=csv 386 | 387 | 388 | # true when field should be saved; false otherwise 389 | 390 | # assertion_results_failure_message only affects CSV output 391 | #jmeter.save.saveservice.assertion_results_failure_message=false 392 | # 393 | # legitimate values: none, first, all 394 | #jmeter.save.saveservice.assertion_results=none 395 | # 396 | #jmeter.save.saveservice.data_type=true 397 | #jmeter.save.saveservice.label=true 398 | #jmeter.save.saveservice.response_code=true 399 | # response_data is not currently supported for CSV output 400 | #jmeter.save.saveservice.response_data=false 401 | # Save ResponseData for failed samples 402 | #jmeter.save.saveservice.response_data.on_error=false 403 | #jmeter.save.saveservice.response_message=true 404 | #jmeter.save.saveservice.successful=true 405 | #jmeter.save.saveservice.thread_name=true 406 | #jmeter.save.saveservice.time=true 407 | #jmeter.save.saveservice.subresults=true 408 | #jmeter.save.saveservice.assertions=true 409 | #jmeter.save.saveservice.latency=true 410 | #jmeter.save.saveservice.samplerData=false 411 | #jmeter.save.saveservice.responseHeaders=false 412 | #jmeter.save.saveservice.requestHeaders=false 413 | #jmeter.save.saveservice.encoding=false 414 | #jmeter.save.saveservice.bytes=true 415 | #jmeter.save.saveservice.url=false 416 | #jmeter.save.saveservice.filename=false 417 | #jmeter.save.saveservice.hostname=false 418 | #jmeter.save.saveservice.thread_counts=false 419 | #jmeter.save.saveservice.sample_count=false 420 | #jmeter.save.saveservice.idle_time=false 421 | 422 | # Timestamp format - this only affects CSV output files 423 | # legitimate values: none, ms, or a format suitable for SimpleDateFormat 424 | #jmeter.save.saveservice.timestamp_format=ms 425 | #jmeter.save.saveservice.timestamp_format=yyyy/MM/dd HH:mm:ss.SSS 426 | 427 | # For use with Comma-separated value (CSV) files or other formats 428 | # where the fields' values are separated by specified delimiters. 429 | # Default: 430 | #jmeter.save.saveservice.default_delimiter=, 431 | # For TAB, since JMeter 2.3 one can use: 432 | #jmeter.save.saveservice.default_delimiter=\t 433 | 434 | # Only applies to CSV format files: 435 | #jmeter.save.saveservice.print_field_names=false 436 | 437 | # Optional list of JMeter variable names whose values are to be saved in the result data files. 438 | # Use commas to separate the names. For example: 439 | #sample_variables=SESSION_ID,REFERENCE 440 | # N.B. The current implementation saves the values in XML as attributes, 441 | # so the names must be valid XML names. 442 | # Versions of JMeter after 2.3.2 send the variable to all servers 443 | # to ensure that the correct data is available at the client. 444 | 445 | # Optional xml processing instruction for line 2 of the file: 446 | #jmeter.save.saveservice.xml_pi= 447 | 448 | # Prefix used to identify filenames that are relative to the current base 449 | #jmeter.save.saveservice.base_prefix=~/ 450 | 451 | #--------------------------------------------------------------------------- 452 | # Settings that affect SampleResults 453 | #--------------------------------------------------------------------------- 454 | 455 | # Save the start time stamp instead of the end 456 | # This also affects the timestamp stored in result files 457 | sampleresult.timestamp.start=true 458 | 459 | # Whether to use System.nanoTime() - otherwise only use System.currentTimeMillis() 460 | #sampleresult.useNanoTime=true 461 | 462 | # Use a background thread to calculate the nanoTime offset 463 | # Set this to <= 0 to disable the background thread 464 | #sampleresult.nanoThreadSleep=5000 465 | 466 | #--------------------------------------------------------------------------- 467 | # Upgrade property 468 | #--------------------------------------------------------------------------- 469 | 470 | # File that holds a record of name changes for backward compatibility issues 471 | upgrade_properties=/bin/upgrade.properties 472 | 473 | #--------------------------------------------------------------------------- 474 | # JMeter Proxy recorder configuration 475 | #--------------------------------------------------------------------------- 476 | 477 | # If the proxy detects a gap of at least 1s (default) between HTTP requests, 478 | # it assumes that the user has clicked a new URL 479 | #proxy.pause=1000 480 | 481 | # Add numeric prefix to Sampler names (default false) 482 | #proxy.number.requests=true 483 | 484 | # List of URL patterns that will be added to URL Patterns to exclude in Proxy 485 | #proxy.excludes.suggested=.*\\.js;.*\\.css;.*\\.swf;.*\\.gif;.*\\.png;.*\\.jpg;.*\\.bmp 486 | 487 | # Change the default HTTP Sampler (currently HttpClient4) 488 | # Java: 489 | #jmeter.httpsampler=HTTPSampler 490 | #or 491 | #jmeter.httpsampler=Java 492 | # 493 | # Apache HTTPClient: 494 | #jmeter.httpsampler=HTTPSampler2 495 | #or 496 | #jmeter.httpsampler=HttpClient3.1 497 | # 498 | # HttpClient4.x 499 | #jmeter.httpsampler=HttpClient4 500 | 501 | # Default content-type include filter to use 502 | #proxy.content_type_include=text/html|text/plain|text/xml 503 | # Default content-type exclude filter to use 504 | #proxy.content_type_exclude=image/.*|text/css|application/.* 505 | 506 | # Default headers to remove from Header Manager elements 507 | # (Cookie and Authorization are always removed) 508 | #proxy.headers.remove=If-Modified-Since,If-None-Match,Host 509 | 510 | # Binary content-type handling 511 | # These content-types will be handled by saving the request in a file: 512 | #proxy.binary.types=application/x-amf,application/x-java-serialized-object 513 | # The files will be saved in this directory: 514 | #proxy.binary.directory=user.dir 515 | # The files will be created with this file filesuffix: 516 | #proxy.binary.filesuffix=.binary 517 | 518 | #--------------------------------------------------------------------------- 519 | # JMeter Proxy configuration 520 | #--------------------------------------------------------------------------- 521 | # use command-line flags for user-name and password 522 | #http.proxyDomain=NTLM domain, if required by HTTPClient sampler 523 | 524 | # SSL configuration 525 | #proxy.cert.directory=. 526 | #proxy.cert.file=proxyserver.jks 527 | #proxy.cert.type=JKS 528 | #proxy.cert.keystorepass=password 529 | #proxy.cert.keypassword=password 530 | #proxy.cert.factory=SunX509 531 | #proxy.ssl.protocol=SSLv3 532 | 533 | #--------------------------------------------------------------------------- 534 | # HTTPSampleResponse Parser configuration 535 | #--------------------------------------------------------------------------- 536 | 537 | # Space-separated list of parser groups 538 | HTTPResponse.parsers=htmlParser wmlParser 539 | # for each parser, there should be a parser.types and a parser.className property 540 | 541 | #--------------------------------------------------------------------------- 542 | # HTML Parser configuration 543 | #--------------------------------------------------------------------------- 544 | 545 | # Define the HTML parser to be used. 546 | # Default parser: 547 | #htmlParser.className=org.apache.jmeter.protocol.http.parser.HtmlParserHTMLParser 548 | # Other parsers: 549 | #htmlParser.className=org.apache.jmeter.protocol.http.parser.JTidyHTMLParser 550 | #htmlParser.className=org.apache.jmeter.protocol.http.parser.RegexpHTMLParser 551 | # 552 | 553 | htmlParser.types=text/html application/xhtml+xml application/xml text/xml 554 | 555 | #--------------------------------------------------------------------------- 556 | # WML Parser configuration 557 | #--------------------------------------------------------------------------- 558 | 559 | wmlParser.className=org.apache.jmeter.protocol.http.parser.RegexpHTMLParser 560 | 561 | wmlParser.types=text/vnd.wap.wml 562 | 563 | #--------------------------------------------------------------------------- 564 | # Remote batching configuration 565 | #--------------------------------------------------------------------------- 566 | # How is Sample sender implementations configured: 567 | # - true (default) means client configuration will be used 568 | # - false means server configuration will be used 569 | #sample_sender_client_configured=true 570 | 571 | # Remote batching support 572 | # Since JMeter 2.9, default is MODE_STRIPPED_BATCH, which returns samples in 573 | # batch mode (every 100 samples or every minute by default) 574 | # Note also that MODE_STRIPPED_BATCH strips response data from SampleResult, so if you need it change to 575 | # another mode 576 | # Hold retains samples until end of test (may need lots of memory) 577 | # Batch returns samples in batches 578 | # Statistical returns sample summary statistics 579 | # hold_samples was originally defined as a separate property, 580 | # but can now also be defined using mode=Hold 581 | # mode can also be the class name of an implementation of org.apache.jmeter.samplers.SampleSender 582 | #mode=Standard 583 | #mode=Batch 584 | #mode=Hold 585 | #mode=Statistical 586 | #Set to true to key statistical samples on threadName rather than threadGroup 587 | #key_on_threadname=false 588 | #mode=Stripped 589 | #mode=StrippedBatch 590 | #mode=org.example.load.MySampleSender 591 | #hold_samples=true 592 | # 593 | #num_sample_threshold=100 594 | # Value is in milliseconds 595 | #time_threshold=60000 596 | # 597 | # Asynchronous sender; uses a queue and background worker process to return the samples 598 | #mode=Asynch 599 | # default queue size 600 | #asynch.batch.queue.size=100 601 | # 602 | # DiskStore: as for Hold mode, but serialises the samples to disk, rather than saving in memory 603 | #mode=DiskStore 604 | 605 | # Note: the mode is currently resolved on the client; 606 | # other properties (e.g. time_threshold) are resolved on the server. 607 | 608 | # To set the Monitor Health Visualiser buffer size, enter the desired value 609 | # monitor.buffer.size=800 610 | 611 | #--------------------------------------------------------------------------- 612 | # TCP Sampler configuration 613 | #--------------------------------------------------------------------------- 614 | 615 | # The default handler class 616 | #tcp.handler=TCPClientImpl 617 | # 618 | # eolByte = byte value for end of line 619 | # set this to a value outside the range -128 to +127 to skip eol checking 620 | #tcp.eolByte=1000 621 | # 622 | # TCP Charset, used by org.apache.jmeter.protocol.tcp.sampler.TCPClientImpl 623 | # default to Platform defaults charset as returned by Charset.defaultCharset().name() 624 | #tcp.charset= 625 | # 626 | # status.prefix and suffix = strings that enclose the status response code 627 | #tcp.status.prefix=Status= 628 | #tcp.status.suffix=. 629 | # 630 | # status.properties = property file to convert codes to messages 631 | #tcp.status.properties=mytestfiles/tcpstatus.properties 632 | 633 | # The length prefix used by LengthPrefixedBinaryTCPClientImpl implementation 634 | # defaults to 2 bytes. 635 | #tcp.binarylength.prefix.length=2 636 | 637 | #--------------------------------------------------------------------------- 638 | # Summariser - Generate Summary Results - configuration (mainly applies to non-GUI mode) 639 | #--------------------------------------------------------------------------- 640 | # 641 | # Define the following property to automatically start a summariser with that name 642 | # (applies to non-GUI mode only) 643 | #summariser.name=summary 644 | # 645 | # interval between summaries (in seconds) default 3 minutes 646 | #summariser.interval=180 647 | # 648 | # Write messages to log file 649 | #summariser.log=true 650 | # 651 | # Write messages to System.out 652 | #summariser.out=true 653 | 654 | #--------------------------------------------------------------------------- 655 | # BeanShell configuration 656 | #--------------------------------------------------------------------------- 657 | 658 | # BeanShell Server properties 659 | # 660 | # Define the port number as non-zero to start the http server on that port 661 | #beanshell.server.port=9000 662 | # The telnet server will be started on the next port 663 | 664 | # 665 | # Define the server initialisation file 666 | beanshell.server.file=../extras/startup.bsh 667 | 668 | # 669 | # Define a file to be processed at startup 670 | # This is processed using its own interpreter. 671 | #beanshell.init.file= 672 | 673 | # 674 | # Define the intialisation files for BeanShell Sampler, Function and other BeanShell elements 675 | # N.B. Beanshell test elements do not share interpreters. 676 | # Each element in each thread has its own interpreter. 677 | # This is retained between samples. 678 | #beanshell.sampler.init=BeanShellSampler.bshrc 679 | #beanshell.function.init=BeanShellFunction.bshrc 680 | #beanshell.assertion.init=BeanShellAssertion.bshrc 681 | #beanshell.listener.init=etc 682 | #beanshell.postprocessor.init=etc 683 | #beanshell.preprocessor.init=etc 684 | #beanshell.timer.init=etc 685 | 686 | # The file BeanShellListeners.bshrc contains sample definitions 687 | # of Test and Thread Listeners. 688 | 689 | #--------------------------------------------------------------------------- 690 | # MailerModel configuration 691 | #--------------------------------------------------------------------------- 692 | 693 | # Number of successful samples before a message is sent 694 | #mailer.successlimit=2 695 | # 696 | # Number of failed samples before a message is sent 697 | #mailer.failurelimit=2 698 | 699 | #--------------------------------------------------------------------------- 700 | # CSVRead configuration 701 | #--------------------------------------------------------------------------- 702 | 703 | # CSVRead delimiter setting (default ",") 704 | # Make sure that there are no trailing spaces or tabs after the delimiter 705 | # characters, or these will be included in the list of valid delimiters 706 | #csvread.delimiter=, 707 | #csvread.delimiter=; 708 | #csvread.delimiter=! 709 | #csvread.delimiter=~ 710 | # The following line has a tab after the = 711 | #csvread.delimiter= 712 | 713 | #--------------------------------------------------------------------------- 714 | # __time() function configuration 715 | # 716 | # The properties below can be used to redefine the default formats 717 | #--------------------------------------------------------------------------- 718 | #time.YMD=yyyyMMdd 719 | #time.HMS=HHmmss 720 | #time.YMDHMS=yyyyMMdd-HHmmss 721 | #time.USER1= 722 | #time.USER2= 723 | 724 | #--------------------------------------------------------------------------- 725 | # CSV DataSet configuration 726 | #--------------------------------------------------------------------------- 727 | 728 | # String to return at EOF (if recycle not used) 729 | #csvdataset.eofstring= 730 | 731 | #--------------------------------------------------------------------------- 732 | # LDAP Sampler configuration 733 | #--------------------------------------------------------------------------- 734 | # Maximum number of search results returned by a search that will be sorted 735 | # to guarantee a stable ordering (if more results then this limit are retruned 736 | # then no sorting is done). Set to 0 to turn off all sorting, in which case 737 | # "Equals" response assertions will be very likely to fail against search results. 738 | # 739 | #ldapsampler.max_sorted_results=1000 740 | 741 | # Number of characters to log for each of three sections (starting matching section, diff section, 742 | # ending matching section where not all sections will appear for all diffs) diff display when an Equals 743 | # assertion fails. So a value of 100 means a maximum of 300 characters of diff text will be displayed 744 | # (+ a number of extra characters like "..." and "[[["/"]]]" which are used to decorate it). 745 | #assertion.equals_section_diff_len=100 746 | # test written out to log to signify start/end of diff delta 747 | #assertion.equals_diff_delta_start=[[[ 748 | #assertion.equals_diff_delta_end=]]] 749 | 750 | #--------------------------------------------------------------------------- 751 | # Miscellaneous configuration 752 | #--------------------------------------------------------------------------- 753 | 754 | # If defined, then start the mirror server on the port 755 | #mirror.server.port=8081 756 | 757 | # ORO PatternCacheLRU size 758 | #oro.patterncache.size=1000 759 | 760 | #TestBeanGui 761 | # 762 | #propertyEditorSearchPath=null 763 | 764 | # Turn expert mode on/off: expert mode will show expert-mode beans and properties 765 | #jmeter.expertMode=true 766 | 767 | # Maximum redirects to follow in a single sequence (default 5) 768 | #httpsampler.max_redirects=5 769 | # Maximum frame/iframe nesting depth (default 5) 770 | #httpsampler.max_frame_depth=5 771 | # Maximum await termination timeout (secs) when concurrent download embedded resources (default 60) 772 | #httpsampler.await_termination_timeout=60 773 | # Revert to BUG 51939 behaviour (no separate container for embedded resources) by setting the following false: 774 | #httpsampler.separate.container=true 775 | 776 | # If embedded resources download fails due to missing resources or other reasons, if this property is true 777 | # Parent sample will not be marked as failed 778 | #httpsampler.ignore_failed_embedded_resources=false 779 | 780 | # The encoding to be used if none is provided (default ISO-8859-1) 781 | #sampleresult.default.encoding=ISO-8859-1 782 | 783 | # Network response size calculation method 784 | # Use real size: number of bytes for response body return by webserver 785 | # (i.e. the network bytes received for response) 786 | # if set to false, the (uncompressed) response data size will used (default before 2.5) 787 | # Include headers: add the headers size in real size 788 | #sampleresult.getbytes.body_real_size=true 789 | #sampleresult.getbytes.headers_size=true 790 | 791 | # CookieManager behaviour - should cookies with null/empty values be deleted? 792 | # Default is true. Use false to revert to original behaviour 793 | #CookieManager.delete_null_cookies=true 794 | 795 | # CookieManager behaviour - should variable cookies be allowed? 796 | # Default is true. Use false to revert to original behaviour 797 | #CookieManager.allow_variable_cookies=true 798 | 799 | # CookieManager behaviour - should Cookies be stored as variables? 800 | # Default is false 801 | #CookieManager.save.cookies=false 802 | 803 | # CookieManager behaviour - prefix to add to cookie name before storing it as a variable 804 | # Default is COOKIE_; to remove the prefix, define it as one or more spaces 805 | #CookieManager.name.prefix= 806 | 807 | # CookieManager behaviour - check received cookies are valid before storing them? 808 | # Default is true. Use false to revert to previous behaviour 809 | #CookieManager.check.cookies=true 810 | 811 | # (2.0.3) JMeterThread behaviour has been changed to set the started flag before 812 | # the controllers are initialised. This is so controllers can access variables earlier. 813 | # In case this causes problems, the previous behaviour can be restored by uncommenting 814 | # the following line. 815 | #jmeterthread.startearlier=false 816 | 817 | # (2.2.1) JMeterThread behaviour has changed so that PostProcessors are run in forward order 818 | # (as they appear in the test plan) rather than reverse order as previously. 819 | # Uncomment the following line to revert to the original behaviour 820 | #jmeterthread.reversePostProcessors=true 821 | 822 | # (2.2) StandardJMeterEngine behaviour has been changed to notify the listeners after 823 | # the running version is enabled. This is so they can access variables. 824 | # In case this causes problems, the previous behaviour can be restored by uncommenting 825 | # the following line. 826 | #jmeterengine.startlistenerslater=false 827 | 828 | # Number of milliseconds to wait for a thread to stop 829 | #jmeterengine.threadstop.wait=5000 830 | 831 | #Whether to invoke System.exit(0) in server exit code after stopping RMI 832 | #jmeterengine.remote.system.exit=false 833 | 834 | # Whether to call System.exit(1) on failure to stop threads in non-GUI mode. 835 | # If this is disabled, it may be necessary to kill the JVM externally 836 | #jmeterengine.stopfail.system.exit=true 837 | 838 | # How long to pause (in ms) in the daemon thread before reporting that the JVM has failed to exit. 839 | # If the value is <= 0, the JMeter does not start the daemon thread 840 | #jmeter.exit.check.pause=2000 841 | 842 | # If running non-GUI, then JMeter listens on the following port for a shutdown message. 843 | # To disable, set the port to 1000 or less. 844 | #jmeterengine.nongui.port=4445 845 | # 846 | # If the initial port is busy, keep trying until this port is reached 847 | # (to disable searching, set the value less than or equal to the .port property) 848 | #jmeterengine.nongui.maxport=4455 849 | 850 | # How often to check for shutdown during ramp-up (milliseconds) 851 | #jmeterthread.rampup.granularity=1000 852 | 853 | #Should JMeter expand the tree when loading a test plan? 854 | # default value is false since JMeter 2.7 855 | #onload.expandtree=false 856 | 857 | # Maximum size of HTML page that can be displayed; default=200 * 1024 858 | # Set to 0 to disable the size check 859 | #view.results.tree.max_size=0 860 | 861 | # Maximum size of Document that can be parsed by Tika engine; defaut=10 * 1024 * 1024 (10MB) 862 | # Set to 0 to disable the size check 863 | #document.max_size=0 864 | 865 | #JMS options 866 | # Enable the following property to stop JMS Point-to-Point Sampler from using 867 | # the properties java.naming.security.[principal|credentials] when creating the queue connection 868 | #JMSSampler.useSecurity.properties=false 869 | 870 | # Set the following value to true in order to skip the delete confirmation dialogue 871 | #confirm.delete.skip=false 872 | 873 | # Used by Webservice Sampler (SOAP) 874 | # Size of Document Cache 875 | #soap.document_cache=50 876 | 877 | # Used by JSR223 elements 878 | # Size of compiled scripts cache 879 | #jsr223.compiled_scripts_cache_size=100 880 | 881 | #--------------------------------------------------------------------------- 882 | # Classpath configuration 883 | #--------------------------------------------------------------------------- 884 | 885 | # List of paths (separated by ;) to search for additional JMeter extension classes 886 | # - for example new GUI elements and samplers 887 | # These are in addition to lib/ext. Do not use this for utility jars. 888 | #search_paths=/app1/lib;/app2/lib 889 | 890 | # Users can define additional classpath items by setting the property below 891 | # - for example, utility jars or JUnit test cases 892 | # 893 | # Use the default separator for the host version of Java 894 | # Paths with spaces may cause problems for the JVM 895 | #user.classpath=../classes;../jars/jar1.jar 896 | 897 | # Classpath finder 898 | # ================ 899 | # The classpath finder currently needs to load every single JMeter class to find 900 | # the classes it needs. 901 | # For non-GUI mode, it's only necessary to scan for Function classes, but all classes 902 | # are still loaded. 903 | # All current Function classes include ".function." in their name, 904 | # and none include ".gui." in the name, so the number of unwanted classes loaded can be 905 | # reduced by checking for these. However, if a valid function class name does not match 906 | # these restrictions, it will not be loaded. If problems are encountered, then comment 907 | # or change the following properties: 908 | classfinder.functions.contain=.functions. 909 | classfinder.functions.notContain=.gui. 910 | 911 | #--------------------------------------------------------------------------- 912 | # Additional property files to load 913 | #--------------------------------------------------------------------------- 914 | 915 | # Should JMeter automatically load additional JMeter properties? 916 | # File name to look for (comment to disable) 917 | user.properties=user.properties 918 | 919 | # Should JMeter automatically load additional system properties? 920 | # File name to look for (comment to disable) 921 | system.properties=system.properties -------------------------------------------------------------------------------- /src/test/resources/saveservice.properties: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------- 2 | # SAVESERVICE PROPERTIES 3 | #--------------------------------------------------------- 4 | 5 | ## Licensed to the Apache Software Foundation (ASF) under one or more 6 | ## contributor license agreements. See the NOTICE file distributed with 7 | ## this work for additional information regarding copyright ownership. 8 | ## The ASF licenses this file to You under the Apache License, Version 2.0 9 | ## (the "License"); you may not use this file except in compliance with 10 | ## the License. You may obtain a copy of the License at 11 | ## 12 | ## http://www.apache.org/licenses/LICENSE-2.0 13 | ## 14 | ## Unless required by applicable law or agreed to in writing, software 15 | ## distributed under the License is distributed on an "AS IS" BASIS, 16 | ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | ## See the License for the specific language governing permissions and 18 | ## limitations under the License. 19 | 20 | #--------------------------------------------------------- 21 | 22 | # N.B. To ensure backward compatibility, please do NOT change or delete any entries 23 | 24 | # New entries can be added as necessary. 25 | # 26 | # Note that keys starting with an underscore are special, 27 | # and are not used as aliases. 28 | # 29 | # Please keep the entries in alphabetical order within the sections 30 | # to reduce the likelihood of duplicates 31 | # 32 | # version number of this file (automatically generated by SVN) 33 | _file_version=$Revision: 1427507 $ 34 | # 35 | # Conversion version (for JMX output files) 36 | # Must be updated if the file has been changed since the previous release 37 | # 38 | # 1.7 = 2.1.1 39 | # 1.8 = 2.1.2 40 | # (Some version updates were missed here...) 41 | # 2.0 = 2.3.1 42 | # 2.1 = 2.3.2 43 | # (Some version updates were missed here...) 44 | # 2.2 = 2.6 45 | # 2.3 = 2.7 46 | # 2.4 = 2.9 47 | # 48 | _version=2.4 49 | # 50 | # 51 | # Character set encoding used to read and write JMeter XML files and CSV results 52 | # 53 | _file_encoding=UTF-8 54 | # 55 | #--------------------------------------------------------- 56 | # 57 | # The following properties are used to create aliases 58 | # [Must all start with capital letter] 59 | # 60 | AccessLogSampler=org.apache.jmeter.protocol.http.sampler.AccessLogSampler 61 | AjpSampler=org.apache.jmeter.protocol.http.sampler.AjpSampler 62 | AjpSamplerGui=org.apache.jmeter.protocol.http.control.gui.AjpSamplerGui 63 | AnchorModifier=org.apache.jmeter.protocol.http.modifier.AnchorModifier 64 | AnchorModifierGui=org.apache.jmeter.protocol.http.modifier.gui.AnchorModifierGui 65 | Argument=org.apache.jmeter.config.Argument 66 | Arguments=org.apache.jmeter.config.Arguments 67 | ArgumentsPanel=org.apache.jmeter.config.gui.ArgumentsPanel 68 | AssertionGui=org.apache.jmeter.assertions.gui.AssertionGui 69 | AssertionVisualizer=org.apache.jmeter.visualizers.AssertionVisualizer 70 | AuthManager=org.apache.jmeter.protocol.http.control.AuthManager 71 | Authorization=org.apache.jmeter.protocol.http.control.Authorization 72 | AuthPanel=org.apache.jmeter.protocol.http.gui.AuthPanel 73 | BarChart=org.apache.jmeter.testelement.BarChart 74 | BarChartGui=org.apache.jmeter.report.gui.BarChartGui 75 | BeanShellAssertion=org.apache.jmeter.assertions.BeanShellAssertion 76 | BeanShellAssertionGui=org.apache.jmeter.assertions.gui.BeanShellAssertionGui 77 | BeanShellListener=org.apache.jmeter.visualizers.BeanShellListener 78 | BeanShellPostProcessor=org.apache.jmeter.extractor.BeanShellPostProcessor 79 | BeanShellPreProcessor=org.apache.jmeter.modifiers.BeanShellPreProcessor 80 | BeanShellSampler=org.apache.jmeter.protocol.java.sampler.BeanShellSampler 81 | BeanShellSamplerGui=org.apache.jmeter.protocol.java.control.gui.BeanShellSamplerGui 82 | BeanShellTimer=org.apache.jmeter.timers.BeanShellTimer 83 | BSFAssertion=org.apache.jmeter.assertions.BSFAssertion 84 | BSFListener=org.apache.jmeter.visualizers.BSFListener 85 | BSFPreProcessor=org.apache.jmeter.modifiers.BSFPreProcessor 86 | BSFPostProcessor=org.apache.jmeter.extractor.BSFPostProcessor 87 | BSFSampler=org.apache.jmeter.protocol.java.sampler.BSFSampler 88 | BSFSamplerGui=org.apache.jmeter.protocol.java.control.gui.BSFSamplerGui 89 | BSFTimer=org.apache.jmeter.timers.BSFTimer 90 | CacheManager=org.apache.jmeter.protocol.http.control.CacheManager 91 | CacheManagerGui=org.apache.jmeter.protocol.http.gui.CacheManagerGui 92 | CompareAssertion=org.apache.jmeter.assertions.CompareAssertion 93 | ComparisonVisualizer=org.apache.jmeter.visualizers.ComparisonVisualizer 94 | ConfigTestElement=org.apache.jmeter.config.ConfigTestElement 95 | ConstantThroughputTimer=org.apache.jmeter.timers.ConstantThroughputTimer 96 | ConstantTimer=org.apache.jmeter.timers.ConstantTimer 97 | ConstantTimerGui=org.apache.jmeter.timers.gui.ConstantTimerGui 98 | Cookie=org.apache.jmeter.protocol.http.control.Cookie 99 | CookieManager=org.apache.jmeter.protocol.http.control.CookieManager 100 | CookiePanel=org.apache.jmeter.protocol.http.gui.CookiePanel 101 | CounterConfig=org.apache.jmeter.modifiers.CounterConfig 102 | CounterConfigGui=org.apache.jmeter.modifiers.gui.CounterConfigGui 103 | CSVDataSet=org.apache.jmeter.config.CSVDataSet 104 | DebugPostProcessor=org.apache.jmeter.extractor.DebugPostProcessor 105 | DebugSampler=org.apache.jmeter.sampler.DebugSampler 106 | DistributionGraphVisualizer=org.apache.jmeter.visualizers.DistributionGraphVisualizer 107 | DurationAssertion=org.apache.jmeter.assertions.DurationAssertion 108 | DurationAssertionGui=org.apache.jmeter.assertions.gui.DurationAssertionGui 109 | # Should really have been defined as floatProp to agree with other properties 110 | # No point changing this now 111 | FloatProperty=org.apache.jmeter.testelement.property.FloatProperty 112 | ForeachController=org.apache.jmeter.control.ForeachController 113 | ForeachControlPanel=org.apache.jmeter.control.gui.ForeachControlPanel 114 | FtpConfigGui=org.apache.jmeter.protocol.ftp.config.gui.FtpConfigGui 115 | FTPSampler=org.apache.jmeter.protocol.ftp.sampler.FTPSampler 116 | FtpTestSamplerGui=org.apache.jmeter.protocol.ftp.control.gui.FtpTestSamplerGui 117 | GaussianRandomTimer=org.apache.jmeter.timers.GaussianRandomTimer 118 | GaussianRandomTimerGui=org.apache.jmeter.timers.gui.GaussianRandomTimerGui 119 | GenericController=org.apache.jmeter.control.GenericController 120 | GraphAccumVisualizer=org.apache.jmeter.visualizers.GraphAccumVisualizer 121 | GraphVisualizer=org.apache.jmeter.visualizers.GraphVisualizer 122 | Header=org.apache.jmeter.protocol.http.control.Header 123 | HeaderManager=org.apache.jmeter.protocol.http.control.HeaderManager 124 | HeaderPanel=org.apache.jmeter.protocol.http.gui.HeaderPanel 125 | HTMLAssertion=org.apache.jmeter.assertions.HTMLAssertion 126 | HTMLAssertionGui=org.apache.jmeter.assertions.gui.HTMLAssertionGui 127 | HTMLReportWriter=org.apache.jmeter.report.writers.HTMLReportWriter 128 | HTMLReportWriterGui=org.apache.jmeter.report.writers.gui.HTMLReportWriterGui 129 | HTTPArgument=org.apache.jmeter.protocol.http.util.HTTPArgument 130 | HTTPArgumentsPanel=org.apache.jmeter.protocol.http.gui.HTTPArgumentsPanel 131 | HTTPFileArg=org.apache.jmeter.protocol.http.util.HTTPFileArg 132 | HTTPFileArgs=org.apache.jmeter.protocol.http.util.HTTPFileArgs 133 | HttpDefaultsGui=org.apache.jmeter.protocol.http.config.gui.HttpDefaultsGui 134 | HtmlExtractor=org.apache.jmeter.extractor.HtmlExtractor 135 | HtmlExtractorGui=org.apache.jmeter.extractor.gui.HtmlExtractorGui 136 | # removed in r1039684, probably not released. Not present in r322831 or since. 137 | #HttpGenericSampler=org.apache.jmeter.protocol.http.sampler.HttpGenericSampler 138 | # removed in r1039684, probably not released. Not present in r322831 or since. 139 | #HttpGenericSamplerGui=org.apache.jmeter.protocol.http.control.gui.HttpGenericSamplerGui 140 | HttpMirrorControl=org.apache.jmeter.protocol.http.control.HttpMirrorControl 141 | HttpMirrorControlGui=org.apache.jmeter.protocol.http.control.gui.HttpMirrorControlGui 142 | # r397955 - removed test class. Keep as commented entry for info only. 143 | #HTTPNullSampler=org.apache.jmeter.protocol.http.sampler.HTTPNullSampler 144 | # Merge previous 2 HTTP samplers into one 145 | HTTPSampler_=org.apache.jmeter.protocol.http.sampler.HTTPSampler 146 | HTTPSampler2_=org.apache.jmeter.protocol.http.sampler.HTTPSampler2 147 | HTTPSamplerProxy,HTTPSampler,HTTPSampler2=org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy 148 | DummySampler=net.unit8.jmeter.protocol.websocket.DummySampler 149 | # Merge GUIs 150 | HttpTestSampleGui,HttpTestSampleGui2=org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui 151 | #HttpTestSampleGui2=org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui2 152 | IfController=org.apache.jmeter.control.IfController 153 | IfControllerPanel=org.apache.jmeter.control.gui.IfControllerPanel 154 | IncludeController=org.apache.jmeter.control.IncludeController 155 | IncludeControllerGui=org.apache.jmeter.control.gui.IncludeControllerGui 156 | InterleaveControl=org.apache.jmeter.control.InterleaveControl 157 | InterleaveControlGui=org.apache.jmeter.control.gui.InterleaveControlGui 158 | JavaConfig=org.apache.jmeter.protocol.java.config.JavaConfig 159 | JavaConfigGui=org.apache.jmeter.protocol.java.config.gui.JavaConfigGui 160 | JavaSampler=org.apache.jmeter.protocol.java.sampler.JavaSampler 161 | JavaTest=org.apache.jmeter.protocol.java.test.JavaTest 162 | JavaTestSamplerGui=org.apache.jmeter.protocol.java.control.gui.JavaTestSamplerGui 163 | JDBCDataSource=org.apache.jmeter.protocol.jdbc.config.DataSourceElement 164 | JDBCPostProcessor=org.apache.jmeter.protocol.jdbc.processor.JDBCPostProcessor 165 | JDBCPreProcessor=org.apache.jmeter.protocol.jdbc.processor.JDBCPreProcessor 166 | JDBCSampler=org.apache.jmeter.protocol.jdbc.sampler.JDBCSampler 167 | # Renamed to JMSSamplerGui; keep original entry for backwards compatibility 168 | JMSConfigGui=org.apache.jmeter.protocol.jms.control.gui.JMSConfigGui 169 | JMSPublisherGui=org.apache.jmeter.protocol.jms.control.gui.JMSPublisherGui 170 | JMSSampler=org.apache.jmeter.protocol.jms.sampler.JMSSampler 171 | JMSSamplerGui=org.apache.jmeter.protocol.jms.control.gui.JMSSamplerGui 172 | JMSSubscriberGui=org.apache.jmeter.protocol.jms.control.gui.JMSSubscriberGui 173 | # Removed in r545311 as Jndi no longer present; keep for compat. 174 | JndiDefaultsGui=org.apache.jmeter.protocol.jms.control.gui.JndiDefaultsGui 175 | JSR223Assertion=org.apache.jmeter.assertions.JSR223Assertion 176 | JSR223Listener=org.apache.jmeter.visualizers.JSR223Listener 177 | JSR223PostProcessor=org.apache.jmeter.extractor.JSR223PostProcessor 178 | JSR223PreProcessor=org.apache.jmeter.modifiers.JSR223PreProcessor 179 | JSR223Sampler=org.apache.jmeter.protocol.java.sampler.JSR223Sampler 180 | JSR223Timer=org.apache.jmeter.timers.JSR223Timer 181 | JUnitSampler=org.apache.jmeter.protocol.java.sampler.JUnitSampler 182 | JUnitTestSamplerGui=org.apache.jmeter.protocol.java.control.gui.JUnitTestSamplerGui 183 | KeystoreConfig=org.apache.jmeter.config.KeystoreConfig 184 | LDAPArgument=org.apache.jmeter.protocol.ldap.config.gui.LDAPArgument 185 | LDAPArguments=org.apache.jmeter.protocol.ldap.config.gui.LDAPArguments 186 | LDAPArgumentsPanel=org.apache.jmeter.protocol.ldap.config.gui.LDAPArgumentsPanel 187 | LdapConfigGui=org.apache.jmeter.protocol.ldap.config.gui.LdapConfigGui 188 | LdapExtConfigGui=org.apache.jmeter.protocol.ldap.config.gui.LdapExtConfigGui 189 | LDAPExtSampler=org.apache.jmeter.protocol.ldap.sampler.LDAPExtSampler 190 | LdapExtTestSamplerGui=org.apache.jmeter.protocol.ldap.control.gui.LdapExtTestSamplerGui 191 | LDAPSampler=org.apache.jmeter.protocol.ldap.sampler.LDAPSampler 192 | LdapTestSamplerGui=org.apache.jmeter.protocol.ldap.control.gui.LdapTestSamplerGui 193 | LineChart=org.apache.jmeter.testelement.LineChart 194 | LineGraphGui=org.apache.jmeter.report.gui.LineGraphGui 195 | LogicControllerGui=org.apache.jmeter.control.gui.LogicControllerGui 196 | LoginConfig=org.apache.jmeter.config.LoginConfig 197 | LoginConfigGui=org.apache.jmeter.config.gui.LoginConfigGui 198 | LoopController=org.apache.jmeter.control.LoopController 199 | LoopControlPanel=org.apache.jmeter.control.gui.LoopControlPanel 200 | MailerModel=org.apache.jmeter.reporters.MailerModel 201 | MailerResultCollector=org.apache.jmeter.reporters.MailerResultCollector 202 | MailerVisualizer=org.apache.jmeter.visualizers.MailerVisualizer 203 | MailReaderSampler=org.apache.jmeter.protocol.mail.sampler.MailReaderSampler 204 | MailReaderSamplerGui=org.apache.jmeter.protocol.mail.sampler.gui.MailReaderSamplerGui 205 | MD5HexAssertion=org.apache.jmeter.assertions.MD5HexAssertion 206 | MD5HexAssertionGUI=org.apache.jmeter.assertions.gui.MD5HexAssertionGUI 207 | ModuleController=org.apache.jmeter.control.ModuleController 208 | ModuleControllerGui=org.apache.jmeter.control.gui.ModuleControllerGui 209 | MonitorHealthVisualizer=org.apache.jmeter.visualizers.MonitorHealthVisualizer 210 | NamePanel=org.apache.jmeter.gui.NamePanel 211 | ObsoleteGui=org.apache.jmeter.config.gui.ObsoleteGui 212 | OnceOnlyController=org.apache.jmeter.control.OnceOnlyController 213 | OnceOnlyControllerGui=org.apache.jmeter.control.gui.OnceOnlyControllerGui 214 | ParamMask=org.apache.jmeter.protocol.http.modifier.ParamMask 215 | ParamModifier=org.apache.jmeter.protocol.http.modifier.ParamModifier 216 | ParamModifierGui=org.apache.jmeter.protocol.http.modifier.gui.ParamModifierGui 217 | PoissonRandomTimer=org.apache.jmeter.timers.PoissonRandomTimer 218 | PoissonRandomTimerGui=org.apache.jmeter.timers.gui.PoissonRandomTimerGui 219 | PropertyControlGui=org.apache.jmeter.visualizers.PropertyControlGui 220 | ProxyControl=org.apache.jmeter.protocol.http.proxy.ProxyControl 221 | ProxyControlGui=org.apache.jmeter.protocol.http.proxy.gui.ProxyControlGui 222 | PublisherSampler=org.apache.jmeter.protocol.jms.sampler.PublisherSampler 223 | RandomControlGui=org.apache.jmeter.control.gui.RandomControlGui 224 | RandomController=org.apache.jmeter.control.RandomController 225 | RandomOrderController=org.apache.jmeter.control.RandomOrderController 226 | RandomOrderControllerGui=org.apache.jmeter.control.gui.RandomOrderControllerGui 227 | RandomVariableConfig=org.apache.jmeter.config.RandomVariableConfig 228 | RecordController=org.apache.jmeter.protocol.http.control.gui.RecordController 229 | RecordingController=org.apache.jmeter.protocol.http.control.RecordingController 230 | # removed in r1039684, class was deleted in r580452 231 | ReflectionThreadGroup=org.apache.jmeter.threads.ReflectionThreadGroup 232 | RegexExtractor=org.apache.jmeter.extractor.RegexExtractor 233 | RegexExtractorGui=org.apache.jmeter.extractor.gui.RegexExtractorGui 234 | RegExUserParameters=org.apache.jmeter.protocol.http.modifier.RegExUserParameters 235 | RegExUserParametersGui=org.apache.jmeter.protocol.http.modifier.gui.RegExUserParametersGui 236 | RemoteListenerWrapper=org.apache.jmeter.samplers.RemoteListenerWrapper 237 | RemoteSampleListenerWrapper=org.apache.jmeter.samplers.RemoteSampleListenerWrapper 238 | RemoteTestListenerWrapper=org.apache.jmeter.samplers.RemoteTestListenerWrapper 239 | ReportGui=org.apache.jmeter.control.gui.ReportGui 240 | ReportPage=org.apache.jmeter.testelement.ReportPage 241 | ReportPageGui=org.apache.jmeter.report.gui.ReportPageGui 242 | ReportPlan=org.apache.jmeter.testelement.ReportPlan 243 | ResponseAssertion=org.apache.jmeter.assertions.ResponseAssertion 244 | RespTimeGraphVisualizer=org.apache.jmeter.visualizers.RespTimeGraphVisualizer 245 | ResultAction=org.apache.jmeter.reporters.ResultAction 246 | ResultActionGui=org.apache.jmeter.reporters.gui.ResultActionGui 247 | ResultCollector=org.apache.jmeter.reporters.ResultCollector 248 | ResultSaver=org.apache.jmeter.reporters.ResultSaver 249 | ResultSaverGui=org.apache.jmeter.reporters.gui.ResultSaverGui 250 | RunTime=org.apache.jmeter.control.RunTime 251 | RunTimeGui=org.apache.jmeter.control.gui.RunTimeGui 252 | SampleSaveConfiguration=org.apache.jmeter.samplers.SampleSaveConfiguration 253 | SimpleConfigGui=org.apache.jmeter.config.gui.SimpleConfigGui 254 | SimpleDataWriter=org.apache.jmeter.visualizers.SimpleDataWriter 255 | SizeAssertion=org.apache.jmeter.assertions.SizeAssertion 256 | SizeAssertionGui=org.apache.jmeter.assertions.gui.SizeAssertionGui 257 | SMIMEAssertion=org.apache.jmeter.assertions.SMIMEAssertionTestElement 258 | SMIMEAssertionGui=org.apache.jmeter.assertions.gui.SMIMEAssertionGui 259 | SmtpSampler=org.apache.jmeter.protocol.smtp.sampler.SmtpSampler 260 | SmtpSamplerGui=org.apache.jmeter.protocol.smtp.sampler.gui.SmtpSamplerGui 261 | SoapSampler=org.apache.jmeter.protocol.http.sampler.SoapSampler 262 | SoapSamplerGui=org.apache.jmeter.protocol.http.control.gui.SoapSamplerGui 263 | SplineVisualizer=org.apache.jmeter.visualizers.SplineVisualizer 264 | # Originally deleted in r397955 as class is obsolete; needed for compat. 265 | SqlConfigGui=org.apache.jmeter.protocol.jdbc.config.gui.SqlConfigGui 266 | StatGraphVisualizer=org.apache.jmeter.visualizers.StatGraphVisualizer 267 | StatVisualizer=org.apache.jmeter.visualizers.StatVisualizer 268 | SubscriberSampler=org.apache.jmeter.protocol.jms.sampler.SubscriberSampler 269 | SubstitutionElement=org.apache.jmeter.assertions.SubstitutionElement 270 | Summariser=org.apache.jmeter.reporters.Summariser 271 | SummariserGui=org.apache.jmeter.reporters.gui.SummariserGui 272 | SummaryReport=org.apache.jmeter.visualizers.SummaryReport 273 | SwitchController=org.apache.jmeter.control.SwitchController 274 | SwitchControllerGui=org.apache.jmeter.control.gui.SwitchControllerGui 275 | SyncTimer=org.apache.jmeter.timers.SyncTimer 276 | SystemSampler=org.apache.jmeter.protocol.system.SystemSampler 277 | SystemSamplerGui=org.apache.jmeter.protocol.system.gui.SystemSamplerGui 278 | Table=org.apache.jmeter.testelement.Table 279 | TableGui=org.apache.jmeter.report.gui.TableGui 280 | TableVisualizer=org.apache.jmeter.visualizers.TableVisualizer 281 | TCPConfigGui=org.apache.jmeter.protocol.tcp.config.gui.TCPConfigGui 282 | TCPSampler=org.apache.jmeter.protocol.tcp.sampler.TCPSampler 283 | TCPSamplerGui=org.apache.jmeter.protocol.tcp.control.gui.TCPSamplerGui 284 | TestAction=org.apache.jmeter.sampler.TestAction 285 | TestActionGui=org.apache.jmeter.sampler.gui.TestActionGui 286 | TestBeanGUI=org.apache.jmeter.testbeans.gui.TestBeanGUI 287 | TestFragmentController=org.apache.jmeter.control.TestFragmentController 288 | TestFragmentControllerGui=org.apache.jmeter.control.gui.TestFragmentControllerGui 289 | TestPlan=org.apache.jmeter.testelement.TestPlan 290 | TestPlanGui=org.apache.jmeter.control.gui.TestPlanGui 291 | ThreadGroup=org.apache.jmeter.threads.ThreadGroup 292 | ThreadGroupGui=org.apache.jmeter.threads.gui.ThreadGroupGui 293 | PostThreadGroup=org.apache.jmeter.threads.PostThreadGroup 294 | PostThreadGroupGui=org.apache.jmeter.threads.gui.PostThreadGroupGui 295 | SetupThreadGroup=org.apache.jmeter.threads.SetupThreadGroup 296 | SetupThreadGroupGui=org.apache.jmeter.threads.gui.SetupThreadGroupGui 297 | ThroughputController=org.apache.jmeter.control.ThroughputController 298 | ThroughputControllerGui=org.apache.jmeter.control.gui.ThroughputControllerGui 299 | TransactionController=org.apache.jmeter.control.TransactionController 300 | TransactionControllerGui=org.apache.jmeter.control.gui.TransactionControllerGui 301 | TransactionSampler=org.apache.jmeter.control.TransactionSampler 302 | UniformRandomTimer=org.apache.jmeter.timers.UniformRandomTimer 303 | UniformRandomTimerGui=org.apache.jmeter.timers.gui.UniformRandomTimerGui 304 | URLRewritingModifier=org.apache.jmeter.protocol.http.modifier.URLRewritingModifier 305 | URLRewritingModifierGui=org.apache.jmeter.protocol.http.modifier.gui.URLRewritingModifierGui 306 | UserParameterModifier=org.apache.jmeter.protocol.http.modifier.UserParameterModifier 307 | UserParameterModifierGui=org.apache.jmeter.protocol.http.modifier.gui.UserParameterModifierGui 308 | UserParameters=org.apache.jmeter.modifiers.UserParameters 309 | UserParametersGui=org.apache.jmeter.modifiers.gui.UserParametersGui 310 | ViewResultsFullVisualizer=org.apache.jmeter.visualizers.ViewResultsFullVisualizer 311 | WebServiceSampler=org.apache.jmeter.protocol.http.sampler.WebServiceSampler 312 | WebServiceSamplerGui=org.apache.jmeter.protocol.http.control.gui.WebServiceSamplerGui 313 | WhileController=org.apache.jmeter.control.WhileController 314 | WhileControllerGui=org.apache.jmeter.control.gui.WhileControllerGui 315 | WorkBench=org.apache.jmeter.testelement.WorkBench 316 | WorkBenchGui=org.apache.jmeter.control.gui.WorkBenchGui 317 | XMLAssertion=org.apache.jmeter.assertions.XMLAssertion 318 | XMLAssertionGui=org.apache.jmeter.assertions.gui.XMLAssertionGui 319 | XMLSchemaAssertion=org.apache.jmeter.assertions.XMLSchemaAssertion 320 | XMLSchemaAssertionGUI=org.apache.jmeter.assertions.gui.XMLSchemaAssertionGUI 321 | XPathAssertion=org.apache.jmeter.assertions.XPathAssertion 322 | XPathAssertionGui=org.apache.jmeter.assertions.gui.XPathAssertionGui 323 | XPathExtractor=org.apache.jmeter.extractor.XPathExtractor 324 | XPathExtractorGui=org.apache.jmeter.extractor.gui.XPathExtractorGui 325 | # 326 | # Properties - all start with lower case letter and end with Prop 327 | # 328 | boolProp=org.apache.jmeter.testelement.property.BooleanProperty 329 | collectionProp=org.apache.jmeter.testelement.property.CollectionProperty 330 | doubleProp=org.apache.jmeter.testelement.property.DoubleProperty 331 | elementProp=org.apache.jmeter.testelement.property.TestElementProperty 332 | # see above - already defined as FloatProperty 333 | #floatProp=org.apache.jmeter.testelement.property.FloatProperty 334 | intProp=org.apache.jmeter.testelement.property.IntegerProperty 335 | longProp=org.apache.jmeter.testelement.property.LongProperty 336 | mapProp=org.apache.jmeter.testelement.property.MapProperty 337 | objProp=org.apache.jmeter.testelement.property.ObjectProperty 338 | stringProp=org.apache.jmeter.testelement.property.StringProperty 339 | # 340 | # Other - must start with a lower case letter (and not end with Prop) 341 | # (otherwise they could clash with the initial set of aliases) 342 | # 343 | hashTree=org.apache.jorphan.collections.ListedHashTree 344 | jmeterTestPlan=org.apache.jmeter.save.ScriptWrapper 345 | sample=org.apache.jmeter.samplers.SampleResult 346 | httpSample=org.apache.jmeter.protocol.http.sampler.HTTPSampleResult 347 | statSample=org.apache.jmeter.samplers.StatisticalSampleResult 348 | testResults=org.apache.jmeter.save.TestResultWrapper 349 | assertionResult=org.apache.jmeter.assertions.AssertionResult 350 | monitorStats=org.apache.jmeter.visualizers.MonitorStats 351 | sampleEvent=org.apache.jmeter.samplers.SampleEvent 352 | # 353 | # Converters to register. Must start line with '_' 354 | # If the converter is a collection of subitems, set equal to "collection" 355 | # If the converter needs to know the class mappings but is not a collection of 356 | # subitems, set it equal to "mapping" 357 | _org.apache.jmeter.protocol.http.sampler.HTTPSamplerBaseConverter=collection 358 | _org.apache.jmeter.protocol.http.util.HTTPResultConverter=collection 359 | _org.apache.jmeter.save.converters.BooleanPropertyConverter= 360 | _org.apache.jmeter.save.converters.IntegerPropertyConverter= 361 | _org.apache.jmeter.save.converters.LongPropertyConverter= 362 | _org.apache.jmeter.save.converters.MultiPropertyConverter=collection 363 | _org.apache.jmeter.save.converters.SampleEventConverter= 364 | _org.apache.jmeter.save.converters.SampleResultConverter=collection 365 | _org.apache.jmeter.save.converters.SampleSaveConfigurationConverter=collection 366 | _org.apache.jmeter.save.converters.StringPropertyConverter= 367 | _org.apache.jmeter.save.converters.HashTreeConverter=collection 368 | _org.apache.jmeter.save.converters.TestElementConverter=collection 369 | _org.apache.jmeter.save.converters.TestElementPropertyConverter=collection 370 | _org.apache.jmeter.save.converters.TestResultWrapperConverter=collection 371 | _org.apache.jmeter.save.ScriptWrapperConverter=mapping 372 | # 373 | # Remember to update the _version entry 374 | # 375 | -------------------------------------------------------------------------------- /src/test/resources/users.csv: -------------------------------------------------------------------------------- 1 | USER_NAME 2 | Lyle 3 | Malcolm 4 | Quinlan 5 | Madaline 6 | Brady 7 | Ariel 8 | Sebastian 9 | Fiona 10 | Kathleen 11 | Quynn 12 | Alisa 13 | Lyle 14 | Orla 15 | Carissa 16 | Buffy 17 | Eliana 18 | Gannon 19 | Moana 20 | Quamar 21 | Deacon 22 | Jesse 23 | Bell 24 | Ira 25 | Rooney 26 | Justine 27 | Gloria 28 | Kameko 29 | Maxwell 30 | Zane 31 | Leo 32 | Karina 33 | Linda 34 | Cooper 35 | Echo 36 | Craig 37 | Gage 38 | Geoffrey 39 | Aretha 40 | McKenzie 41 | Steel 42 | Scarlet 43 | Nash 44 | Jin 45 | Laith 46 | Shay 47 | Madeline 48 | Sierra 49 | Chava 50 | Emma 51 | Madaline 52 | Irene 53 | Rana 54 | Norman 55 | Suki 56 | Levi 57 | Courtney 58 | Dana 59 | Blair 60 | Suki 61 | Cruz 62 | Nehru 63 | Hector 64 | Salvador 65 | Tyrone 66 | Miranda 67 | Amy 68 | Debra 69 | Alec 70 | Bradley 71 | Timothy 72 | Tara 73 | Warren 74 | Lillith 75 | Hanae 76 | Kaseem 77 | Jackson 78 | Abdul 79 | Hall 80 | Mariko 81 | Eric 82 | Zia 83 | Autumn 84 | Axel 85 | Nolan 86 | Wilma 87 | Mohammad 88 | Victoria 89 | Cheyenne 90 | Raven 91 | Rosalyn 92 | Idola 93 | Jesse 94 | Clementine 95 | Darryl 96 | Henry 97 | Sydney 98 | Emerald 99 | Maryam 100 | Thor 101 | Holmes -------------------------------------------------------------------------------- /src/test/scripts/chat.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | process.title = 'chat'; 4 | 5 | var webSocketsServerPort = 9090; 6 | 7 | var webSocketServer = require('websocket').server; 8 | var http = require('http'); 9 | 10 | var history = [ ]; 11 | var clients = [ ]; 12 | 13 | var server = http.createServer(function(request, response) { 14 | }); 15 | 16 | server.listen(webSocketsServerPort, function() { 17 | console.log((new Date()) + " Server is listening on port " + webSocketsServerPort); 18 | }); 19 | 20 | var wsServer = new webSocketServer({ 21 | httpServer: server 22 | }); 23 | 24 | wsServer.on('request', function(request) { 25 | var query = request.resourceURL.query; 26 | var name = query["name"] || "unknown"; 27 | 28 | var connection = request.accept(null, request.origin); 29 | var index = clients.push(connection) - 1; 30 | 31 | if (history.length > 0) { 32 | connection.sendUTF(JSON.stringify(history)); 33 | } 34 | 35 | connection.on('message', function(message) { 36 | if (message.type !== 'utf8') 37 | return; 38 | 39 | var message = message.utf8Data; 40 | 41 | var chat = { 42 | name: name, 43 | message: message, 44 | chatedAt: new Date() 45 | }; 46 | history.push(chat); 47 | history = history.slice(-100); 48 | 49 | var json = JSON.stringify([chat]); 50 | for (var i=0; i < clients.length; i++) { 51 | clients[i].sendUTF(json); 52 | } 53 | }); 54 | 55 | connection.on('close', function(connection) { 56 | console.log((new Date()) + " User " 57 | + name + " disconnected."); 58 | clients.splice(index, 1); 59 | }); 60 | }); --------------------------------------------------------------------------------