xref: /unit/src/test/nxt_unit_app_test.c (revision 1980)
1743Smax.romanov@nginx.com 
2743Smax.romanov@nginx.com /*
3743Smax.romanov@nginx.com  * Copyright (C) NGINX, Inc.
4743Smax.romanov@nginx.com  */
5743Smax.romanov@nginx.com 
6743Smax.romanov@nginx.com #include <nxt_unit.h>
7743Smax.romanov@nginx.com #include <nxt_unit_request.h>
8743Smax.romanov@nginx.com #include <nxt_clang.h>
91669Smax.romanov@nginx.com #include <pthread.h>
101669Smax.romanov@nginx.com #include <string.h>
111669Smax.romanov@nginx.com #include <stdlib.h>
12743Smax.romanov@nginx.com 
13743Smax.romanov@nginx.com 
14743Smax.romanov@nginx.com #define CONTENT_TYPE  "Content-Type"
15743Smax.romanov@nginx.com #define TEXT_PLAIN    "text/plain"
16743Smax.romanov@nginx.com #define HELLO_WORLD   "Hello world!\n"
17743Smax.romanov@nginx.com 
18743Smax.romanov@nginx.com #define NEW_LINE      "\n"
19743Smax.romanov@nginx.com 
20743Smax.romanov@nginx.com #define REQUEST_DATA  "Request data:\n"
21743Smax.romanov@nginx.com #define METHOD        "  Method: "
22743Smax.romanov@nginx.com #define PROTOCOL      "  Protocol: "
23743Smax.romanov@nginx.com #define REMOTE_ADDR   "  Remote addr: "
24743Smax.romanov@nginx.com #define LOCAL_ADDR    "  Local addr: "
25743Smax.romanov@nginx.com #define TARGET        "  Target: "
26743Smax.romanov@nginx.com #define PATH          "  Path: "
27743Smax.romanov@nginx.com #define QUERY         "  Query: "
28743Smax.romanov@nginx.com #define FIELDS        "  Fields:\n"
29743Smax.romanov@nginx.com #define FIELD_PAD     "    "
30743Smax.romanov@nginx.com #define FIELD_SEP     ": "
31743Smax.romanov@nginx.com #define BODY          "  Body:\n"
32743Smax.romanov@nginx.com 
33743Smax.romanov@nginx.com 
341669Smax.romanov@nginx.com static int ready_handler(nxt_unit_ctx_t *ctx);
351669Smax.romanov@nginx.com static void *worker(void *main_ctx);
361669Smax.romanov@nginx.com static void greeting_app_request_handler(nxt_unit_request_info_t *req);
371669Smax.romanov@nginx.com static inline char *copy(char *p, const void *src, uint32_t len);
381669Smax.romanov@nginx.com 
391669Smax.romanov@nginx.com 
401669Smax.romanov@nginx.com static int        thread_count;
411669Smax.romanov@nginx.com static pthread_t  *threads;
421669Smax.romanov@nginx.com 
431669Smax.romanov@nginx.com 
441669Smax.romanov@nginx.com int
451669Smax.romanov@nginx.com main(int argc, char **argv)
46743Smax.romanov@nginx.com {
471669Smax.romanov@nginx.com     int              i, err;
481669Smax.romanov@nginx.com     nxt_unit_ctx_t   *ctx;
491669Smax.romanov@nginx.com     nxt_unit_init_t  init;
501669Smax.romanov@nginx.com 
511669Smax.romanov@nginx.com     if (argc == 3 && strcmp(argv[1], "-t") == 0) {
521669Smax.romanov@nginx.com         thread_count = atoi(argv[2]);
531669Smax.romanov@nginx.com     }
541669Smax.romanov@nginx.com 
551669Smax.romanov@nginx.com     memset(&init, 0, sizeof(nxt_unit_init_t));
561669Smax.romanov@nginx.com 
571669Smax.romanov@nginx.com     init.callbacks.request_handler = greeting_app_request_handler;
581669Smax.romanov@nginx.com     init.callbacks.ready_handler = ready_handler;
591669Smax.romanov@nginx.com 
601669Smax.romanov@nginx.com     ctx = nxt_unit_init(&init);
611669Smax.romanov@nginx.com     if (ctx == NULL) {
621669Smax.romanov@nginx.com         return 1;
631669Smax.romanov@nginx.com     }
641669Smax.romanov@nginx.com 
651669Smax.romanov@nginx.com     err = nxt_unit_run(ctx);
661669Smax.romanov@nginx.com 
671669Smax.romanov@nginx.com     nxt_unit_debug(ctx, "main worker finished with %d code", err);
681669Smax.romanov@nginx.com 
691669Smax.romanov@nginx.com     if (thread_count > 1) {
701669Smax.romanov@nginx.com         for (i = 0; i < thread_count - 1; i++) {
711669Smax.romanov@nginx.com             err = pthread_join(threads[i], NULL);
721669Smax.romanov@nginx.com 
731676Svbart@nginx.com             if (nxt_fast_path(err == 0)) {
741676Svbart@nginx.com                 nxt_unit_debug(ctx, "join thread #%d", i);
751676Svbart@nginx.com 
761676Svbart@nginx.com             } else {
771676Svbart@nginx.com                 nxt_unit_alert(ctx, "pthread_join(#%d) failed: %s (%d)",
781676Svbart@nginx.com                                     i, strerror(err), err);
791676Svbart@nginx.com             }
801669Smax.romanov@nginx.com         }
811669Smax.romanov@nginx.com 
821669Smax.romanov@nginx.com         nxt_unit_free(ctx, threads);
831669Smax.romanov@nginx.com     }
841669Smax.romanov@nginx.com 
851669Smax.romanov@nginx.com     nxt_unit_done(ctx);
861669Smax.romanov@nginx.com 
871669Smax.romanov@nginx.com     nxt_unit_debug(NULL, "main worker done");
881669Smax.romanov@nginx.com 
891669Smax.romanov@nginx.com     return 0;
901669Smax.romanov@nginx.com }
911669Smax.romanov@nginx.com 
92743Smax.romanov@nginx.com 
931669Smax.romanov@nginx.com static int
941669Smax.romanov@nginx.com ready_handler(nxt_unit_ctx_t *ctx)
951669Smax.romanov@nginx.com {
961669Smax.romanov@nginx.com     int  i, err;
971669Smax.romanov@nginx.com 
981669Smax.romanov@nginx.com     nxt_unit_debug(ctx, "ready");
991669Smax.romanov@nginx.com 
100*1980Smax.romanov@nginx.com     if (thread_count <= 1) {
1011669Smax.romanov@nginx.com         return NXT_UNIT_OK;
1021669Smax.romanov@nginx.com     }
1031669Smax.romanov@nginx.com 
1041669Smax.romanov@nginx.com     threads = nxt_unit_malloc(ctx, sizeof(pthread_t) * (thread_count - 1));
1051669Smax.romanov@nginx.com     if (threads == NULL) {
1061669Smax.romanov@nginx.com         return NXT_UNIT_ERROR;
1071669Smax.romanov@nginx.com     }
1081669Smax.romanov@nginx.com 
1091669Smax.romanov@nginx.com     for (i = 0; i < thread_count - 1; i++) {
1101669Smax.romanov@nginx.com         err = pthread_create(&threads[i], NULL, worker, ctx);
1111669Smax.romanov@nginx.com         if (err != 0) {
1121669Smax.romanov@nginx.com             return NXT_UNIT_ERROR;
1131669Smax.romanov@nginx.com         }
1141669Smax.romanov@nginx.com     }
1151669Smax.romanov@nginx.com 
1161669Smax.romanov@nginx.com     return NXT_UNIT_OK;
1171669Smax.romanov@nginx.com }
1181669Smax.romanov@nginx.com 
1191669Smax.romanov@nginx.com 
1201669Smax.romanov@nginx.com static void *
1211669Smax.romanov@nginx.com worker(void *main_ctx)
1221669Smax.romanov@nginx.com {
1231669Smax.romanov@nginx.com     int             rc;
1241669Smax.romanov@nginx.com     nxt_unit_ctx_t  *ctx;
1251669Smax.romanov@nginx.com 
1261669Smax.romanov@nginx.com     ctx = nxt_unit_ctx_alloc(main_ctx, NULL);
1271669Smax.romanov@nginx.com     if (ctx == NULL) {
1281669Smax.romanov@nginx.com         return NULL;
1291669Smax.romanov@nginx.com     }
1301669Smax.romanov@nginx.com 
1311669Smax.romanov@nginx.com     nxt_unit_debug(ctx, "start worker");
1321669Smax.romanov@nginx.com 
1331669Smax.romanov@nginx.com     rc = nxt_unit_run(ctx);
1341669Smax.romanov@nginx.com 
1351669Smax.romanov@nginx.com     nxt_unit_debug(ctx, "worker finished with %d code", rc);
1361669Smax.romanov@nginx.com 
1371669Smax.romanov@nginx.com     nxt_unit_done(ctx);
1381669Smax.romanov@nginx.com 
1391676Svbart@nginx.com     return (void *) (intptr_t) rc;
140743Smax.romanov@nginx.com }
141743Smax.romanov@nginx.com 
142743Smax.romanov@nginx.com 
143743Smax.romanov@nginx.com static void
144743Smax.romanov@nginx.com greeting_app_request_handler(nxt_unit_request_info_t *req)
145743Smax.romanov@nginx.com {
146743Smax.romanov@nginx.com     int                 rc;
147743Smax.romanov@nginx.com     char                *p;
148743Smax.romanov@nginx.com     ssize_t             res;
149743Smax.romanov@nginx.com     uint32_t            i;
150743Smax.romanov@nginx.com     nxt_unit_buf_t      *buf;
151743Smax.romanov@nginx.com     nxt_unit_field_t    *f;
152743Smax.romanov@nginx.com     nxt_unit_request_t  *r;
153743Smax.romanov@nginx.com 
154743Smax.romanov@nginx.com     rc = nxt_unit_response_init(req, 200 /* Status code. */,
155743Smax.romanov@nginx.com                                 1 /* Number of response headers. */,
156743Smax.romanov@nginx.com                                 nxt_length(CONTENT_TYPE)
157743Smax.romanov@nginx.com                                 + nxt_length(TEXT_PLAIN)
158743Smax.romanov@nginx.com                                 + nxt_length(HELLO_WORLD));
159743Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
160743Smax.romanov@nginx.com         goto fail;
161743Smax.romanov@nginx.com     }
162743Smax.romanov@nginx.com 
163743Smax.romanov@nginx.com     rc = nxt_unit_response_add_field(req,
164743Smax.romanov@nginx.com                                      CONTENT_TYPE, nxt_length(CONTENT_TYPE),
165743Smax.romanov@nginx.com                                      TEXT_PLAIN, nxt_length(TEXT_PLAIN));
166743Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
167743Smax.romanov@nginx.com         goto fail;
168743Smax.romanov@nginx.com     }
169743Smax.romanov@nginx.com 
170743Smax.romanov@nginx.com     rc = nxt_unit_response_add_content(req, HELLO_WORLD,
171743Smax.romanov@nginx.com                                        nxt_length(HELLO_WORLD));
172743Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
173743Smax.romanov@nginx.com         goto fail;
174743Smax.romanov@nginx.com     }
175743Smax.romanov@nginx.com 
176743Smax.romanov@nginx.com     rc = nxt_unit_response_send(req);
177743Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
178743Smax.romanov@nginx.com         goto fail;
179743Smax.romanov@nginx.com     }
180743Smax.romanov@nginx.com 
181743Smax.romanov@nginx.com     r = req->request;
182743Smax.romanov@nginx.com 
183743Smax.romanov@nginx.com     buf = nxt_unit_response_buf_alloc(req, (req->request_buf->end
184743Smax.romanov@nginx.com                                             - req->request_buf->start)
185743Smax.romanov@nginx.com                                       + nxt_length(REQUEST_DATA)
186743Smax.romanov@nginx.com                                       + nxt_length(METHOD)
187743Smax.romanov@nginx.com                                       + nxt_length(NEW_LINE)
188743Smax.romanov@nginx.com                                       + nxt_length(PROTOCOL)
189743Smax.romanov@nginx.com                                       + nxt_length(NEW_LINE)
190743Smax.romanov@nginx.com                                       + nxt_length(REMOTE_ADDR)
191743Smax.romanov@nginx.com                                       + nxt_length(NEW_LINE)
192743Smax.romanov@nginx.com                                       + nxt_length(LOCAL_ADDR)
193743Smax.romanov@nginx.com                                       + nxt_length(NEW_LINE)
194743Smax.romanov@nginx.com                                       + nxt_length(TARGET)
195743Smax.romanov@nginx.com                                       + nxt_length(NEW_LINE)
196743Smax.romanov@nginx.com                                       + nxt_length(PATH)
197743Smax.romanov@nginx.com                                       + nxt_length(NEW_LINE)
198743Smax.romanov@nginx.com                                       + nxt_length(QUERY)
199743Smax.romanov@nginx.com                                       + nxt_length(NEW_LINE)
200743Smax.romanov@nginx.com                                       + nxt_length(FIELDS)
201743Smax.romanov@nginx.com                                       + r->fields_count * (
202743Smax.romanov@nginx.com                                           nxt_length(FIELD_PAD)
203743Smax.romanov@nginx.com                                           + nxt_length(FIELD_SEP))
204743Smax.romanov@nginx.com                                       + nxt_length(BODY));
205743Smax.romanov@nginx.com     if (nxt_slow_path(buf == NULL)) {
206743Smax.romanov@nginx.com         rc = NXT_UNIT_ERROR;
207743Smax.romanov@nginx.com 
208743Smax.romanov@nginx.com         goto fail;
209743Smax.romanov@nginx.com     }
210743Smax.romanov@nginx.com 
211743Smax.romanov@nginx.com     p = buf->free;
212743Smax.romanov@nginx.com 
213743Smax.romanov@nginx.com     p = copy(p, REQUEST_DATA, nxt_length(REQUEST_DATA));
214743Smax.romanov@nginx.com 
215743Smax.romanov@nginx.com     p = copy(p, METHOD, nxt_length(METHOD));
216743Smax.romanov@nginx.com     p = copy(p, nxt_unit_sptr_get(&r->method), r->method_length);
217743Smax.romanov@nginx.com     *p++ = '\n';
218743Smax.romanov@nginx.com 
219743Smax.romanov@nginx.com     p = copy(p, PROTOCOL, nxt_length(PROTOCOL));
220743Smax.romanov@nginx.com     p = copy(p, nxt_unit_sptr_get(&r->version), r->version_length);
221743Smax.romanov@nginx.com     *p++ = '\n';
222743Smax.romanov@nginx.com 
223743Smax.romanov@nginx.com     p = copy(p, REMOTE_ADDR, nxt_length(REMOTE_ADDR));
224743Smax.romanov@nginx.com     p = copy(p, nxt_unit_sptr_get(&r->remote), r->remote_length);
225743Smax.romanov@nginx.com     *p++ = '\n';
226743Smax.romanov@nginx.com 
227743Smax.romanov@nginx.com     p = copy(p, LOCAL_ADDR, nxt_length(LOCAL_ADDR));
228743Smax.romanov@nginx.com     p = copy(p, nxt_unit_sptr_get(&r->local), r->local_length);
229743Smax.romanov@nginx.com     *p++ = '\n';
230743Smax.romanov@nginx.com 
231743Smax.romanov@nginx.com     p = copy(p, TARGET, nxt_length(TARGET));
232743Smax.romanov@nginx.com     p = copy(p, nxt_unit_sptr_get(&r->target), r->target_length);
233743Smax.romanov@nginx.com     *p++ = '\n';
234743Smax.romanov@nginx.com 
235743Smax.romanov@nginx.com     p = copy(p, PATH, nxt_length(PATH));
236743Smax.romanov@nginx.com     p = copy(p, nxt_unit_sptr_get(&r->path), r->path_length);
237743Smax.romanov@nginx.com     *p++ = '\n';
238743Smax.romanov@nginx.com 
239743Smax.romanov@nginx.com     if (r->query.offset) {
240743Smax.romanov@nginx.com         p = copy(p, QUERY, nxt_length(QUERY));
241743Smax.romanov@nginx.com         p = copy(p, nxt_unit_sptr_get(&r->query), r->query_length);
242743Smax.romanov@nginx.com         *p++ = '\n';
243743Smax.romanov@nginx.com     }
244743Smax.romanov@nginx.com 
245743Smax.romanov@nginx.com     p = copy(p, FIELDS, nxt_length(FIELDS));
246743Smax.romanov@nginx.com 
247743Smax.romanov@nginx.com     for (i = 0; i < r->fields_count; i++) {
248743Smax.romanov@nginx.com         f = r->fields + i;
249743Smax.romanov@nginx.com 
250743Smax.romanov@nginx.com         p = copy(p, FIELD_PAD, nxt_length(FIELD_PAD));
251743Smax.romanov@nginx.com         p = copy(p, nxt_unit_sptr_get(&f->name), f->name_length);
252743Smax.romanov@nginx.com         p = copy(p, FIELD_SEP, nxt_length(FIELD_SEP));
253743Smax.romanov@nginx.com         p = copy(p, nxt_unit_sptr_get(&f->value), f->value_length);
254743Smax.romanov@nginx.com         *p++ = '\n';
255743Smax.romanov@nginx.com     }
256743Smax.romanov@nginx.com 
257743Smax.romanov@nginx.com     if (r->content_length > 0) {
258743Smax.romanov@nginx.com         p = copy(p, BODY, nxt_length(BODY));
259743Smax.romanov@nginx.com 
260743Smax.romanov@nginx.com         res = nxt_unit_request_read(req, buf->free, buf->end - buf->free);
261743Smax.romanov@nginx.com         buf->free += res;
262743Smax.romanov@nginx.com 
263743Smax.romanov@nginx.com     }
264743Smax.romanov@nginx.com 
265743Smax.romanov@nginx.com     buf->free = p;
266743Smax.romanov@nginx.com 
267743Smax.romanov@nginx.com     rc = nxt_unit_buf_send(buf);
268743Smax.romanov@nginx.com 
269743Smax.romanov@nginx.com fail:
270743Smax.romanov@nginx.com 
271743Smax.romanov@nginx.com     nxt_unit_request_done(req, rc);
272743Smax.romanov@nginx.com }
273743Smax.romanov@nginx.com 
274743Smax.romanov@nginx.com 
2751669Smax.romanov@nginx.com static inline char *
2761669Smax.romanov@nginx.com copy(char *p, const void *src, uint32_t len)
2771669Smax.romanov@nginx.com {
2781669Smax.romanov@nginx.com     memcpy(p, src, len);
279743Smax.romanov@nginx.com 
2801669Smax.romanov@nginx.com     return p + len;
281743Smax.romanov@nginx.com }
282