Support for split testsuite, launchmon in testsuite
[dyninst.git] / testsuite / src / remotetest.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31 #include "remotetest.h"
32 #include "ParameterDict.h"
33 #include "module.h"
34 #include "test_lib.h"
35
36 #include <cstring>
37 #include <cassert>
38 #include <string>
39
40 using namespace std;
41
42 //#define debug_printf(format, args...) fprintf(stderr, format, ## args)
43 #define debug_printf(format, args...) 
44
45 #define PARAMETER_ARG "PARAMETER"
46 #define TESTRESULT_ARG "TESTRESULT"
47 #define STRING_ARG "STRING"
48 #define GROUP_ARG "GROUP"
49 #define TESTINFO_ARG "TESTINFO"
50 #define BOOL_ARG "BOOL"
51 #define INT_ARG "INT"
52
53 #define COMPONENT_PROGRAM_SETUP "COMP_PROGSETUP"
54 #define COMPONENT_PROGRAM_TEARDOWN "COMP_PROGTEARDOWN"
55 #define COMPONENT_GROUP_SETUP "COMP_GROUPSETUP"
56 #define COMPONENT_GROUP_TEARDOWN "COMP_GROUPTEARDOWN"
57 #define COMPONENT_TEST_SETUP "COMP_TESTSETUP"
58 #define COMPONENT_TEST_TEARDOWN "COMP_TESTTEARDOWN"
59 #define COMPONENT_ERR_MSG "COMP_ERRMESSAGE"
60
61 #define TEST_CUSTOM_PATH "TEST_CUSTOMPATH"
62 #define TEST_SETUP "TEST_SETUP"
63 #define TEST_EXECUTE "TEST_EXECUTE"
64 #define TEST_POST_EXECUTE "TEST_POST_EXECUTE"
65 #define TEST_TEARDOWN "TEST_TEARDOWN"
66
67 #define LOAD_TEST "LOAD_TEST"
68 #define LOAD_COMPONENT "LOAD_COMPONENT"
69 #define RETURN "RETURN"
70 #define LOG "LOG"
71 #define EXIT_MSG "EXIT"
72
73 static char *my_strtok(char *str, const char *delim);
74
75 class MessageBuffer
76 {
77 private:
78    char *buffer;
79    unsigned int size;
80    unsigned int cur;
81 public:
82    MessageBuffer() :
83       buffer(NULL),
84       size(0),
85       cur(0)
86    {
87    }
88
89    ~MessageBuffer() 
90    {
91       if (buffer)
92          free(buffer);
93       buffer = NULL;
94    }
95
96    void add(const char *b, unsigned int b_size)
97    {
98       if (!buffer) {
99          size = (b_size * 2);
100          buffer = (char *) malloc(size);
101       }
102       if (cur + b_size > size) {
103          while (cur + b_size > size)
104             size *= 2;
105          buffer = (char *) realloc(buffer, size);
106       }
107       memcpy(buffer+cur, b, b_size);
108       cur += b_size;
109    }
110
111    char *get_buffer() const {
112       char *new_buffer = (char *) malloc(cur*2);
113       memset(new_buffer, 0xab, cur*2);
114       memcpy(new_buffer, buffer, cur);
115       return new_buffer;
116    }
117
118    unsigned int get_buffer_size() const {
119       return cur;
120    }
121 };
122
123 static void encodeParams(ParameterDict &params, MessageBuffer &buf)
124 {
125    std::string result;
126    
127    result = PARAMETER_ARG + std::string(":");
128    for (ParameterDict::iterator i=params.begin(); i != params.end(); i++) {
129       result += i->first + std::string(":");
130       if (dynamic_cast<ParamString *>(i->second)) 
131       {
132          result += std::string("s:");
133          if (i->second->getString() == NULL) {
134             result += "<NULL>" + std::string(":");
135          }
136          else if (*i->second->getString() == '\0') {
137             result += "<EMPTY>" + std::string(":");
138          }
139          else {
140             result += i->second->getString() + std::string(":");
141          }
142       }
143       if (dynamic_cast<ParamInt *>(i->second)) 
144       {
145          result += std::string("i:");
146          char i_buffer[32];
147          snprintf(i_buffer, 32, "%d:", i->second->getInt());
148          result += i_buffer;
149       }
150       if (dynamic_cast<ParamPtr *>(i->second)) 
151       {
152          result += std::string("p:");
153          char p_buffer[32];
154          snprintf(p_buffer, 32, "%lu:", i->second->getPtr());
155          result += p_buffer;
156       }
157    }
158    result += std::string(";");
159    buf.add(result.c_str(), result.length());
160 }
161
162 static char *decodeParams(ParameterDict &params, char *buffer)
163 {
164    params.clear();
165    char *cur = my_strtok(buffer, ":");
166    assert(strcmp(cur, PARAMETER_ARG) == 0);
167    
168    for (;;) {
169       cur = my_strtok(NULL, ":");
170       if (*cur == ';')
171          break;
172       char *key = strdup(cur);
173       cur = my_strtok(NULL, ":");
174       char *type = strdup(cur);
175       cur = my_strtok(NULL, ":");
176       char *value = strdup(cur);
177       char *orig_value = value;
178
179       switch (*type) {
180          case 's': {
181             if (strcmp(value, "<NULL>") == 0)
182                value = NULL;
183             else if (strcmp(value, "<EMPTY>") == 0)
184                value = "";
185             params[key] = new ParamString(value);
186             break;
187          }
188          case 'i': {
189             int val;
190             sscanf(value, "%d", &val);
191             params[key] = new ParamInt(val);
192             break;
193          }
194          case 'p': {
195             unsigned long val;
196             sscanf(value, "%lu", &val);
197             params[key] = new ParamPtr((void *) val);
198             break;
199          }
200          default:
201             assert(0);
202       }
203       free(key);
204       free(type);
205       free(orig_value);
206    }
207    char *next = strchr(buffer, ';');
208    return next+1;
209 }
210
211 static void encodeTestResult(test_results_t res, MessageBuffer &buf)
212 {
213    char s_buffer[64];
214    snprintf(s_buffer, 64, "%s:%d;", TESTRESULT_ARG, res);
215    buf.add(s_buffer, strlen(s_buffer));
216 }
217
218 static char *decodeTestResult(test_results_t &res, char *buffer)
219 {
220    char *cur = my_strtok(buffer, ":;");
221    assert(strcmp(cur, TESTRESULT_ARG) == 0);
222    cur = my_strtok(NULL, ":;");
223    sscanf(cur, "%d", (int *) &res);
224    return strchr(buffer, ';')+1;
225 }
226
227 static void encodeInt(int i, MessageBuffer &buf)
228 {
229    char s_buffer[64];
230    snprintf(s_buffer, 64, "%s:%d;", INT_ARG, i);
231    buf.add(s_buffer, strlen(s_buffer));
232 }
233
234 static char *decodeInt(int i, char *buffer)
235 {
236    char *cur = my_strtok(buffer, ":;");
237    assert(strcmp(cur, INT_ARG) == 0);
238    cur = my_strtok(NULL, ":;");
239    sscanf(cur, "%d", (int *) &i);
240    return strchr(buffer, ';')+1;
241 }
242
243 static void encodeString(std::string str, MessageBuffer &buf)
244 {
245    buf.add(STRING_ARG, strlen(STRING_ARG));
246    buf.add(":", 1);
247    if (!str.length())
248       buf.add("<EMPTY>", strlen("<EMPTY>"));
249    else
250       buf.add(str.c_str(), str.length());
251    buf.add(";", 1);
252 }
253
254 static char *decodeString(std::string &str, char *buffer)
255 {
256    assert(strncmp(buffer, STRING_ARG, strlen(STRING_ARG)) == 0);
257    char *cur = my_strtok(buffer, ";");
258    cur += strlen(STRING_ARG)+1;
259    if (strncmp(cur, "<EMPTY>", strlen("<EMPTY>")) == 0)
260       str = std::string();
261    else
262       str = std::string(cur);
263    return strchr(cur, ';')+1;
264 }
265
266 static void encodeBool(bool b, MessageBuffer &buf)
267 {
268    buf.add(BOOL_ARG, strlen(BOOL_ARG));
269    buf.add(":", 1);
270    string str = b ? "true" : "false";
271    buf.add(str.c_str(), str.length());
272    buf.add(";", 1);
273 }
274
275 static char *decodeBool(bool &b, char *buffer)
276 {
277    char *cur = my_strtok(buffer, ":;");
278    assert(strcmp(cur, BOOL_ARG) == 0);
279    cur = my_strtok(NULL, ":;");
280    string str = std::string(cur);
281    if (str == "true") {
282       b = true;
283    }
284    else if (str == "false") {
285       b = false;
286    }
287    else {
288       assert(0);
289    }
290    return strchr(buffer, ';')+1;
291 }
292
293 static void encodeGroup(RunGroup *group, MessageBuffer &buf)
294 {
295    char s_buffer[64];
296    snprintf(s_buffer, 64, "%s:%d;", GROUP_ARG, group->index);
297    buf.add(s_buffer, strlen(s_buffer));
298 }
299
300 static char *decodeGroup(RunGroup* &group, vector<RunGroup *> &groups, char *buffer)
301 {
302    char *cur = my_strtok(buffer, ":;");
303    assert(strcmp(cur, GROUP_ARG) == 0);
304    int group_index;
305    cur = my_strtok(NULL, ":;");
306    sscanf(cur, "%d", &group_index);
307    assert(group_index >= 0 && group_index < groups.size());
308    group = groups[group_index];
309    return strchr(buffer, ';')+1;
310 }
311
312 static void encodeTest(TestInfo *test, MessageBuffer &buf)
313 {
314    char s_buffer[128];
315    snprintf(s_buffer, 128, "%s:%d:%d;", TESTINFO_ARG, test->group_index, test->index);
316    buf.add(s_buffer, strlen(s_buffer));
317 }
318
319 static char *decodeTest(TestInfo* &test, vector<RunGroup *> &groups, char *buffer)
320 {
321    char *cur = my_strtok(buffer, ":;");
322    assert(strcmp(cur, TESTINFO_ARG) == 0);
323    int group_index, test_index;
324
325    cur = my_strtok(NULL, ":;");
326    sscanf(cur, "%d", &group_index);
327    assert(group_index >= 0 && group_index < groups.size());
328    RunGroup *group = groups[group_index];
329
330    cur = my_strtok(NULL, ":;");
331    sscanf(cur, "%d", &test_index);
332    assert(test_index >= 0 && test_index < group->tests.size());
333    
334    test = group->tests[test_index];
335
336    return strchr(buffer, ';')+1;
337 }
338
339 static void comp_header(std::string name, MessageBuffer &buffer, char *call)
340 {
341    buffer.add("C;", 2);
342    buffer.add(call, strlen(call));
343    buffer.add(";", 1);
344    buffer.add(name.c_str(), strlen(name.c_str()));
345    buffer.add(";", 1);   
346 }
347
348 static void test_header(TestInfo *test, MessageBuffer &buffer, char *call)
349 {
350    buffer.add("T;", 2);
351    buffer.add(call, strlen(call));
352    buffer.add(";", 1);
353    char str[128];
354    snprintf(str, 128, "%d:%d;", test->group_index, test->index);
355    buffer.add(str, strlen(str));
356 }
357
358 static void load_header(MessageBuffer &buffer, std::string name)
359 {
360    buffer.add("L;", 2);
361    buffer.add(name.c_str(), name.length());
362    buffer.add(";", 1);
363 }
364
365 static void exit_header(MessageBuffer &buffer)
366 {
367    buffer.add("X;", 2);
368    buffer.add(EXIT_MSG, strlen(EXIT_MSG));
369 }
370
371 static void return_header(MessageBuffer &buffer)
372 {
373    buffer.add("R;", 2);
374 }
375
376 static void message_header(MessageBuffer &buffer) 
377 {
378    buffer.add("M;", 2);
379 }
380
381 test_results_t RemoteComponentFE::program_setup(ParameterDict &params)
382 {
383    MessageBuffer buffer;
384    comp_header(name, buffer, COMPONENT_PROGRAM_SETUP);
385    encodeParams(params, buffer);
386
387    connection->send_message(buffer);
388    char *result_msg;
389    connection->recv_return(result_msg);
390
391    char *next_ret = decodeParams(params, result_msg);
392    test_results_t result;
393    decodeTestResult(result, next_ret);
394
395    return result;
396 }
397
398 test_results_t RemoteComponentFE::program_teardown(ParameterDict &params)
399 {
400    MessageBuffer buffer;
401    comp_header(name, buffer, COMPONENT_PROGRAM_TEARDOWN);
402    encodeParams(params, buffer);
403
404    connection->send_message(buffer);
405    char *result_msg;
406    connection->recv_return(result_msg);
407
408    char *next_ret = decodeParams(params, result_msg);
409    test_results_t result;
410    decodeTestResult(result, next_ret);
411
412    return result;
413 }
414
415 test_results_t RemoteComponentFE::group_setup(RunGroup *group, ParameterDict &params)
416 {
417    MessageBuffer buffer;
418    comp_header(name, buffer, COMPONENT_GROUP_SETUP);
419
420    encodeGroup(group, buffer);
421    encodeParams(params, buffer);
422
423    connection->send_message(buffer);
424    char *result_msg;
425    connection->recv_return(result_msg);
426
427    char *next_ret = decodeParams(params, result_msg);
428    test_results_t result;
429    decodeTestResult(result, next_ret);
430
431    return result;   
432 }
433
434 test_results_t RemoteComponentFE::group_teardown(RunGroup *group, ParameterDict &params)
435 {
436    MessageBuffer buffer;
437    comp_header(name, buffer, COMPONENT_GROUP_TEARDOWN);
438
439    encodeGroup(group, buffer);
440    encodeParams(params, buffer);
441
442    connection->send_message(buffer);
443    char *result_msg;
444    connection->recv_return(result_msg);
445
446    char *next_ret = decodeParams(params, result_msg);
447    test_results_t result;
448    decodeTestResult(result, next_ret);
449
450    return result;
451 }
452
453 test_results_t RemoteComponentFE::test_setup(TestInfo *test, ParameterDict &params)
454 {
455    MessageBuffer buffer;
456    comp_header(name, buffer, COMPONENT_TEST_SETUP);
457
458    encodeTest(test, buffer);
459    encodeParams(params, buffer);
460
461    connection->send_message(buffer);
462    char *result_msg;
463    connection->recv_return(result_msg);
464
465    char *next_ret = decodeParams(params, result_msg);
466    test_results_t result;
467    decodeTestResult(result, next_ret);
468
469    return result;      
470 }
471
472 test_results_t RemoteComponentFE::test_teardown(TestInfo *test, ParameterDict &params)
473 {
474    MessageBuffer buffer;
475    comp_header(name, buffer, COMPONENT_TEST_TEARDOWN);
476
477    encodeTest(test, buffer);
478    encodeParams(params, buffer);
479
480    connection->send_message(buffer);
481    char *result_msg;
482    connection->recv_return(result_msg);
483
484    char *next_ret = decodeParams(params, result_msg);
485    test_results_t result;
486    decodeTestResult(result, next_ret);
487
488    return result;         
489 }
490
491 std::string RemoteComponentFE::getLastErrorMsg()
492 {
493    MessageBuffer buffer;
494    comp_header(name, buffer, COMPONENT_ERR_MSG);
495
496    connection->send_message(buffer);
497    char *result_msg;
498    connection->recv_return(result_msg);
499
500    std::string str;
501    decodeString(str, result_msg);
502
503    return str;
504 }
505
506 RemoteComponentFE::RemoteComponentFE(std::string n, Connection *c) :
507    connection(c)
508 {
509    //Strip any preceeding 'remote::'
510    if (strstr(n.c_str(), "remote::"))
511       name = std::string(strchr(n.c_str(), ':')+2);
512    else
513       name = n;
514 }
515
516 RemoteComponentFE::~RemoteComponentFE()
517 {
518 }
519
520 RemoteComponentFE *RemoteComponentFE::createRemoteComponentFE(std::string n, Connection *c)
521 {
522    MessageBuffer buf;
523    load_header(buf, LOAD_COMPONENT);
524
525    encodeString(n, buf);
526    c->send_message(buf);
527    char *result_msg;
528    c->recv_return(result_msg);
529
530    bool result;
531    decodeBool(result, result_msg);
532    
533    if (!result)
534       return NULL;
535    
536    RemoteComponentFE *cmp = new RemoteComponentFE(n, c);
537    return cmp;
538 }
539
540 bool RemoteTestFE::hasCustomExecutionPath()
541 {
542    MessageBuffer buffer;
543    test_header(test, buffer, TEST_CUSTOM_PATH);
544
545    connection->send_message(buffer);
546    char *result_msg;
547    connection->recv_return(result_msg);
548
549    bool b;
550    decodeBool(b, result_msg);
551    return b;
552 }
553
554 test_results_t RemoteTestFE::setup(ParameterDict &params)
555 {
556    MessageBuffer buffer;
557    test_header(test, buffer, TEST_SETUP);
558    encodeParams(params, buffer);
559
560    connection->send_message(buffer);
561    char *result_msg;
562    connection->recv_return(result_msg);
563
564    char *next_ret = decodeParams(params, result_msg);
565    test_results_t result;
566    decodeTestResult(result, next_ret);
567
568    return result;
569 }
570
571 test_results_t RemoteTestFE::executeTest()
572 {
573    MessageBuffer buffer;
574    test_header(test, buffer, TEST_EXECUTE);
575
576    connection->send_message(buffer);
577    char *result_msg;
578    connection->recv_return(result_msg);
579
580    test_results_t result;
581    decodeTestResult(result, result_msg);
582
583    return result;
584 }
585
586 test_results_t RemoteTestFE::postExecution()
587 {
588    MessageBuffer buffer;
589    test_header(test, buffer, TEST_POST_EXECUTE);
590
591    connection->send_message(buffer);
592    char *result_msg;
593    connection->recv_return(result_msg);
594
595    test_results_t result;
596    decodeTestResult(result, result_msg);
597
598    return result;
599 }
600
601 test_results_t RemoteTestFE::teardown()
602 {
603    MessageBuffer buffer;
604    test_header(test, buffer, TEST_TEARDOWN);
605
606    connection->send_message(buffer);
607    char *result_msg;
608    connection->recv_return(result_msg);
609
610    test_results_t result;
611    decodeTestResult(result, result_msg);
612
613    return result;
614 }
615
616 RemoteTestFE::RemoteTestFE(TestInfo *t, Connection *c) :
617    test(t),
618    connection(c)
619 {
620 }
621
622 RemoteTestFE::~RemoteTestFE()
623 {
624 }
625
626 RemoteTestFE *RemoteTestFE::createRemoteTestFE(TestInfo *t, Connection *c) {
627    MessageBuffer buf;
628    load_header(buf, LOAD_TEST);
629    
630    encodeTest(t, buf);
631    c->send_message(buf);
632    char *result_msg;
633    c->recv_return(result_msg);
634
635    bool result;
636    decodeBool(result, result_msg);
637    
638    if (!result)
639       return NULL;
640
641    RemoteTestFE *test = new RemoteTestFE(t, c);
642    return test;
643 }
644
645 RemoteBE::RemoteBE(vector<RunGroup *> &g, Connection *c) :
646    groups(g),
647    connection(c)
648 {
649 }
650
651 RemoteBE::~RemoteBE()
652 {
653 }
654
655 void RemoteBE::dispatch(char *message)
656 {
657    char *message_begin = message+2;
658    if (*message == 'C') {
659       dispatchComp(message_begin);
660    }
661    else if (*message == 'T') {
662       dispatchTest(message_begin);
663    }
664    else if (*message == 'L') {
665       dispatchLoad(message_begin);
666    }
667    else if (*message == 'X') {
668       dispatchExit(message_begin);
669    }
670    else {
671       assert(0);
672    }
673 }
674
675 void RemoteBE::dispatchLoad(char *message)
676 {
677    if (strncmp(message, LOAD_TEST, strlen(LOAD_TEST)) == 0) {
678       loadTest(message);
679    }
680    else if (strncmp(message, LOAD_COMPONENT, strlen(LOAD_COMPONENT)) == 0) {
681       loadModule(message);
682    }
683    else {
684       assert(0);
685    }
686 }
687
688 void RemoteBE::dispatchTest(char *message)
689 {
690    char *tag = strdup(my_strtok(message, ":;"));
691    char *group_s = strdup(my_strtok(NULL, ":;"));
692    char *test_s = strdup(my_strtok(NULL, ":;"));
693
694    char *args = strchr(message, ';')+1;
695    args = strchr(args, ';')+1;
696
697    int group_index, test_index;
698    sscanf(group_s, "%d", &group_index);
699    sscanf(test_s, "%d", &test_index);
700    
701    TestMutator *test = getTestBE(group_index, test_index);
702
703    MessageBuffer buffer;
704    return_header(buffer);
705
706    if (strcmp(tag, TEST_CUSTOM_PATH) == 0) {
707       bool result = test->hasCustomExecutionPath();
708       encodeBool(result, buffer);
709    }
710    else if (strcmp(tag, TEST_SETUP) == 0) {
711       ParameterDict params;
712       args = decodeParams(params, args);
713       test_results_t res = test->setup(params);
714       encodeParams(params, buffer);
715       encodeTestResult(res, buffer);
716    }
717    else if (strcmp(tag, TEST_EXECUTE) == 0) {
718       test_results_t res = test->executeTest();
719       encodeTestResult(res, buffer);
720    }
721    else if (strcmp(tag, TEST_POST_EXECUTE) == 0) {
722       test_results_t res = test->postExecution();
723       encodeTestResult(res, buffer);
724    }
725    else if (strcmp(tag, TEST_TEARDOWN) == 0) {
726       test_results_t res = test->teardown();
727       encodeTestResult(res, buffer);
728    }
729    else 
730       assert(0);
731
732    connection->send_message(buffer);
733
734    free(tag);
735    free(test_s);
736 }
737
738 void RemoteBE::dispatchComp(char *message)
739 {
740    char *tag = strdup(my_strtok(message, ":;"));
741    char *name = strdup(my_strtok(NULL, ":;"));
742
743    char *args = strchr(message, ';')+1;
744    args = strchr(args, ';')+1;
745    
746    ComponentTester *compbe = getComponentBE(name);
747    assert(compbe);
748
749    MessageBuffer buffer;
750    return_header(buffer);
751
752    ParameterDict params;
753    RunGroup *group;
754    TestInfo *test;
755    test_results_t result;
756    if (strcmp(tag, COMPONENT_PROGRAM_SETUP) == 0) {
757       args = decodeParams(params, args);
758       result = compbe->program_setup(params);
759    }
760    else if (strcmp(tag, COMPONENT_PROGRAM_TEARDOWN) == 0) {
761       args = decodeParams(params, args);
762       result = compbe->program_teardown(params);
763    }
764    else if (strcmp(tag, COMPONENT_GROUP_SETUP) == 0) {
765       args = decodeGroup(group, groups, args);
766       args = decodeParams(params, args);
767       result = compbe->group_setup(group, params);
768    }
769    else if (strcmp(tag, COMPONENT_GROUP_TEARDOWN) == 0) {
770       args = decodeGroup(group, groups, args);
771       args = decodeParams(params, args);
772       result = compbe->group_teardown(group, params);
773    }
774    else if (strcmp(tag, COMPONENT_TEST_SETUP) == 0) {
775       args = decodeTest(test, groups, args);
776       args = decodeParams(params, args);
777       result = compbe->test_setup(test, params);
778    }
779    else if (strcmp(tag, COMPONENT_TEST_TEARDOWN) == 0) {
780       args = decodeTest(test, groups, args);
781       args = decodeParams(params, args);
782       result = compbe->test_teardown(test, params);
783    }
784
785    if (strcmp(tag, COMPONENT_ERR_MSG) == 0) {      
786       std::string str_result = compbe->getLastErrorMsg();
787       encodeString(str_result, buffer);
788    }
789    else {
790       encodeParams(params, buffer);
791       encodeTestResult(result, buffer);
792    }
793
794    connection->send_message(buffer);
795
796    free(tag);
797    free(name);
798 }
799
800 void RemoteBE::dispatchExit(char *message)
801 {
802    exit(0);
803 }
804
805 static std::string getLocalComponentName(std::string modname)
806 {
807    int prefix_length = strlen("remote::");
808    if (strncmp(modname.c_str(), "remote::", prefix_length) == 0) {
809       return std::string(modname.c_str()+prefix_length);
810    }
811    return modname;
812 }
813
814
815 ComponentTester *RemoteBE::getComponentBE(std::string name)
816 {
817    map<string, ComponentTester *>::iterator i = nameToComponent.find(getLocalComponentName(name));
818    assert(i != nameToComponent.end());
819    return i->second;
820 }
821
822 TestMutator *RemoteBE::getTestBE(int group_index, int test_index)
823 {
824    map<pair<int, int>, TestMutator *>::iterator i;
825    i = testToMutator.find(pair<int, int>(group_index, test_index));
826    assert(i != testToMutator.end());
827    return i->second;
828 }
829
830 void RemoteBE::loadModule(char *message) {
831    assert(strncmp(message, LOAD_COMPONENT, strlen(LOAD_COMPONENT)) == 0);
832    char *args = strchr(message, ';')+1;
833
834    bool error = false;
835
836    string modname;
837    decodeString(modname, args);
838    modname = getLocalComponentName(modname);
839
840    map<string, ComponentTester *>::iterator i;
841    i = nameToComponent.find(modname);
842
843    if (i == nameToComponent.end()) {
844       ComponentTester *comp = NULL;
845       for (unsigned j=0; j<groups.size(); j++) {
846          RunGroup *group = groups[j];
847          if (group->modname == modname) {
848             bool result = Module::registerGroupInModule(modname, group, false);
849             if (!result) {
850                error = true;
851                goto done;
852             }
853             if (!comp)
854                comp = group->mod->tester;
855             assert(comp == group->mod->tester);
856          }
857       }
858       nameToComponent[modname] = comp;
859    }
860    
861   done:
862    MessageBuffer buffer;
863    return_header(buffer);
864    encodeBool(!error, buffer);
865    connection->send_message(buffer);   
866 }
867
868 void RemoteBE::loadTest(char *message) {
869    assert(strncmp(message, LOAD_TEST, strlen(LOAD_TEST)) == 0);
870    char *args = strchr(message, ';')+1;
871    
872    TestInfo *test;
873    decodeTest(test, groups, args);
874    int group_index = test->group_index;
875    int test_index = test->index;
876    RunGroup *group = groups[group_index];
877
878    map<pair<int, int>, TestMutator *>::iterator i;
879    i = testToMutator.find(pair<int, int>(group_index, test_index));
880    if (i == testToMutator.end()) {
881       setupMutatorsForRunGroup(group);
882       for (unsigned j=0; j < group->tests.size(); j++) {
883          TestMutator *mutator = group->tests[j]->mutator;
884          if (mutator) {
885             testToMutator[pair<int, int>(group_index, test_index)] = mutator;
886          }
887       }
888    }
889
890    bool module_result, test_result;
891    test_result = group->tests[test_index]->mutator != NULL;
892    module_result = group->mod != NULL;
893
894    MessageBuffer buffer;
895    return_header(buffer);
896
897    encodeBool(test_result && module_result, buffer);
898    connection->send_message(buffer);   
899 }
900
901 void RemoteOutputDriver::startNewTest(std::map<std::string, std::string> &, TestInfo *, RunGroup *)
902 {
903    assert(0); //Not expected to be called from BE
904 }
905
906 void RemoteOutputDriver::redirectStream(TestOutputStream stream, const char * filename)
907 {
908    assert(0); //Not expected to be called from BE   
909 }
910
911 void RemoteOutputDriver::logResult(test_results_t result, int stage)
912 {
913    assert(0); //Not expected to be called from BE
914 }
915
916 void RemoteOutputDriver::logCrash(std::string testname)
917 {
918    assert(0); //Not expected to be called from BE
919 }
920
921 void RemoteOutputDriver::log(TestOutputStream stream, const char *fmt, ...)
922 {
923   va_list args;
924   va_start(args, fmt);
925   vlog(stream, fmt, args);
926   va_end(args);
927 }
928
929 void RemoteOutputDriver::vlog(TestOutputStream stream, const char *fmt, va_list args)
930 {
931    static char buffer[4096];
932    vsnprintf(buffer, 4095, fmt, args);
933    buffer[4095] = '\0';
934
935    MessageBuffer msg;
936    message_header(msg);
937    encodeInt(stream, msg);
938    encodeString(std::string(buffer), msg);
939
940    connection->send_message(msg);
941 }
942
943 void RemoteOutputDriver::finalizeOutput()
944 {
945    assert(0); //Not expected to be called from BE
946 }
947
948 RemoteOutputDriver::RemoteOutputDriver(Connection *c) :
949    connection(c)
950 {
951 }
952
953 static void handle_message(char *buffer) {
954    TestOutputStream stream;
955    std::string string;
956
957    buffer = decodeInt(stream, buffer);
958    decodeString(string, buffer);
959    logerror(string.c_str());
960 }
961
962 #define SOCKTYPE_UNIX
963
964 bool Connection::recv_return(char* &buffer) {
965    char *msg;
966    for (;;) {
967       bool result = recv_message(msg);
968       if (!result)
969          return false;
970    
971       if (*msg == 'R') {
972          buffer = msg+2;
973          return true;
974       }
975       if (*msg == 'M') {
976          handle_message(msg+2);
977       }
978    }
979 }
980
981 #include <sys/time.h>
982 #include <sys/select.h>
983 #include <sys/socket.h>
984 #include <sys/types.h>
985 #include <netinet/in.h>
986 #include <netinet/ip.h>
987 #include <unistd.h>
988 #include <arpa/inet.h>
989 #include <netdb.h>
990
991 int Connection::sockfd = -1;
992 std::string Connection::hostname;
993 int Connection::port;
994 bool Connection::has_hostport = false;
995
996 Connection::Connection() :
997    fd(-1),
998    has_error(false)
999 {
1000 }
1001
1002 Connection::Connection(std::string hostname_, int port_) :
1003    fd(-1)
1004 {
1005    hostname = hostname_;
1006    port = port_;
1007    has_hostport = true;
1008
1009    has_error = !client_connect();
1010 }
1011
1012 Connection::~Connection()
1013 {
1014    MessageBuffer buf;
1015    exit_header(buf);
1016    send_message(buf);
1017
1018    if (fd != -1)
1019       close(fd);
1020 }
1021
1022 bool Connection::hasError()
1023 {
1024    return has_error;
1025 }
1026
1027 bool Connection::send_message(MessageBuffer &buffer)
1028 {
1029    buffer.add("\0", 1);
1030
1031    uint32_t msg_size_unenc = buffer.get_buffer_size();
1032    assert(msg_size_unenc == strlen(buffer.get_buffer())+1);
1033    uint32_t msg_size = htonl(msg_size_unenc);
1034
1035    ssize_t result = send(fd, &msg_size, sizeof(uint32_t), 0);
1036    if (result == -1) {
1037       debug_printf("Error sending data count on socket\n");
1038       return false;
1039    }
1040    debug_printf("[%d] - Send size of %lu, (encoded 0x%lx)\n", 
1041            getpid(), (unsigned long) msg_size_unenc, (unsigned long) msg_size);
1042    
1043    result = send(fd, buffer.get_buffer(), msg_size_unenc, 0);
1044    if (result == -1) {
1045      debug_printf("Error sending raw data on socket\n");
1046       return false;
1047    }
1048   debug_printf("[%d] - Sent buffer %s\n", getpid(), buffer.get_buffer());
1049    return true;
1050 }
1051
1052 bool Connection::recv_message(char* &buffer)
1053 {
1054    static char *cur_buffer = NULL;
1055    static int cur_buffer_size = 0;
1056    bool sock_error;
1057
1058    if (!waitForAvailData(fd, recv_timeout, sock_error))
1059       return false;
1060    if (sock_error) {
1061      debug_printf("[%d] - Recv sock exception\n", getpid());
1062    }
1063    
1064    uint32_t msg_size = 0, enc_msg_size = 0;
1065    ssize_t result;
1066    result = recv(fd, &enc_msg_size, sizeof(uint32_t), MSG_WAITALL);
1067    if (result == -1) {
1068       int errornum = errno;
1069       debug_printf("Error receiving data size on socket: %s\n", strerror(errornum));
1070       return false;
1071    }
1072    if (result == 0) {
1073       debug_printf("[%d] - Recv zero, other size shutdown.\n", getpid());
1074       return false;
1075    }
1076    msg_size = ntohl(enc_msg_size);
1077    debug_printf("[%d] - Recv size of %lu, (encoded 0x%lx, result = %d)\n", 
1078                 getpid(), (unsigned long) msg_size, enc_msg_size, (int) result);
1079
1080    assert(msg_size < (1024*1024)); //No message over 1MB--should be plenty
1081    
1082    if (msg_size == 0) {
1083       //Other side hung up.
1084       return false;
1085    }
1086
1087    if (msg_size > cur_buffer_size) {
1088       if (cur_buffer)
1089          free(cur_buffer);
1090       cur_buffer = NULL;
1091    }
1092    if (cur_buffer == NULL) {
1093       cur_buffer_size = msg_size+1;
1094       cur_buffer = (char *) malloc(cur_buffer_size);
1095    }
1096    memset(cur_buffer, 0, cur_buffer_size);
1097
1098    result = recv(fd, cur_buffer, msg_size, MSG_WAITALL);
1099    if (result == -1) {
1100      debug_printf("Error receiving data on socket\n");
1101       return false;
1102    }
1103
1104    buffer = cur_buffer;
1105   debug_printf("[%d] - Recv of buffer %s\n", getpid(), buffer);
1106
1107    return true;
1108 }
1109
1110 bool Connection::waitForAvailData(int sock, int timeout_s, bool &sock_error)
1111 {
1112    fd_set readfds;
1113    fd_set exceptfds;
1114    fd_set writefds;
1115    FD_ZERO(&readfds);
1116    FD_ZERO(&exceptfds);
1117    FD_ZERO(&writefds);
1118    FD_SET(sock, &readfds);
1119    FD_SET(sock, &exceptfds);
1120
1121    struct timeval timeout;
1122    timeout.tv_sec = timeout_s;
1123    timeout.tv_usec = 0;
1124    sock_error = false;
1125
1126    for (;;) {
1127       int result = select(sock+1, &readfds, &writefds, &exceptfds, &timeout);
1128       if (result == -1 && errno == EINTR) 
1129          continue;
1130       else if (result == -1) {
1131         debug_printf("Error selecting to accept connections\n");
1132          return false;
1133       }
1134       else if (result == 0) {
1135         debug_printf("Timeout accepting connections\n");
1136          return false;
1137       }
1138       else if (result >= 1) {
1139          if (FD_ISSET(sock, &readfds) && FD_ISSET(sock, &exceptfds)) {
1140             sock_error = true;
1141             return true;
1142          }
1143          if (FD_ISSET(sock, &readfds)) {
1144             return true;
1145          }
1146          if (FD_ISSET(sock, &exceptfds)) {
1147             sock_error = true;
1148             return false;
1149          }
1150          assert(0);
1151       }      
1152       else {
1153          assert(0);
1154       }
1155    }
1156 }
1157
1158 bool Connection::server_accept()
1159 {
1160    struct sockaddr_in addr;
1161    socklen_t socklen = sizeof(struct sockaddr_in);
1162    bool sock_error;
1163
1164    if (!waitForAvailData(sockfd, accept_timeout, sock_error))
1165       return false;
1166        
1167    assert(fd == -1); //One connection at a time.
1168
1169    fd = accept(sockfd, (sockaddr *) &addr, &socklen);
1170    if (fd == -1) {
1171      debug_printf("Error accepting connection\n");
1172       return false;
1173    }
1174    
1175    return true;
1176 }
1177
1178 bool Connection::client_connect()
1179 {
1180    assert(has_hostport);
1181    fd = socket(PF_INET, SOCK_STREAM, 0);
1182    if (fd == -1) {
1183      debug_printf("Unable to create client socket: %s\n", strerror(errno));
1184       return false;
1185    }
1186
1187    struct hostent *host = gethostbyname2(hostname.c_str(), AF_INET);
1188    if (!host) {
1189      debug_printf("Error looking up hostname %s\n", hostname.c_str());
1190       return false;
1191    }
1192    assert(host->h_addrtype = AF_INET);
1193
1194    if (host->h_length == 0) {
1195      debug_printf("No addresses with hostname %s\n", hostname.c_str());
1196       return false;
1197    }
1198    
1199
1200    struct sockaddr_in addr;
1201    socklen_t socklen = sizeof(struct sockaddr_in);
1202    addr.sin_family = AF_INET;
1203    addr.sin_port = port;
1204    addr.sin_addr.s_addr = *(u_int32_t *) (host->h_addr_list[0]);
1205
1206    int result = connect(fd, (struct sockaddr *) &addr, socklen);
1207    if (result == -1) {
1208      debug_printf("Error connecting to server\n");
1209       return false;
1210    }
1211
1212    return true;
1213 }
1214
1215 bool Connection::server_setup(string &hostname_, int &port_)
1216 {
1217    if (has_hostport) {
1218       hostname_ = hostname;
1219       port_ = port;
1220       assert(sockfd != -1);
1221       return true;
1222    }
1223
1224    sockfd = socket(PF_INET, SOCK_STREAM, 0);
1225    if (sockfd == -1) {
1226      debug_printf("Unable to create socket: %s\n", strerror(errno));
1227       return false;
1228    }
1229    
1230    struct sockaddr_in addr;
1231    socklen_t socklen = sizeof(struct sockaddr_in);
1232    
1233    memset(&addr, 0, socklen);
1234    addr.sin_family = AF_INET;
1235    addr.sin_port = 0;
1236    addr.sin_addr.s_addr = INADDR_ANY;
1237    
1238    int result = bind(sockfd, (struct sockaddr *) &addr, socklen);
1239    if (result != 0){
1240      debug_printf("Unable to bind socket: %s\n", strerror(errno));
1241       return false;
1242    }
1243    
1244    result = listen(sockfd, 16);
1245    if (result == -1) {
1246      debug_printf("Unable to listen on socket: %s\n", strerror(errno));
1247       return false;
1248    }
1249
1250    result = getsockname(sockfd, (sockaddr *) &addr, &socklen);
1251    if (result != 0) {
1252      debug_printf("Unable to getsockname on socket\n");
1253       return false;
1254    }
1255
1256    char name_buffer[1024];
1257    result = gethostname(name_buffer, 1024);
1258    if (result != 0) {
1259      debug_printf("Unable to get hostname\n");
1260       return false;
1261    }
1262
1263    hostname = name_buffer;
1264    port = (int) addr.sin_port;
1265
1266    hostname_ = hostname;
1267    port_ = port;
1268    has_hostport = true;
1269    return true;
1270 }
1271
1272 static Connection *con = NULL;
1273 Connection *getConnection()
1274 {
1275    return con;
1276 }
1277
1278 void setConnection(Connection *c)
1279 {
1280    con = c;
1281 }
1282
1283 static char *my_strtok(char *str, const char *delim)
1284 {
1285    static char *my_str = NULL;
1286    static char *save_ptr = NULL;
1287    
1288    if (str) {
1289       char *backup_str = strdup(str);
1290       if (my_str)
1291          free(my_str);
1292       my_str = backup_str;
1293    }
1294    else {
1295       my_str = NULL;
1296    }
1297    
1298    return strtok_r(my_str, delim, &save_ptr);
1299 }