test.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*
  2. test.c -- Unit test program for GoAhead
  3. Usage: goahead-test [options] [documents] [endpoints...]
  4. Options:
  5. --auth authFile # User and role configuration
  6. --home directory # Change to directory to run
  7. --log logFile:level # Log to file file at verbosity level
  8. --route routeFile # Route configuration file
  9. --verbose # Same as --log stderr:2
  10. --version # Output version information
  11. Copyright (c) All Rights Reserved. See details at the end of the file.
  12. */
  13. /********************************* Includes ***********************************/
  14. #include "goahead.h"
  15. #include "js.h"
  16. /********************************* Defines ************************************/
  17. static int finished = 0;
  18. #undef ME_GOAHEAD_LISTEN
  19. /*
  20. These must match TOP.es.set
  21. */
  22. #if TEST_IPV6
  23. #if ME_COM_SSL
  24. #define ME_GOAHEAD_LISTEN "http://127.0.0.1:18080, https://127.0.0.1:14443, http://[::1]:18090, https://[::1]:14453"
  25. #else
  26. #define ME_GOAHEAD_LISTEN "http://127.0.0.1:18080, http://[::1]:18090"
  27. #endif
  28. #else
  29. #if ME_COM_SSL
  30. #define ME_GOAHEAD_LISTEN "http://127.0.0.1:18080, https://127.0.0.1:14443"
  31. #else
  32. #define ME_GOAHEAD_LISTEN "http://127.0.0.1:18080"
  33. #endif
  34. #endif
  35. /********************************* Forwards ***********************************/
  36. static void initPlatform();
  37. static void logHeader();
  38. static void usage();
  39. static bool testHandler(Webs *wp);
  40. #if ME_GOAHEAD_JAVASCRIPT
  41. static int aspTest(int eid, Webs *wp, int argc, char **argv);
  42. static int bigTest(int eid, Webs *wp, int argc, char **argv);
  43. #endif
  44. static void actionTest(Webs *wp);
  45. static void sessionTest(Webs *wp);
  46. static void showTest(Webs *wp);
  47. #if ME_GOAHEAD_UPLOAD && !ME_ROM
  48. static void uploadTest(Webs *wp);
  49. #endif
  50. #if ME_GOAHEAD_LEGACY
  51. static int legacyTest(Webs *wp, char *prefix, char *dir, int flags);
  52. #endif
  53. #if ME_UNIX_LIKE
  54. static void sigHandler(int signo);
  55. #endif
  56. static void exitProc(void *data, int id);
  57. /*********************************** Code *************************************/
  58. MAIN(goahead, int argc, char **argv, char **envp)
  59. {
  60. char *argp, *auth, *home, *documents, *endpoints, *endpoint, *route, *tok, *lspec;
  61. int argind, duration;
  62. route = "route.txt";
  63. auth = "auth.txt";
  64. duration = 0;
  65. for (argind = 1; argind < argc; argind++) {
  66. argp = argv[argind];
  67. if (*argp != '-') {
  68. break;
  69. } else if (smatch(argp, "--auth") || smatch(argp, "-a")) {
  70. if (argind >= argc) usage();
  71. auth = argv[++argind];
  72. #if ME_UNIX_LIKE && !MACOSX
  73. } else if (smatch(argp, "--background") || smatch(argp, "-b")) {
  74. websSetBackground(1);
  75. #endif
  76. } else if (smatch(argp, "--debugger") || smatch(argp, "-d") || smatch(argp, "-D")) {
  77. websSetDebug(1);
  78. } else if (smatch(argp, "--duration")) {
  79. if (argind >= argc) usage();
  80. duration = atoi(argv[++argind]);
  81. } else if (smatch(argp, "--home")) {
  82. if (argind >= argc) usage();
  83. home = argv[++argind];
  84. if (chdir(home) < 0) {
  85. error("Cannot change directory to %s", home);
  86. exit(-1);
  87. }
  88. } else if (smatch(argp, "--log") || smatch(argp, "-l")) {
  89. if (argind >= argc) usage();
  90. logSetPath(argv[++argind]);
  91. } else if (smatch(argp, "--verbose") || smatch(argp, "-v")) {
  92. logSetPath("stdout:2");
  93. } else if (smatch(argp, "--route") || smatch(argp, "-r")) {
  94. route = argv[++argind];
  95. } else if (smatch(argp, "--version") || smatch(argp, "-V")) {
  96. printf("%s\n", ME_VERSION);
  97. exit(0);
  98. } else if (*argp == '-' && isdigit((uchar) argp[1])) {
  99. lspec = sfmt("stdout:%s", &argp[1]);
  100. logSetPath(lspec);
  101. wfree(lspec);
  102. } else {
  103. usage();
  104. }
  105. }
  106. documents = ME_GOAHEAD_DOCUMENTS;
  107. if (argc > argind) {
  108. documents = argv[argind++];
  109. }
  110. initPlatform();
  111. if (websOpen(documents, route) < 0) {
  112. error("Cannot initialize server. Exiting.");
  113. return -1;
  114. }
  115. logHeader();
  116. if (websLoad(auth) < 0) {
  117. error("Cannot load %s", auth);
  118. return -1;
  119. }
  120. if (argind < argc) {
  121. while (argind < argc) {
  122. endpoint = argv[argind++];
  123. if (websListen(endpoint) < 0) {
  124. return -1;
  125. }
  126. }
  127. } else {
  128. endpoints = sclone(ME_GOAHEAD_LISTEN);
  129. for (endpoint = stok(endpoints, ", \t", &tok); endpoint; endpoint = stok(NULL, ", \t,", &tok)) {
  130. if (getenv("TRAVIS")) {
  131. if (strstr(endpoint, "::1") != 0) {
  132. /* Travis CI does not support IPv6 */
  133. continue;
  134. }
  135. }
  136. if (websListen(endpoint) < 0) {
  137. return -1;
  138. }
  139. }
  140. wfree(endpoints);
  141. }
  142. websDefineHandler("test", testHandler, 0, 0, 0);
  143. websAddRoute("/test", "test", 0);
  144. #if ME_GOAHEAD_LEGACY
  145. websUrlHandlerDefine("/legacy/", 0, 0, legacyTest, 0);
  146. #endif
  147. #if ME_GOAHEAD_JAVASCRIPT
  148. websDefineJst("aspTest", aspTest);
  149. websDefineJst("bigTest", bigTest);
  150. #endif
  151. websDefineAction("test", actionTest);
  152. websDefineAction("sessionTest", sessionTest);
  153. websDefineAction("showTest", showTest);
  154. #if ME_GOAHEAD_UPLOAD && !ME_ROM
  155. websDefineAction("uploadTest", uploadTest);
  156. #endif
  157. #if ME_UNIX_LIKE && !MACOSX
  158. /*
  159. Service events till terminated
  160. */
  161. if (websGetBackground()) {
  162. if (daemon(0, 0) < 0) {
  163. error("Cannot run as daemon");
  164. return -1;
  165. }
  166. }
  167. #endif
  168. if (duration) {
  169. printf("Running for %d secs\n", duration);
  170. websStartEvent(duration * 1000, (WebsEventProc) exitProc, 0);
  171. }
  172. websServiceEvents(&finished);
  173. logmsg(1, "Instructed to exit\n");
  174. websClose();
  175. return 0;
  176. }
  177. static void exitProc(void *data, int id)
  178. {
  179. websStopEvent(id);
  180. finished = 1;
  181. }
  182. static void logHeader()
  183. {
  184. char home[ME_GOAHEAD_LIMIT_STRING];
  185. getcwd(home, sizeof(home));
  186. logmsg(2, "Configuration for %s", ME_TITLE);
  187. logmsg(2, "---------------------------------------------");
  188. logmsg(2, "Version: %s", ME_VERSION);
  189. logmsg(2, "BuildType: %s", ME_DEBUG ? "Debug" : "Release");
  190. logmsg(2, "CPU: %s", ME_CPU);
  191. logmsg(2, "OS: %s", ME_OS);
  192. logmsg(2, "Host: %s", websGetServer());
  193. logmsg(2, "Directory: %s", home);
  194. logmsg(2, "Documents: %s", websGetDocuments());
  195. logmsg(2, "Configure: %s", ME_CONFIG_CMD);
  196. logmsg(2, "---------------------------------------------");
  197. }
  198. static void usage() {
  199. fprintf(stderr, "\n%s Usage:\n\n"
  200. " %s [options] [documents] [IPaddress][:port]...\n\n"
  201. " Options:\n"
  202. " --auth authFile # User and role configuration\n"
  203. #if ME_UNIX_LIKE && !MACOSX
  204. " --background # Run as a Unix daemon\n"
  205. #endif
  206. " --debugger # Run in debug mode\n"
  207. " --home directory # Change to directory to run\n"
  208. " --log logFile:level # Log to file file at verbosity level\n"
  209. " --route routeFile # Route configuration file\n"
  210. " --verbose # Same as --log stderr:2\n"
  211. " --version # Output version information\n\n",
  212. ME_TITLE, ME_NAME);
  213. exit(-1);
  214. }
  215. void initPlatform()
  216. {
  217. #if ME_UNIX_LIKE
  218. printf("===> ME_UNIX_LIKE\n");
  219. signal(SIGINT, sigHandler);
  220. signal(SIGTERM, sigHandler);
  221. signal(SIGKILL, sigHandler);
  222. #ifdef SIGPIPE
  223. signal(SIGPIPE, SIG_IGN);
  224. #endif
  225. #elif ME_WIN_LIKE
  226. _fmode=_O_BINARY;
  227. #endif
  228. }
  229. #if ME_UNIX_LIKE
  230. static void sigHandler(int signo)
  231. {
  232. finished = 1;
  233. }
  234. #endif
  235. /*
  236. Simple handler and route test
  237. Note: Accesses to "/" are normally remapped automatically to /index.html
  238. */
  239. static bool testHandler(Webs *wp)
  240. {
  241. if (smatch(wp->path, "/")) {
  242. websRewriteRequest(wp, "/home.html");
  243. /* Fall through */
  244. }
  245. return 0;
  246. }
  247. #if ME_GOAHEAD_JAVASCRIPT
  248. /*
  249. Parse the form variables: name, address and echo back
  250. */
  251. static int aspTest(int eid, Webs *wp, int argc, char **argv)
  252. {
  253. char *name, *address;
  254. if (jsArgs(argc, argv, "%s %s", &name, &address) < 2) {
  255. websError(wp, 400, "Insufficient args\n");
  256. return -1;
  257. }
  258. return (int) websWrite(wp, "Name: %s, Address %s", name, address);
  259. }
  260. /*
  261. Generate a large response
  262. */
  263. static int bigTest(int eid, Webs *wp, int argc, char **argv)
  264. {
  265. int i;
  266. websSetStatus(wp, 200);
  267. websWriteHeaders(wp, -1, 0);
  268. websWriteEndHeaders(wp);
  269. websWrite(wp, "<html>\n");
  270. for (i = 0; i < 800; i++) {
  271. websWrite(wp, " Line: %05d %s", i, "aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccccddddddd<br/>\r\n");
  272. }
  273. websWrite(wp, "</html>\n");
  274. websDone(wp);
  275. return 0;
  276. }
  277. #endif
  278. /*
  279. Implement /action/actionTest. Parse the form variables: name, address and echo back.
  280. */
  281. static void actionTest(Webs *wp)
  282. {
  283. char *name, *address;
  284. name = websGetVar(wp, "name", NULL);
  285. address = websGetVar(wp, "address", NULL);
  286. websSetStatus(wp, 200);
  287. websWriteHeaders(wp, -1, 0);
  288. websWriteEndHeaders(wp);
  289. websWrite(wp, "<html><body><h2>name: %s, address: %s</h2></body></html>\n", name, address);
  290. websFlush(wp, 0);
  291. websDone(wp);
  292. }
  293. static void sessionTest(Webs *wp)
  294. {
  295. char *number;
  296. if (scaselessmatch(wp->method, "POST")) {
  297. number = websGetVar(wp, "number", 0);
  298. websSetSessionVar(wp, "number", number);
  299. } else {
  300. number = websGetSessionVar(wp, "number", 0);
  301. }
  302. websSetStatus(wp, 200);
  303. websWriteHeaders(wp, -1, 0);
  304. websWriteEndHeaders(wp);
  305. websWrite(wp, "<html><body><p>Number %s</p></body></html>\n", number);
  306. websDone(wp);
  307. }
  308. static void showTest(Webs *wp)
  309. {
  310. WebsKey *s;
  311. websSetStatus(wp, 200);
  312. websWriteHeaders(wp, -1, 0);
  313. websWriteEndHeaders(wp);
  314. websWrite(wp, "<html><body><pre>\n");
  315. for (s = hashFirst(wp->vars); s; s = hashNext(wp->vars, s)) {
  316. websWrite(wp, "%s=%s\n", s->name.value.string, s->content.value.string);
  317. }
  318. websWrite(wp, "</pre></body></html>\n");
  319. websDone(wp);
  320. }
  321. #if ME_GOAHEAD_UPLOAD && !ME_ROM
  322. /*
  323. Dump the file upload details. Don't actually do anything with the uploaded file.
  324. */
  325. static void uploadTest(Webs *wp)
  326. {
  327. WebsKey *s;
  328. WebsUpload *up;
  329. char *upfile;
  330. printf("<>>>>>>>>>>come in >>>>>>>>>>>\n");
  331. websSetStatus(wp, 200);
  332. websWriteHeaders(wp, -1, 0);
  333. websWriteHeader(wp, "Content-Type", "text/plain");
  334. websWriteEndHeaders(wp);
  335. if (scaselessmatch(wp->method, "POST")) {
  336. for (s = hashFirst(wp->files); s; s = hashNext(wp->files, s)) {
  337. up = s->content.value.symbol;
  338. websWrite(wp, "FILE: %s\r\n", s->name.value.string);
  339. websWrite(wp, "FILENAME=%s\r\n", up->filename);
  340. websWrite(wp, "CLIENT=%s\r\n", up->clientFilename);
  341. websWrite(wp, "TYPE=%s\r\n", up->contentType);
  342. websWrite(wp, "SIZE=%d\r\n", up->size);
  343. upfile = sfmt("%s/tmp/%s", websGetDocuments(), up->clientFilename);
  344. if (rename(up->filename, upfile) < 0) {
  345. error("Cannot rename uploaded file: %s to %s, errno %d", up->filename, upfile, errno);
  346. }
  347. wfree(upfile);
  348. }
  349. websWrite(wp, "\r\nVARS:\r\n");
  350. for (s = hashFirst(wp->vars); s; s = hashNext(wp->vars, s)) {
  351. websWrite(wp, "%s=%s\r\n", s->name.value.string, s->content.value.string);
  352. }
  353. }
  354. websDone(wp);
  355. }
  356. #endif
  357. #if ME_GOAHEAD_LEGACY
  358. /*
  359. Legacy handler with old parameter sequence
  360. */
  361. static int legacyTest(Webs *wp, char *prefix, char *dir, int flags)
  362. {
  363. websSetStatus(wp, 200);
  364. websWriteHeaders(wp, -1, 0);
  365. websWriteHeader(wp, "Content-Type", "text/plain");
  366. websWriteEndHeaders(wp);
  367. websWrite(wp, "Hello Legacy World\n");
  368. websDone(wp);
  369. return 1;
  370. }
  371. #endif
  372. /*
  373. @copy default
  374. Copyright (c) Embedthis Software LLC, 2003-2014. All Rights Reserved.
  375. This software is distributed under commercial and open source licenses.
  376. You may use the Embedthis GoAhead open source license or you may acquire
  377. a commercial license from Embedthis Software. You agree to be fully bound
  378. by the terms of either license. Consult the LICENSE.md distributed with
  379. this software for full details and other copyrights.
  380. Local variables:
  381. tab-width: 4
  382. c-basic-offset: 4
  383. End:
  384. vim: sw=4 ts=4 expandtab
  385. @end
  386. */