PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/media/test-suite/core/src/main/java/org/mobicents/media/server/testsuite/cli/CLIRunner.java

http://mobicents.googlecode.com/
Java | 652 lines | 467 code | 88 blank | 97 comment | 59 complexity | a4b25a6d91a78a94398f8c8f29dd2656 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. package org.mobicents.media.server.testsuite.cli;
  2. import gnu.getopt.Getopt;
  3. import gnu.getopt.LongOpt;
  4. import jain.protocol.ip.mgcp.CreateProviderException;
  5. import java.awt.List;
  6. import java.io.BufferedReader;
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.FileNotFoundException;
  10. import java.io.FileOutputStream;
  11. import java.io.FileReader;
  12. import java.io.IOException;
  13. import java.io.InputStream;
  14. import java.io.ObjectInputStream;
  15. import java.io.OutputStreamWriter;
  16. import java.net.InetAddress;
  17. import java.net.SocketException;
  18. import java.net.URL;
  19. import java.net.UnknownHostException;
  20. import java.util.ArrayList;
  21. import java.util.Arrays;
  22. import java.util.HashSet;
  23. import java.util.Properties;
  24. import java.util.Set;
  25. import java.util.TooManyListenersException;
  26. import java.util.Vector;
  27. import java.util.logging.Level;
  28. import java.util.logging.Logger;
  29. import javax.sdp.Attribute;
  30. import javax.sdp.SdpFactory;
  31. import org.apache.log4j.PropertyConfigurator;
  32. import org.mobicents.media.server.testsuite.general.AbstractTestCase;
  33. import org.mobicents.media.server.testsuite.general.CallDisplayInterface;
  34. import org.mobicents.media.server.testsuite.general.TestState;
  35. import org.mobicents.media.server.testsuite.general.ann.AnnouncementTest;
  36. import org.mobicents.media.server.testsuite.general.file.FileUtils;
  37. /**
  38. * Start time:12:13:39 2009-07-16<br>
  39. * Project: mobicents-media-server-test-suite<br>
  40. *
  41. * This is class which enables running test tool in cli mode.
  42. *
  43. * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
  44. */
  45. public class CLIRunner implements CallDisplayInterface {
  46. private transient static final String _COLLECTIVE_FILE_NAME = "graph.txt";
  47. private String localAddress = "127.0.0.1", remoteAddress = "127.0.0.1";
  48. private int localPort = 2428, remotePort = 2427;
  49. private int cps = 1;
  50. private long callDuration = 2500;
  51. private long maxCalls = AbstractTestCase._TURN_OFF_BOUNDRY;
  52. private int maxConcurrentCalls = AbstractTestCase._TURN_OFF_BOUNDRY;
  53. private int maxFailCalls = AbstractTestCase._TURN_OFF_BOUNDRY;
  54. private File dataDumpDir = new File("datadump");
  55. private String audioFileURL = new File("target/audio/ulaw_13s.wav").toURI().toString();
  56. private Vector<Attribute> codec = new Vector<Attribute>();
  57. private AbstractTestCase testCase;
  58. private TestTypeEnum testType = TestTypeEnum.AnnTest;
  59. private boolean performOfflineDumps;
  60. private long callSequenceToDump;
  61. private boolean performTestRun;
  62. private static final LongOpt[] _LONG_OPTS = new LongOpt[15];
  63. private static final String _GETOPT_PARAMS_STRING = "h:q:w:e:r:t:y:u:i:o:p:a:f:g";
  64. private static final Logger log = Logger.getLogger(CLIRunner.class.getName());
  65. private static void configLog4j() {
  66. InputStream inStreamLog4j = CLIRunner.class.getClassLoader().getResourceAsStream("log4j.properties");
  67. Properties propertiesLog4j = new Properties();
  68. try {
  69. propertiesLog4j.load(inStreamLog4j);
  70. PropertyConfigurator.configure(propertiesLog4j);
  71. } catch (Exception e) {
  72. e.printStackTrace();
  73. }
  74. log.finest("log4j configured");
  75. }
  76. static {
  77. _LONG_OPTS[0] = new LongOpt("usage", LongOpt.NO_ARGUMENT, null, 'h');
  78. _LONG_OPTS[1] = new LongOpt("localaddr", LongOpt.OPTIONAL_ARGUMENT, null, 'q');
  79. _LONG_OPTS[2] = new LongOpt("remoteaddr", LongOpt.OPTIONAL_ARGUMENT, null, 'w');
  80. _LONG_OPTS[3] = new LongOpt("remoteport", LongOpt.OPTIONAL_ARGUMENT, null, 'e');
  81. _LONG_OPTS[4] = new LongOpt("localport", LongOpt.OPTIONAL_ARGUMENT, null, 'r');
  82. _LONG_OPTS[5] = new LongOpt("concurrentcalls", LongOpt.OPTIONAL_ARGUMENT, null, 't');
  83. _LONG_OPTS[6] = new LongOpt("maxcalls", LongOpt.OPTIONAL_ARGUMENT, null, 'y');
  84. _LONG_OPTS[7] = new LongOpt("datadir", LongOpt.OPTIONAL_ARGUMENT, null, 'u');
  85. _LONG_OPTS[8] = new LongOpt("audiofile", LongOpt.OPTIONAL_ARGUMENT, null, 'i');
  86. _LONG_OPTS[9] = new LongOpt("audiocodec", LongOpt.OPTIONAL_ARGUMENT, null, 'o');
  87. _LONG_OPTS[10] = new LongOpt("testtype", LongOpt.OPTIONAL_ARGUMENT, null, 'p');
  88. _LONG_OPTS[11] = new LongOpt("cps", LongOpt.OPTIONAL_ARGUMENT, null, 'a');
  89. _LONG_OPTS[12] = new LongOpt("maxfail", LongOpt.OPTIONAL_ARGUMENT, null, 'f');
  90. _LONG_OPTS[13] = new LongOpt("callduration", LongOpt.OPTIONAL_ARGUMENT, null, 'l');
  91. _LONG_OPTS[14] = new LongOpt("graph", LongOpt.OPTIONAL_ARGUMENT, null, 'g');
  92. configLog4j();
  93. }
  94. /**
  95. *
  96. */
  97. public CLIRunner() {
  98. // TODO Auto-generated constructor stub
  99. convertCodec("0 pcmu/8000");
  100. }
  101. // ////////////////
  102. // Usage method //
  103. // ////////////////
  104. public static void usage() {
  105. StringBuffer sb = new StringBuffer();
  106. sb.append("java " + CLIRunner.class.getName() + " [OPTIONS] --testtype TestType \n");
  107. sb.append("Where options can be:\n");
  108. sb.append("--localaddr : local address, default is 127.0.0.1\n");
  109. sb.append("--remoteaddr : remote address, default is 127.0.0.1\n");
  110. sb.append("--localpport : local port, default is 2428\n");
  111. sb.append("--remoteport : remote port, default is 2427\n");
  112. sb.append("--concurrentcalls : concurrent calls, default is -1, which means unbound\n");
  113. sb.append("--maxcalls : max calls, default is -1, which means unbound\n");
  114. sb.append("--datadir : data dump directory, default is ./datadump. IN case of offline runs, it must point to valid test, like: /datadump/1231463412\n");
  115. sb.append("--audiofile : audio file url, if requried, default is file:/./../../target/audio/ulaw_13s.wav\n");
  116. sb.append("--audiocodec : audio codec to be used if requried, default is \'0 pcmu/8000\', value should be specifiedd in \'\'\n");
  117. sb.append("--testtype : test type, currently there is only one available: AnnTest\n");
  118. sb.append("--maxfail : specifies how many calls may fail until testtool will stop sending requests to server, default is -1, which means unbound\n");
  119. sb.append("--callduration : specifies how long test runs(in milliseconds), default is 2500 \n");
  120. sb.append("--cps : specifies calls per second, default is 1 \n");
  121. sb.append("--usage : print this message\n");
  122. sb.append("--graph : It makes test case produce graphic files and present some txt output. Graphic files depend on testcase, some do not support graphic. If there is no value, test case picks one call arbitrary, otherwise it performs this operation for specific call. Argumetn must match call sequence.\n");
  123. sb.append("example options part: --localaddress=127.0.0.1 --localport=2499 --concurentcalls=12 --audiocodec=\'8 pcma/8000\' --testtype=AnnTest\n");
  124. log.severe("Usage: \n" + sb);
  125. }
  126. // ///////////////////////
  127. // Some helper methods //
  128. // ///////////////////////
  129. private void convertCodec(String s) {
  130. SdpFactory sdpFactory = SdpFactory.getInstance();
  131. codec.clear();
  132. codec.add(sdpFactory.createAttribute("rtpmap", s.replaceAll("'", "")));
  133. }
  134. private void convertTest(String v) {
  135. testType = TestTypeEnum.fromString(v);
  136. }
  137. // ////////////////////////
  138. // Methods used by test //
  139. // ////////////////////////
  140. /*
  141. * (non-Javadoc)
  142. *
  143. * @see
  144. * org.mobicents.media.server.testsuite.general.CallDisplayInterface#getCPS
  145. * ()
  146. */
  147. public int getCPS() {
  148. return this.cps;
  149. }
  150. /*
  151. * (non-Javadoc)
  152. *
  153. * @seeorg.mobicents.media.server.testsuite.general.CallDisplayInterface#
  154. * getCallDuration()
  155. */
  156. public long getCallDuration() {
  157. return this.callDuration;
  158. }
  159. /*
  160. * (non-Javadoc)
  161. *
  162. * @see
  163. * org.mobicents.media.server.testsuite.general.CallDisplayInterface#getCodec
  164. * ()
  165. */
  166. public Vector<Attribute> getCodecs() {
  167. return this.codec;
  168. }
  169. /*
  170. * (non-Javadoc)
  171. *
  172. * @seeorg.mobicents.media.server.testsuite.general.CallDisplayInterface#
  173. * getDefaultDataDumpDirectory()
  174. */
  175. public File getDefaultDataDumpDirectory() {
  176. return this.dataDumpDir;
  177. }
  178. /*
  179. * (non-Javadoc)
  180. *
  181. * @see
  182. * org.mobicents.media.server.testsuite.general.CallDisplayInterface#getFileURL
  183. * ()
  184. */
  185. public String getFileURL() {
  186. return this.audioFileURL;
  187. }
  188. /*
  189. * (non-Javadoc)
  190. *
  191. * @seeorg.mobicents.media.server.testsuite.general.CallDisplayInterface#
  192. * getLocalAddress()
  193. */
  194. public String getLocalAddress() {
  195. return this.localAddress;
  196. }
  197. /*
  198. * (non-Javadoc)
  199. *
  200. * @seeorg.mobicents.media.server.testsuite.general.CallDisplayInterface#
  201. * getLocalPort()
  202. */
  203. public int getLocalPort() {
  204. return this.localPort;
  205. }
  206. /*
  207. * (non-Javadoc)
  208. *
  209. * @seeorg.mobicents.media.server.testsuite.general.CallDisplayInterface#
  210. * getRemoteAddress()
  211. */
  212. public String getRemoteAddress() {
  213. return this.remoteAddress;
  214. }
  215. /*
  216. * (non-Javadoc)
  217. *
  218. * @seeorg.mobicents.media.server.testsuite.general.CallDisplayInterface#
  219. * getRemotePort()
  220. */
  221. public int getRemotePort() {
  222. return this.remotePort;
  223. }
  224. /*
  225. * (non-Javadoc)
  226. *
  227. * @seeorg.mobicents.media.server.testsuite.general.CallDisplayInterface#
  228. * updateCallView()
  229. */
  230. public void updateCallView() {
  231. if (log.isLoggable(Level.INFO)) {
  232. StringBuffer sb = new StringBuffer();
  233. sb.append("=============================================================\n");
  234. sb.append("Press 'q' + Enter to stop test\n");
  235. sb.append("Current calls : " + this.testCase.getOngoingCallNumber() + "\n");
  236. sb.append("Success calls : " + this.testCase.getCompletedCallNumber() + "\n");
  237. sb.append("Failed calls : " + this.testCase.getErrorCallNumber() + "\n");
  238. sb.append("Max failed calls : " + this.maxFailCalls + "\n");
  239. sb.append("Total calls : " + this.testCase.getTotalCallNumber() + "\n");
  240. log.info(sb.toString());
  241. }
  242. }
  243. public int getMaxConcurrentCalls() {
  244. return this.maxConcurrentCalls;
  245. }
  246. public long getMaxCalls() {
  247. return this.maxCalls;
  248. }
  249. public int getMaxFailCalls() {
  250. return this.maxFailCalls;
  251. }
  252. public static void main(String[] args) {
  253. CLIRunner cli = new CLIRunner();
  254. cli.parseArgs(args);
  255. ;
  256. if (cli.performTestRun)
  257. cli.runTest();
  258. // This is required, since mgc stack leaves some threads alive....
  259. if (cli.performOfflineDumps) {
  260. if(cli.loadTest())
  261. {
  262. cli.performDumps();
  263. }else
  264. {
  265. log.severe("Failed to load test from: "+cli.dataDumpDir);
  266. }
  267. }
  268. System.exit(0);
  269. }
  270. private boolean loadTest() {
  271. //we must load test if its not there yet
  272. if(testCase !=null)
  273. {
  274. return true;
  275. }
  276. try{
  277. AbstractTestCase test = FileUtils.deserializeTestCase(this.dataDumpDir);
  278. this.testCase = test;
  279. this.testCase.setCallDisplay(this,this.dataDumpDir);
  280. this.dataDumpDir = this.dataDumpDir.getParentFile();
  281. return true;
  282. }catch(Exception e)
  283. {
  284. e.printStackTrace();
  285. }
  286. return false;
  287. }
  288. private void performDumps() {
  289. this.testCase.createGraphicDumps(callSequenceToDump);
  290. String[] txtDumps = this.testCase.getTextDump();
  291. log.info(" ------------- TEST Output -------------");
  292. for(String s: txtDumps)
  293. {
  294. log.info(">>"+s);
  295. }
  296. log.info(" ---------------------------------------");
  297. }
  298. private void runTest() {
  299. try {
  300. this.testCase = testType.getTestCaseForType(this);
  301. log.info("Starting test case, prest 'q' to exit test");
  302. } catch (UnknownHostException ex) {
  303. log.log(Level.SEVERE, null, ex);
  304. return;
  305. } catch (Exception e) {
  306. log.log(Level.SEVERE, null, e);
  307. return;
  308. }
  309. try {
  310. this.testCase.start();
  311. while (this.testCase.getTestState() != TestState.Stoped) {
  312. try {
  313. Thread.sleep(1000);
  314. if (System.in.available() > 0) {
  315. int r = System.in.read();
  316. if (r == 'q') {
  317. break;
  318. }
  319. }
  320. } catch (Exception e) {
  321. e.printStackTrace();
  322. }
  323. }
  324. } catch (CreateProviderException ex) {
  325. log.log(Level.SEVERE, null, ex);
  326. } catch (TooManyListenersException ex) {
  327. log.log(Level.SEVERE, null, ex);
  328. } finally {
  329. if (testCase != null) {
  330. try {
  331. testCase.stop(false);
  332. } catch (Exception e) {
  333. e.printStackTrace();
  334. }
  335. try {
  336. Thread.currentThread().sleep(this.getCallDuration() + 5000);
  337. } catch (InterruptedException e) {
  338. // TODO Auto-generated catch block
  339. e.printStackTrace();
  340. }
  341. }
  342. }
  343. }
  344. private void parseArgs(String[] args) {
  345. Getopt getOpt = new Getopt("CLIRunner", args, _GETOPT_PARAMS_STRING, _LONG_OPTS);
  346. getOpt.setOpterr(true);
  347. int c = -1;
  348. String v = null;
  349. while ((c = getOpt.getopt()) != -1) {
  350. // _GETOPT_PARAMS_STRING ="h:q:w:e:r:t:y:u:i:o:p";
  351. switch (c) {
  352. case 'h':
  353. usage();
  354. System.exit(0);
  355. case 'q':
  356. // local address
  357. v = getOpt.getOptarg();
  358. if (v == null) {
  359. log.severe("Local Address must have value");
  360. } else {
  361. try {
  362. InetAddress.getByName(v);
  363. this.localAddress = v;
  364. } catch (UnknownHostException ex) {
  365. log.log(Level.SEVERE, null, ex);
  366. }
  367. }
  368. this.performTestRun = true;
  369. break;
  370. case 'w':
  371. // remote address
  372. v = getOpt.getOptarg();
  373. if (v == null) {
  374. log.severe("Remote Address must have value");
  375. } else {
  376. try {
  377. InetAddress.getByName(v);
  378. this.remoteAddress = v;
  379. } catch (UnknownHostException ex) {
  380. log.log(Level.SEVERE, null, ex);
  381. }
  382. }
  383. this.performTestRun = true;
  384. break;
  385. case 'e':
  386. // remote port
  387. v = getOpt.getOptarg();
  388. if (v == null) {
  389. log.severe("Remote Port must have value");
  390. } else {
  391. try {
  392. this.remotePort = Integer.valueOf(v);
  393. } catch (NumberFormatException ex) {
  394. log.log(Level.SEVERE, null, ex);
  395. }
  396. }
  397. this.performTestRun = true;
  398. break;
  399. case 'r':
  400. // local port
  401. v = getOpt.getOptarg();
  402. if (v == null) {
  403. log.severe("Local Port must have value");
  404. } else {
  405. try {
  406. this.localPort = Integer.valueOf(v);
  407. } catch (NumberFormatException ex) {
  408. log.log(Level.SEVERE, null, ex);
  409. }
  410. }
  411. this.performTestRun = true;
  412. break;
  413. case 't':
  414. // concurrent calls
  415. v = getOpt.getOptarg();
  416. if (v == null) {
  417. log.severe("Concurrent Calls must have value");
  418. } else {
  419. try {
  420. this.maxConcurrentCalls = Integer.valueOf(v);
  421. } catch (NumberFormatException ex) {
  422. log.log(Level.SEVERE, null, ex);
  423. }
  424. }
  425. this.performTestRun = true;
  426. break;
  427. case 'y':
  428. // max calls
  429. v = getOpt.getOptarg();
  430. if (v == null) {
  431. log.severe("Max Calls must have value");
  432. } else {
  433. try {
  434. this.maxCalls = Integer.valueOf(v);
  435. } catch (NumberFormatException ex) {
  436. log.log(Level.SEVERE, null, ex);
  437. }
  438. }
  439. this.performTestRun = true;
  440. break;
  441. case 'u':
  442. // data dir
  443. v = getOpt.getOptarg();
  444. if (v == null) {
  445. log.severe("Data Dir must have value");
  446. } else {
  447. this.dataDumpDir = new File(v);
  448. }
  449. //this.performTestRun = true;
  450. break;
  451. case 'i':
  452. // audio file
  453. v = getOpt.getOptarg();
  454. if (v == null) {
  455. log.severe("Audio File URL must have value");
  456. } else {
  457. try {
  458. new URL(v);
  459. this.audioFileURL = v;
  460. } catch (Exception ex) {
  461. log.log(Level.SEVERE, null, ex);
  462. }
  463. }
  464. this.performTestRun = true;
  465. break;
  466. case 'o':
  467. v = getOpt.getOptarg();
  468. if (v == null) {
  469. log.severe("Audio Codec must have value");
  470. } else {
  471. try {
  472. this.convertCodec(v);
  473. } catch (Exception ex) {
  474. log.log(Level.SEVERE, null, ex);
  475. }
  476. }
  477. this.performTestRun = true;
  478. break;
  479. case 'p':
  480. v = getOpt.getOptarg();
  481. if (v == null) {
  482. log.severe("Test Type must have value");
  483. } else {
  484. try {
  485. this.convertTest(v);
  486. } catch (Exception ex) {
  487. log.log(Level.SEVERE, null, ex);
  488. }
  489. }
  490. this.performTestRun = true;
  491. break;
  492. case 'a':
  493. v = getOpt.getOptarg();
  494. if (v == null) {
  495. log.severe("Test Type must have value");
  496. } else {
  497. try {
  498. this.cps = Integer.valueOf(v);
  499. } catch (Exception ex) {
  500. log.log(Level.SEVERE, null, ex);
  501. }
  502. }
  503. this.performTestRun = true;
  504. break;
  505. case 'f':
  506. v = getOpt.getOptarg();
  507. if (v == null) {
  508. log.severe("Max Failure Calls must have value");
  509. } else {
  510. try {
  511. this.maxFailCalls = Integer.valueOf(v);
  512. } catch (Exception ex) {
  513. log.log(Level.SEVERE, null, ex);
  514. }
  515. }
  516. this.performTestRun = true;
  517. break;
  518. case 'l':
  519. v = getOpt.getOptarg();
  520. if (v == null) {
  521. log.severe("Call Duration must have value");
  522. } else {
  523. try {
  524. this.callDuration = Long.valueOf(v);
  525. } catch (Exception ex) {
  526. log.log(Level.SEVERE, null, ex);
  527. }
  528. }
  529. this.performTestRun = true;
  530. break;
  531. case 'g':
  532. this.performOfflineDumps = true;
  533. v = getOpt.getOptarg();
  534. if(v == null)
  535. {
  536. this.callSequenceToDump = -1;
  537. }else
  538. {
  539. this.callSequenceToDump = Long.valueOf(v);
  540. }
  541. break;
  542. default:
  543. log.severe("Wrong parameter!! ---> " + Character.toString((char) c));
  544. }
  545. }
  546. }
  547. }
  548. enum TestTypeEnum {
  549. AnnTest;
  550. public static TestTypeEnum fromString(String v) {
  551. if (v.equals(AnnTest.toString())) {
  552. return AnnTest;
  553. }
  554. throw new RuntimeException("There is no such test type, valid are: " + AnnTest + ", value passed:" + v);
  555. }
  556. public AbstractTestCase getTestCaseForType(CallDisplayInterface cdi) throws IllegalStateException, SocketException, IOException {
  557. if (this.toString().equals(AnnTest.toString())) {
  558. AnnouncementTest at = new AnnouncementTest();
  559. at.setCallDisplay(cdi);
  560. return at;
  561. }
  562. throw new RuntimeException("There is no such test type: " + this);
  563. }
  564. }