ceptr
 All Data Structures Files Functions Variables Typedefs Macros Modules Pages
receptor_spec.h
Go to the documentation of this file.
1 
7 #include "../src/ceptr.h"
8 #include "../src/receptor.h"
9 #include "../src/def.h"
10 #include "../src/accumulator.h"
11 #include "../src/vmhost.h"
12 #include "../src/protocol.h"
13 #include "http_example.h"
14 #include <unistd.h>
15 #include "spec_utils.h"
16 
19  Receptor *r;
20  r = _r_new(G_sem,TEST_RECEPTOR);
21 
22  spec_is_symbol_equal(r,_t_symbol(r->root),RECEPTOR_INSTANCE);
23 
24  T *t;
25 
26  // test that expectations and signals are set up correctly on the default aspect
27  t = __r_get_expectations(r,DEFAULT_ASPECT);
28  spec_is_symbol_equal(r,_t_symbol(t),EXPECTATIONS);
29  t = __r_get_signals(r,DEFAULT_ASPECT);
30  spec_is_symbol_equal(r,_t_symbol(t),SIGNALS);
31 
32  // test that the flux is set up correctly
33  int p[] = {ReceptorInstanceStateIdx,ReceptorFluxIdx,TREE_PATH_TERMINATOR};
34  t = _t_get(r->root,p);
35  spec_is_symbol_equal(r,_t_symbol(r->flux),FLUX);
36  spec_is_ptr_equal(t,r->flux);
37  t = _t_child(r->flux,1);
38  spec_is_symbol_equal(r,_t_symbol(t),DEFAULT_ASPECT);
39 
40  spec_is_str_equal(t2s(r->root),"(RECEPTOR_INSTANCE (INSTANCE_OF:TEST_RECEPTOR) (CONTEXT_NUM:3) (PARENT_CONTEXT_NUM:0) (RECEPTOR_STATE (FLUX (DEFAULT_ASPECT (EXPECTATIONS) (SIGNALS))) (PENDING_SIGNALS) (PENDING_RESPONSES) (CONVERSATIONS) (RECEPTOR_ELAPSED_TIME:0)))");
41 
42  _r_free(r);
44 }
45 
46 void testReceptorAddRemoveExpectation() {
47  Receptor *r;
48  r = _r_new(G_sem,TEST_RECEPTOR);
49 
50  Symbol dummy = {r->context,SEM_TYPE_SYMBOL,1};
51  // test that you can add a expectation to a receptor's aspect
52  T *s = _t_new_root(PATTERN);
53  _sl(s,dummy);
54  T *a = _t_news(0,ACTION,NULL_PROCESS);
55  _r_add_expectation(r,DEFAULT_ASPECT,TEST_INT_SYMBOL,s,a,0,0,NULL,NULL);
56 
57  T *es = __r_get_expectations(r,DEFAULT_ASPECT);
58  T *e = _t_child(es,1); // expectation should have been added as first child of expectations
59  spec_is_str_equal(_td(r,e),"(EXPECTATION (CARRIER:TEST_INT_SYMBOL) (PATTERN (SEMTREX_SYMBOL_LITERAL (SEMTREX_SYMBOL:TEST_INT_SYMBOL))) (ACTION:NULL_PROCESS) (PARAMS) (END_CONDITIONS (UNLIMITED)))");
60 
61  _r_remove_expectation(r,e);
62 
63  spec_is_str_equal(_td(r,es),"(EXPECTATIONS)");
64  _r_free(r);
65 }
66 
67 void testReceptorSignal() {
68  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
69  T *sc,*signal_contents = _t_newi(0,TEST_INT_SYMBOL,314);
70  ReceptorAddress f = {3}; // DUMMY ADDR
71  ReceptorAddress t = {4}; // DUMMY ADDR
72 
73  T *s = __r_make_signal(f,t,DEFAULT_ASPECT,TESTING,sc=_t_clone(signal_contents),0,0,0);
74 
75  spec_is_symbol_equal(r,_t_symbol(s),SIGNAL);
76 
77  T *envelope = _t_child(s,SignalEnvelopeIdx);
78  spec_is_str_equal(t2s(envelope),"(ENVELOPE (SIGNAL_UUID))");
79 
80  T *message = _t_child(s,SignalMessageIdx);
81 
82  T *head = _t_child(message,MessageHeadIdx);
83  spec_is_str_equal(t2s(head),"(HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:4)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:TESTING))");
84  T *body = _t_child(message,MessageBodyIdx);
85  spec_is_str_equal(t2s(body),"(BODY:{(TEST_INT_SYMBOL:314)})");
86  T *contents = (T*)_t_surface(body);
87  spec_is_ptr_equal(sc,contents);
88  _t_free(s);
89 
90  UUIDt u = __uuid_gen();
91  s = __r_make_signal(f,t,DEFAULT_ASPECT,TESTING,_t_clone(signal_contents),&u,0,0);
92  spec_is_str_equal(t2s(s),"(SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:4)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:TESTING) (IN_RESPONSE_TO_UUID)) (BODY:{(TEST_INT_SYMBOL:314)})))");
93  int p[] = {SignalMessageIdx,MessageHeadIdx,HeadOptionalsIdx,TREE_PATH_TERMINATOR};
94  T *ru = _t_get(s,p);
95  spec_is_true(__uuid_equal(&u,_t_surface(ru)));
96 
97  _t_free(s);
98  T *ec = defaultRequestUntil();
99  s = __r_make_signal(f,t,DEFAULT_ASPECT,TESTING,signal_contents,0,ec,0);
100  spec_is_ptr_equal(ec,_t_get(s,p));
101  _t_free(s);
102 
103  _r_free(r);
104 }
105 
106 void testReceptorSignalDeliver() {
107  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
108  T *signal_contents = _t_newi(0,TEST_INT_SYMBOL,314);
109  ReceptorAddress f = {3}; // DUMMY ADDR
110  ReceptorAddress t = {4}; // DUMMY ADDR
111 
112  // a new signal should simply be placed on the flux when delivered
113  T *s = __r_make_signal(f,t,DEFAULT_ASPECT,TESTING,signal_contents,0,0,0);
114  spec_is_equal(_r_deliver(r,s),noDeliveryErr);
115 
116  T *signals = __r_get_signals(r,DEFAULT_ASPECT);
117  spec_is_str_equal(_td(r,signals),"(SIGNALS (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:4)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:TESTING)) (BODY:{(TEST_INT_SYMBOL:314)}))))");
118  _r_free(r);
119 }
120 
121 void testReceptorDeliverConversation() {
122  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
123  T *signal_contents = _t_newi(0,TEST_INT_SYMBOL,314);
124  ReceptorAddress f = {3}; // DUMMY ADDR
125  ReceptorAddress t = {4}; // DUMMY ADDR
126 
127  // the first signal in a conversation should create a conversation record
128  UUIDt cuuid = __uuid_gen();
129  T *cu = __cid_new(0,&cuuid,0);
130 
131  T *s = __r_make_signal(f,t,DEFAULT_ASPECT,TESTING,signal_contents,0,0,cu);
132 
133  spec_is_str_equal(_td(r,r->conversations),"(CONVERSATIONS)");
134  spec_is_equal(_r_deliver(r,s),noDeliveryErr);
135  // when the signal arrives a new conversation should be in place
136  spec_is_str_equal(_td(r,r->conversations),"(CONVERSATIONS (CONVERSATION (CONVERSATION_IDENT (CONVERSATION_UUID)) (END_CONDITIONS (UNLIMITED)) (CONVERSATIONS)))");
137  _t_free(cu);
138  _r_free(r);
139 }
140 
141 void testReceptorConversations() {
142  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
143  spec_is_str_equal(_td(r,r->conversations),"(CONVERSATIONS)");
144 
145  UUIDt u = __uuid_gen();
146  T *c = _r_add_conversation(r,0,&u,0,0);
147  spec_is_str_equal(_td(r,c),"(CONVERSATION (CONVERSATION_IDENT (CONVERSATION_UUID)) (END_CONDITIONS (UNLIMITED)) (CONVERSATIONS))");
148  spec_is_str_equal(_td(r,r->conversations),"(CONVERSATIONS (CONVERSATION (CONVERSATION_IDENT (CONVERSATION_UUID)) (END_CONDITIONS (UNLIMITED)) (CONVERSATIONS)))");
149 
150  spec_is_ptr_equal(_r_find_conversation(r,&u),c);
151 
152  // add a child conversation
153  UUIDt u2 = __uuid_gen();
154  T *c2 = _r_add_conversation(r,&u,&u2,0,0);
155 
156  spec_is_str_equal(_td(r,r->conversations),"(CONVERSATIONS (CONVERSATION (CONVERSATION_IDENT (CONVERSATION_UUID)) (END_CONDITIONS (UNLIMITED)) (CONVERSATIONS (CONVERSATION (CONVERSATION_IDENT (CONVERSATION_UUID)) (END_CONDITIONS (UNLIMITED)) (CONVERSATIONS)))))");
157 
158  spec_is_ptr_equal(_r_find_conversation(r,&u2),c2);
159 
160  // add a sibling conversation
161  UUIDt u3 = __uuid_gen();
162  T *c3 = _r_add_conversation(r,0,&u3,0,0);
163 
164  spec_is_str_equal(_td(r,r->conversations),"(CONVERSATIONS (CONVERSATION (CONVERSATION_IDENT (CONVERSATION_UUID)) (END_CONDITIONS (UNLIMITED)) (CONVERSATIONS (CONVERSATION (CONVERSATION_IDENT (CONVERSATION_UUID)) (END_CONDITIONS (UNLIMITED)) (CONVERSATIONS)))) (CONVERSATION (CONVERSATION_IDENT (CONVERSATION_UUID)) (END_CONDITIONS (UNLIMITED)) (CONVERSATIONS)))");
165 
166  spec_is_ptr_equal(_r_find_conversation(r,&u3),c3);
167 
168  _r_free(r);
169 }
170 
171 extern int G_next_process_id;
172 void testReceptorResponseDeliver() {
173  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
174 
175  G_next_process_id = 0; // reset the process ids so the test will always work
176 
177  ReceptorAddress tt = {4}; // DUMMY ADDR
178 
179  // set up receptor to have sent a signal and blocked waiting for the response
180  T *t = _t_new_root(RUN_TREE);
181  T *p = _t_new_root(NOOP);
182  T *req = _t_newr(p,REQUEST);
183  __r_make_addr(req,TO_ADDRESS,tt);
184  _t_news(req,ASPECT_IDENT,DEFAULT_ASPECT);
185  _t_news(req,CARRIER,TESTING);
186  _t_newi(req,TEST_INT_SYMBOL,98789);
187  _t_news(req,RESPONSE_CARRIER,TESTING);
188 
189  T *c = _t_rclone(p);
190  _t_free(p);
191  _t_add(t,c);
192  _p_addrt2q(r->q,t);
193  _p_reduceq(r->q);
194 
195  // the run tree should now be blocked with the sending signal uuid in the place
196  // where the response value should be filled and the pending responses list should
197  // have the UUID and the code path in it
198  T *rt = r->q->blocked->context->run_tree;
199  spec_is_str_equal(_td(r,rt),"(RUN_TREE (process:NOOP (SIGNAL_UUID)))");
200  T *pr = _t_child(r->pending_responses,1);
201  spec_is_str_equal(_td(r,_t_child(pr,1)),"(SIGNAL_UUID)");
202  spec_is_str_equal(_td(r,_t_child(pr,2)),"(CARRIER:TESTING)");
203  spec_is_str_equal(_td(r,_t_child(pr,3)),"(WAKEUP_REFERENCE (PROCESS_IDENT:1) (CODE_PATH:/1/1))");
204  T *ec = _t_child(pr,4);
205  spec_is_sem_equal(_t_symbol(ec),END_CONDITIONS);
206 
207  // create a response signals
208  ReceptorAddress from = {4}; // DUMMY ADDR
209  ReceptorAddress to = {0}; // DUMMY ADDR
210 
211  // get the original signal uuid from the run tree
212  UUIDt response_id = *(UUIDt *)_t_surface(_t_child(_t_child(rt,1),1));
213  T *s = __r_make_signal(from,to,DEFAULT_ASPECT,TESTING,_t_new_str(0,TEST_STR_SYMBOL,"foo"),&response_id,0,0);
214 
215  // debug_enable(D_SIGNALS);
216  spec_is_equal(_r_deliver(r,s),noDeliveryErr);
217  // debug_disable(D_SIGNALS);
218 
219  // block list should now be empty
220  spec_is_ptr_equal(r->q->blocked,NULL);
221 
222  // and the run tree should now be active and have the response contents value
223  // in place for reduction.
224  rt = r->q->active->context->run_tree;
225  spec_is_str_equal(_td(r,rt),"(RUN_TREE (process:NOOP (TEST_STR_SYMBOL:foo)))");
226 
227  // and the pending_responses list should be cleared too because we only asked for one response.
228  spec_is_str_equal(_td(r,r->pending_responses),"(PENDING_RESPONSES)");
229 
230  _r_free(r);
231 }
232 
233 void testReceptorEndCondition() {
234  T *until = _t_new_root(END_CONDITIONS);
235  _t_newr(until,UNLIMITED);
236  bool cleanup,allow;
237  evaluateEndCondition(until,&cleanup,&allow);
238  spec_is_false(cleanup);spec_is_true(allow);
239  _t_free(until);
240 
241  until = _t_new_root(END_CONDITIONS);
242  _t_newi(until,COUNT,2);
243  evaluateEndCondition(until,&cleanup,&allow);
244  spec_is_false(cleanup);spec_is_true(allow);
245  spec_is_str_equal(t2s(until),"(END_CONDITIONS (COUNT:1))");
246  evaluateEndCondition(until,&cleanup,&allow);
247  spec_is_true(cleanup);spec_is_true(allow);
248  spec_is_str_equal(t2s(until),"(END_CONDITIONS (COUNT:0))");
249  _t_free(until);
250  // debug_enable(D_SIGNALS);
251  until = _t_new_root(END_CONDITIONS);
252  T *ts = __r_make_timestamp(TIMEOUT_AT,-2);
253  _t_add(until,ts);
254  evaluateEndCondition(until,&cleanup,&allow);
255  spec_is_true(cleanup);spec_is_false(allow);
256  _t_free(until);
257 
258  until = _t_new_root(END_CONDITIONS);
259  ts = __r_make_timestamp(TIMEOUT_AT,+2);
260  _t_add(until,ts);
261  evaluateEndCondition(until,&cleanup,&allow);
262  spec_is_false(cleanup);spec_is_true(allow);
263  _t_free(until);
264  debug_disable(D_SIGNALS);
265 
266 }
267 
270  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
271 
272  // The signal is an HTTP request
273  T *signal_contents = _makeTestHTTPRequestTree(); // GET /groups/5/users.json?sort_by=last_name?page=2 HTTP/1.0
274 
275  ReceptorAddress f = {3}; // DUMMY ADDR
276  ReceptorAddress t = {4}; // DUMMY ADDR
277 
278  T *signal = __r_make_signal(f,t,DEFAULT_ASPECT,HTTP_REQUEST,signal_contents,0,0,0);
279 
280  // our expectation pattern should match on the first path segment
281  // /HTTP_REQUEST/.,.,HTTP_REQUEST_PATH/HTTP_REQUEST_PATH_SEGMENTS/<HTTP_REQUEST_PATH_SEGMENT:HTTP_REQUEST_PATH_SEGMENT>
282  T *pattern = _t_new_root(PATTERN);
283  char *stx = "/HTTP_REQUEST_LINE/(.,.,HTTP_REQUEST_PATH/HTTP_REQUEST_PATH_SEGMENTS/<HTTP_REQUEST_PATH_SEGMENT:HTTP_REQUEST_PATH_SEGMENT>)";
284  T *req = parseSemtrex(G_sem,stx);
285  _t_add(pattern,req);
286 /* T *req = _t_news(pattern,SEMTREX_SYMBOL_LITERAL,HTTP_REQUEST);
287  T *seq = _t_newr(req,SEMTREX_SEQUENCE);
288  _t_newr(seq,SEMTREX_SYMBOL_ANY); // skips the Version
289  _t_newr(seq,SEMTREX_SYMBOL_ANY); // skips over the Method
290  T *path = _t_news(seq,SEMTREX_SYMBOL_LITERAL,HTTP_REQUEST_PATH);
291  T *segs = _t_news(path,SEMTREX_SYMBOL_LITERAL,HTTP_REQUEST_PATH_SEGMENTS);
292  T *g = _t_news(segs,SEMTREX_GROUP,HTTP_REQUEST_PATH_SEGMENT);
293  _t_news(g,SEMTREX_SYMBOL_LITERAL,HTTP_REQUEST_PATH_SEGMENT);
294 */
295 
296  // gotta load the defs into the receptor for printing things out to work right.
297  // r->defs.symbols = _t_clone(test_HTTP_defs.symbols);
298  // r->defs.structures = _t_clone(test_HTTP_defs.structures);
299 
300  T *result;
301  int matched;
302  // make sure our expectation semtrex actually matches the signal
303  spec_is_true(_t_matchr(req,signal_contents,&result));
304  T *m = _t_get_match(result,HTTP_REQUEST_PATH_SEGMENT);
305 
306  spec_is_str_equal(_td(r,m),"(SEMTREX_MATCH:1 (SEMTREX_MATCH_SYMBOL:HTTP_REQUEST_PATH_SEGMENT) (SEMTREX_MATCH_PATH:/3/1/1) (SEMTREX_MATCH_SIBLINGS_COUNT:1))");
307  if (result) {
308  _t_free(result);
309  }
310 
311  T *params;
312  Process p;
313  _makeTestHTTPResponseProcess(r,&params,&p);
314  T *act = _t_newp(0,ACTION,p);
315 
316  // have this expectation clean itself up after one match
317  T *until = _t_new_root(END_CONDITIONS);
318  _t_newi(until,COUNT,1);
319 
320  T *using = NULL;
321 
322  _r_add_expectation(r,DEFAULT_ASPECT,HTTP_REQUEST,pattern,act,params,until,using,NULL);
323 
324  Error err = _r_deliver(r,signal);
325  spec_is_equal(err,noDeliveryErr);
326 
327  // signal and run_tree should be added and ready on the process queue
328  spec_is_equal(r->q->contexts_count,1);
329  spec_is_str_equal(_td(r,__r_get_signals(r,DEFAULT_ASPECT)),
330  "(SIGNALS (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:4)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:HTTP_REQUEST)) (BODY:{(HTTP_REQUEST_LINE (HTTP_REQUEST_VERSION (VERSION_MAJOR:1) (VERSION_MINOR:1)) (HTTP_REQUEST_METHOD:GET) (HTTP_REQUEST_PATH (HTTP_REQUEST_PATH_SEGMENTS (HTTP_REQUEST_PATH_SEGMENT:groups) (HTTP_REQUEST_PATH_SEGMENT:5)) (HTTP_REQUEST_PATH_FILE (FILE_NAME:users) (FILE_EXTENSION:json)) (HTTP_REQUEST_PATH_QUERY (HTTP_REQUEST_PATH_QUERY_PARAMS (HTTP_REQUEST_PATH_QUERY_PARAM (PARAM_KEY:sort_by) (PARAM_VALUE:last_name)) (HTTP_REQUEST_PATH_QUERY_PARAM (PARAM_KEY:page) (PARAM_VALUE:2))))))})) (RUN_TREE (process:RESPOND (CARRIER:HTTP_RESPONSE) (PARAM_REF:/2/1)) (PARAMS (HTTP_RESPONSE (HTTP_RESPONSE_STATUS (STATUS_VALUE:200) (STATUS_TEXT:OK)) (HTTP_HEADERS (CONTENT_TYPE (MEDIA_TYPE_IDENT:TEXT_MEDIA_TYPE) (MEDIA_SUBTYPE_IDENT:CEPTR_TEXT_MEDIA_SUBTYPE))) (HTTP_RESPONSE_BODY (HTTP_REQUEST_PATH_SEGMENT:groups)))))))"
331  );
332 
333  // manually run the process queue
334  _p_reduceq(r->q);
335 
336  // should add a pending signal to be sent with the matched PATH_SEGMENT returned as the response signal body
337  spec_is_str_equal(_td(r,r->pending_signals),"(PENDING_SIGNALS (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:4)) (TO_ADDRESS (RECEPTOR_ADDR:3)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:HTTP_RESPONSE) (IN_RESPONSE_TO_UUID)) (BODY:{(HTTP_RESPONSE (HTTP_RESPONSE_STATUS (STATUS_VALUE:200) (STATUS_TEXT:OK)) (HTTP_HEADERS (CONTENT_TYPE (MEDIA_TYPE_IDENT:TEXT_MEDIA_TYPE) (MEDIA_SUBTYPE_IDENT:CEPTR_TEXT_MEDIA_SUBTYPE))) (HTTP_RESPONSE_BODY (HTTP_REQUEST_PATH_SEGMENT:groups)))}))))");
338 
339  if (r->q->completed) {
340  result = _t_child(r->q->completed->context->run_tree,1);
341  spec_is_str_equal(_td(r,result),"(SIGNAL_UUID)");
342  }
343  else {
344  spec_is_true(!r->q->completed);
345  }
346 
347  T *es = __r_get_expectations(r,DEFAULT_ASPECT);
348  spec_is_str_equal(_td(r,es),"(EXPECTATIONS)");
349 
350  _r_free(r);
352 }
353 
354 void testReceptorDef() {
355  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
356 
357  Symbol lat = _r_define_symbol(r,FLOAT,"Latitude");
358  Symbol lon = _r_define_symbol(r,FLOAT,"Longitude");
359 
360  spec_is_structure_equal(r,__r_get_symbol_structure(r,lat),FLOAT);
361 
362  T *def = _sem_get_def(r->sem,lat);
363  spec_is_str_equal(t2s(def),"(SYMBOL_DEFINITION (SYMBOL_LABEL (ENGLISH_LABEL:Latitude)) (SYMBOL_STRUCTURE:FLOAT))");
364  def = _sem_get_def(r->sem,lon);
365  spec_is_str_equal(t2s(def),"(SYMBOL_DEFINITION (SYMBOL_LABEL (ENGLISH_LABEL:Longitude)) (SYMBOL_STRUCTURE:FLOAT))");
366 
367  spec_is_sem_equal(_r_get_sem_by_label(r,"Latitude"),lat);
368  SemanticID sid;
369  __sem_get_by_label(G_sem,"Latitude",&sid,r->context);
370  spec_is_sem_equal(sid,lat);
371 
372  Structure latlong = _r_define_structure(r,"Latlong",2,lat,lon);
373 
374  def = _sem_get_def(r->sem,latlong);
375  spec_is_str_equal(t2s(def),"(STRUCTURE_DEFINITION (STRUCTURE_LABEL (ENGLISH_LABEL:Latlong)) (STRUCTURE_SEQUENCE (STRUCTURE_SYMBOL:Latitude) (STRUCTURE_SYMBOL:Longitude)))");
376 
377  spec_is_structure_equal(r,_r_get_sem_by_label(r,"Latlong"),latlong);
378  spec_is_long_equal(__r_get_symbol_size(r,lat,0),sizeof(float));
379 
380  Symbol house_loc = _r_define_symbol(r,latlong,"house location");
381  spec_is_sem_equal(__r_get_symbol_structure(r,house_loc),latlong);
382  spec_is_long_equal(__r_get_symbol_size(r,house_loc,0),sizeof(float)*2);
383 
384  Symbol name = _r_define_symbol(r,CSTRING,"name");
385  spec_is_long_equal(__r_get_symbol_size(r,name,"zippy"),(long)6);
386 
387  Structure namedhouse = _r_define_structure(r,"namedhouse",2,house_loc,name);
388 
389  Symbol home = _r_define_symbol(r,namedhouse,"home");
390  char surface[] ={1,2,3,4,5,6,7,8,'b','o','b','b','y',0};
391  spec_is_long_equal(__r_get_symbol_size(r,home,surface),sizeof(float)*2+6);
392 
393  T *code = _t_new_root(NOOP);
394  Process p = _r_define_process(r,code,"do nothing","long version of doing nothing",NULL,NULL);
395  def = _sem_get_def(r->sem,p);
396 
397  spec_is_str_equal(_td(r,def),"(PROCESS_DEFINITION (PROCESS_NAME (ENGLISH_LABEL:do nothing)) (PROCESS_INTENTION:long version of doing nothing) (process:NOOP) (PROCESS_SIGNATURE))");
398 
399  _r_free(r);
400 }
401 
407 void defineHouseLocation(Receptor *r,Symbol *lat,Symbol *lon, Structure *latlong, Symbol *house_loc) {
409  *lat = _r_define_symbol(r,FLOAT,"latitude");
410  *lon = _r_define_symbol(r,FLOAT,"longitude");
411  *latlong = _r_define_structure(r,"latlong",2,*lat,*lon);
412  *house_loc = _r_define_symbol(r,*latlong,"house location");
413 }
415 
418  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
419  Symbol lat,lon,house_loc;
420  Structure latlong;
421  defineHouseLocation(r,&lat,&lon,&latlong,&house_loc);
422 
423  T *t = _t_new_root(house_loc);
424  float x = 99.0;
425  T *t_lat = _t_new(t,lat,&x,sizeof(x));
426  T *t_lon = _t_new(t,lon,&x,sizeof(x));
427 
428  T *stx = _r_build_def_semtrex(r,house_loc);
429  char buf[2000];
430  spec_is_str_equal(_dump_semtrex(r->sem,stx,buf),"/house location/(latitude,longitude)");
431  __t_dump(r->sem,stx,0,buf);
432  spec_is_str_equal(buf,"(SEMTREX_SYMBOL_LITERAL (SEMTREX_SYMBOL:house location) (SEMTREX_SEQUENCE (SEMTREX_SYMBOL_LITERAL (SEMTREX_SYMBOL:latitude)) (SEMTREX_SYMBOL_LITERAL (SEMTREX_SYMBOL:longitude))))");
433 
434  // a correctly structured tree should match its definition
435  spec_is_true(_r_def_match(r,house_loc,t));
436 
437  // a correctly structured tree with different semantics shouldn't match its definition
438  t_lon->contents.symbol = lat;
439  spec_is_true(!_r_def_match(r,house_loc,t));
440 
441  // an incorrectly structured tree (i.e. missing a child) shouldn't match its definition
442  _t_detach_by_idx(t,2);
443  spec_is_true(!_r_def_match(r,house_loc,t));
444 
445  _t_free(stx);
446  _t_free(t);
447  _t_free(t_lon);
448  _r_free(r);
450 }
451 
454  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
455  Symbol lat,lon,house_loc;
456  Structure latlong;
457  defineHouseLocation(r,&lat,&lon,&latlong,&house_loc);
458 
459  // create a house location tree
460  T *t = _t_new_root(house_loc);
461  float ll[] = {132.5,92.3};
462  T *t_lat = _t_new(t,lat,&ll[0],sizeof(float));
463  T *t_lon = _t_new(t,lon,&ll[1],sizeof(float));
464 
465  Xaddr x = _r_new_instance(r,t);
466  spec_is_equal(x.addr,1);
467  spec_is_sem_equal(x.symbol,house_loc);
468 
469  float *ill;
470  T *i = _r_get_instance(r,x);
471 
472  wjson(r->sem,i,"houseloc",-1);
473  spec_is_ptr_equal(i,t);
474 
475  _r_delete_instance(r,x);
476  i = _r_get_instance(r,x);
477  spec_is_ptr_equal(i,NULL);
478 
479  _r_free(r);
481 }
482 
485 
486  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
487  Symbol lat,lon,house_loc;
488  Structure latlong;
489  lat = _r_get_sem_by_label(r,"latitude");
490  lon = _r_get_sem_by_label(r,"longitude");
491  house_loc = _r_get_sem_by_label(r,"house location");
492  latlong = _r_get_sem_by_label(r,"latlong");
493 
494  // create a house location tree
495  T *t = _t_new_root(house_loc);
496  float ll[] = {132.5,92.3};
497  T *t_lat = _t_new(t,lat,&ll[0],sizeof(float));
498  T *t_lon = _t_new(t,lon,&ll[1],sizeof(float));
499 
500  Xaddr x = _r_new_instance(r,t);
501 
502  // also add a sub-receptor as an instance so we can test proper
503  // serialization of nested receptors
504  Receptor *r2 = _r_new(G_sem,TEST_RECEPTOR);
505  T *ir = _t_new_receptor(0,TEST_RECEPTOR,r2);
506  Xaddr xr = _r_new_instance(r,ir);
507  T *t2 = _t_newi(0,TEST_INT_SYMBOL,314);
508  Xaddr x2 = _r_new_instance(r2,t2);
509 
510  void *surface;
511  size_t length;
512  char buf[2000];
513  char buf1[2000];
514 
515  T *signal_contents = _t_newi(0,TEST_INT_SYMBOL,314);
516  ReceptorAddress from = {3}; // DUMMY ADDR
517  ReceptorAddress to = {4}; // DUMMY ADDR
518 
519  // add a signal too
520  T *s = __r_make_signal(from,to,DEFAULT_ASPECT,TESTING,signal_contents,0,0,0);
521  _r_deliver(r,s);
522 
523  _r_serialize(r,&surface,&length);
524 
525  // serialized receptor is two stacked serialized mtrees, first one for the state tree
526  // and then the second for the receptor's instances
527  S *s1 = (S *)surface;
528  S *s2 = (S *)(surface + s1->total_size);
529  spec_is_long_equal(length,s1->total_size+s2->total_size);
530  // spec_is_long_equal(length,250);
531  // spec_is_long_equal(*(size_t *)surface,250);
532 
533  Receptor *ru = _r_unserialize(G_sem,surface);
534  // __r_dump_instances(r);
535  // __r_dump_instances(ru);
536 
537  // check that the structures look the same by comparing a string dump of the two
538  // receptors
539  __t_dump(r->sem,r->root,0,buf);
540  __t_dump(ru->sem,ru->root,0,buf1);
541  spec_is_str_equal(buf1,buf);
542 
543  // check flux
544  spec_is_sem_equal(_t_symbol(ru->flux),FLUX);
545  spec_is_sem_equal(_t_symbol(ru->pending_signals),PENDING_SIGNALS);
546  spec_is_sem_equal(_t_symbol(ru->pending_responses),PENDING_RESPONSES);
547 
548  // check that the unserialized receptor is matched up to the correct definitions in the semtable
549  spec_is_sem_equal(_r_get_sem_by_label(ru,"latitude"),lat);
550  spec_is_sem_equal(_r_get_sem_by_label(ru,"latlong"),latlong);
551 
552  // check that the unserialized receptor has all the instances loaded into the instance store too
553  T *t1 = _r_get_instance(ru,x);
554  buf[0] = buf1[0] = 0;
555  __t_dump(r->sem,t,0,buf);
556  __t_dump(ru->sem,t1,0,buf1);
557  spec_is_str_equal(buf1,buf);
558 
559  t1 = _r_get_instance(ru,xr);
560  spec_is_true(t1 != NULL);
561  if (t1) {
562  buf[0] = buf1[0] = 0;
563  __t_dump(r->sem,ir,0,buf);
564  __t_dump(ru->sem,t1,0,buf1);
565  spec_is_str_equal(buf1,buf);
566  Receptor *r3 = __r_get_receptor(t1);
567  t1 = _r_get_instance(r3,x2);
568  spec_is_equal(*(int*)_t_surface(t1),314);
569  _r_free(ru);
570  }
571  //__r_dump_instances(r3); // show the 314 int
572 
573  free(surface);
574  _r_free(r);
576 }
577 
578 
579 Symbol mantissa;
580 Symbol exponent;
581 Symbol exps[16];
582 Structure flt;
583 Structure integer;
584 Symbol latitude;
585 Symbol longitude;
586 Structure lat_long;
587 Symbol home_location;
588 
589 void defineNums(Receptor *r) {
590  int i = 0;
591  char buf[10];
592  for(i=0;i<16;i++){
593  sprintf(buf,"exp%d",i);
594  exps[i] = _r_define_symbol(r,BIT,buf);
595  }
596  integer = _r_define_structure(r,"integer",16,exps[0],exps[1],exps[2],exps[3],exps[4],exps[5],exps[6],exps[7],exps[8],exps[9],exps[10],exps[11],exps[12],exps[13],exps[14],exps[15]);
597  mantissa = _r_define_symbol(r,integer,"mantissa");
598  exponent = _r_define_symbol(r,integer,"exponent");
599  flt = _r_define_structure(r,"float",2,mantissa,exponent);
600  latitude = _r_define_symbol(r,flt,"latitude");
601  longitude = _r_define_symbol(r,flt,"longitude");
602  lat_long = _r_define_structure(r,"latlong",2,latitude,longitude);
603  home_location = _r_define_symbol(r,lat_long,"home_location");
604 }
605 
606 void makeInt(T *t,int v) {
607  int i;
608  for(i=0;i<16;i++){
609  _t_newi(t,exps[i],(v>>i)&1);
610  }
611 }
612 void testReceptorNums() {
613  Receptor *r = _r_new(G_sem,TEST_RECEPTOR);
614  defineNums(r);
615 
616  // create a home location tree
617  T *t = _t_new_root(home_location);
618  T *lat = _t_newr(t,latitude);
619  T *lon = _t_newr(t,longitude);
620  T *m = _t_newr(lat,mantissa);
621  T *e = _t_newr(lat,exponent);
622  makeInt(m,22);
623  makeInt(e,1);
624  m = _t_newr(lon,mantissa);
625  e = _t_newr(lon,exponent);
626  makeInt(m,1);
627  makeInt(e,2);
628  spec_is_str_equal(_td(r,t),"(home_location (latitude (mantissa (exp0:0) (exp1:1) (exp2:1) (exp3:0) (exp4:1) (exp5:0) (exp6:0) (exp7:0) (exp8:0) (exp9:0) (exp10:0) (exp11:0) (exp12:0) (exp13:0) (exp14:0) (exp15:0)) (exponent (exp0:1) (exp1:0) (exp2:0) (exp3:0) (exp4:0) (exp5:0) (exp6:0) (exp7:0) (exp8:0) (exp9:0) (exp10:0) (exp11:0) (exp12:0) (exp13:0) (exp14:0) (exp15:0))) (longitude (mantissa (exp0:1) (exp1:0) (exp2:0) (exp3:0) (exp4:0) (exp5:0) (exp6:0) (exp7:0) (exp8:0) (exp9:0) (exp10:0) (exp11:0) (exp12:0) (exp13:0) (exp14:0) (exp15:0)) (exponent (exp0:0) (exp1:1) (exp2:0) (exp3:0) (exp4:0) (exp5:0) (exp6:0) (exp7:0) (exp8:0) (exp9:0) (exp10:0) (exp11:0) (exp12:0) (exp13:0) (exp14:0) (exp15:0))))");
629  wjson(r->sem,t,"homeloc",-1);
630 
631  _t_free(t);
632  _r_free(r);
633 }
634 
635 void testReceptorEdgeStream() {
636  FILE *rs,*ws;
637  char buffer[] = "line1\nline2\n";
638 
639  rs = fmemopen(buffer, strlen (buffer), "r");
640  Stream *reader_stream = _st_new_unix_stream(rs,1);
641 
642  VMHost *v = _v_new();
643 
644  char *output_data;
645  size_t size;
646  ws = open_memstream(&output_data,&size);
647  Stream *writer_stream = _st_new_unix_stream(ws,0);
648 
649  Receptor *r = _r_makeStreamEdgeReceptor(v->sem);
650  Xaddr edge = _v_new_receptor(v,v->r,STREAM_EDGE,r);
651  _r_addWriter(r,writer_stream,DEFAULT_ASPECT);
652  _r_addReader(r,reader_stream,r->addr,DEFAULT_ASPECT,LINE,LINE,false);
653 
654  spec_is_str_equal(_td(r,__r_get_expectations(r,DEFAULT_ASPECT)),"(EXPECTATIONS (EXPECTATION (CARRIER:NULL_SYMBOL) (PATTERN (SEMTREX_SYMBOL_ANY)) (ACTION:echo2stream) (PARAMS (EDGE_STREAM) (SLOT (USAGE:NULL_SYMBOL))) (END_CONDITIONS (UNLIMITED))))");
655 
656  // manually run the reader's process queue
657  //debug_enable(D_STREAM);
658  Q *q = r->q;
659  Stream *st = reader_stream;
660  spec_is_equal(_p_reduceq(q),noReductionErr);
661  while(!(st->flags&StreamHasData) && st->flags&StreamAlive ) {sleepms(1);};
662  spec_is_equal(_p_reduceq(q),noReductionErr);
663  while(!(st->flags&StreamHasData) && st->flags&StreamAlive ) {sleepms(1);};
664  spec_is_equal(_p_reduceq(q),noReductionErr);
665  while(!(st->flags&StreamHasData) && st->flags&StreamAlive ) {sleepms(1);};
666  spec_is_equal(_p_reduceq(q),noReductionErr);
667  //debug_disable(D_STREAM);
668  spec_is_false(_st_is_alive(st));
669 
670  spec_is_false(r->q->completed == NULL);
671  if (r->q->completed) {
672  spec_is_equal(r->q->completed->context->err,deadStreamReadReductionErr);
673  }
674  /* T *result = r->q->blocked->context->run_tree; */
675 
676  /* /// @todo BOOLEAN is what's left from the replicate. Should it be something else? */
677  /* spec_is_str_equal(_td(r,result),"(RUN_TREE (BOOLEAN:0))"); */
678 
679  spec_is_str_equal(_td(r,r->pending_signals),"(PENDING_SIGNALS (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:3)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE)) (BODY:{(LINE:line1)}))) (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:3)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE)) (BODY:{(LINE:line2)}))))");
680 
681  // manually run the signal sending code
682  _v_deliver_signals(v,r);
683 
684  // and see that they've shown up in the edge receptor's flux signals list
685  spec_is_str_equal(_td(r,__r_get_signals(r,DEFAULT_ASPECT)),"(SIGNALS (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:3)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE)) (BODY:{(LINE:line1)})) (RUN_TREE (process:STREAM_WRITE (PARAM_REF:/2/1) (process:TRANSCODE (TRANSCODE_PARAMS (TRANSCODE_TO:LINES)) (TRANSCODE_ITEMS (PARAM_REF:/2/2)))) (PARAMS (EDGE_STREAM) (LINE:line1)))) (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:3)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE)) (BODY:{(LINE:line2)})) (RUN_TREE (process:STREAM_WRITE (PARAM_REF:/2/1) (process:TRANSCODE (TRANSCODE_PARAMS (TRANSCODE_TO:LINES)) (TRANSCODE_ITEMS (PARAM_REF:/2/2)))) (PARAMS (EDGE_STREAM) (LINE:line2)))))");
686 
687  // and that they've been removed from process queue pending signals list
688  spec_is_str_equal(_td(r,r->pending_signals),"(PENDING_SIGNALS)");
689 
690  spec_is_str_equal(_td(r,r->q->active->context->run_tree),"(RUN_TREE (process:STREAM_WRITE (PARAM_REF:/2/1) (process:TRANSCODE (TRANSCODE_PARAMS (TRANSCODE_TO:LINES)) (TRANSCODE_ITEMS (PARAM_REF:/2/2)))) (PARAMS (EDGE_STREAM) (LINE:line1)))");
691 
692  // manually run the process queue
693  //debug_enable(D_REDUCE+D_STEP);
694  _p_reduceq(r->q);
695  debug_disable(D_REDUCE+D_STEP);
696 
697  spec_is_str_equal(_td(r,r->q->completed->context->run_tree),"(RUN_TREE (REDUCTION_ERROR_SYMBOL:NULL_SYMBOL) (PARAMS (EDGE_STREAM) (LINE:line2)))");
698 
699  spec_is_str_equal(output_data,"line1\nline2\n");
700 
701  _st_free(reader_stream);
702  _st_free(writer_stream);
703  free(output_data);
704  _v_free(v);
705 }
706 
707 void *_ltester(void *arg) {
708  char *result = doSys("echo 'testing!\nfish\n' | nc localhost 8888");
709  spec_is_str_equal(result,"testing!\nfish\n\n");
710  free(result);
711  G_done = true;
712  pthread_exit(NULL);
713 }
714 
715 void testReceptorEdgeListener() {
716  VMHost *v = _v_new();
717  Receptor *r = _r_makeStreamEdgeReceptor(v->sem);
718  Xaddr edge = _v_new_receptor(v,v->r,STREAM_EDGE,r);
719 
720  /*
721  (RUN_TREE
722  (INITIATE (PNAME:HTTP)
723  (WHICH_INTERACTION:backnforth)
724  (BINDINGS)
725  )
726  )
727  (RUN_TREE
728  (CONVERSE
729  (SCOPE
730  (LISTEN <aspect> <carrier> <match> (ACTION:echo2stream) (PARAMS (EDGE_STREAM) (SLOT (NULL_SYMBOL))))
731  (LISTEN CONTROL <carrier> (PATTERN (CLOSE)) (STREAM_CLOSE (EDGE_STREAM)))
732 
733  (ITERATE (PARAMS) (STREAM_ALIVE (EDGE_STREAM))
734  (SAY <to> <aspect> <carrier> (STREAM_READ (EDGE_STREAM) (RESULT_SYMBOL:<result>)))))
735 
736 
737  (END_CONDITIONS (TIMEOUT_VALUE_HERE))
738  (BOOLEAN:1) )
739 
740  (PARAMS)
741 
742  (COND (CONDITIONS
743  (COND_PAIR (EQ_SYM (SYMBOL_OF (PARAM_REF:/4/1)) (RESULT_SYMBOL:READ_ON_DEAD_STREAM_ERROR))
744  (CONTINUE (POP_PATH (PARAM_REF:/4/1/1) (RESULT_SYMBOL:CONTINUE_LOCATION) (POP_COUNT:2))
745  (CONTINUE_VALUE (BOOLEAN:0))))
746  (COND_ELSE (RAISE (PARAM_REF:/4/1)))
747  ))
748 
749  (PARAMS (READ_ON_DEAD_STREAM_ERROR (ERROR_LOCATION:/1/1/3/3/4))))
750 
751  */
752 
753  T *code = _t_parse(r->sem,0,"(CONVERSE (SCOPE (LISTEN (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE) (PATTERN (SEMTREX_SYMBOL_ANY)) (ACTION:echo2stream) (PARAMS (PARAM_REF:/2/1) (SLOT (USAGE:NULL_SYMBOL)))) (ITERATE (PARAMS) (STREAM_ALIVE (PARAM_REF:/2/1)) (SAY % (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE) (STREAM_READ (PARAM_REF:/2/1) (RESULT_SYMBOL:LINE)))) (STREAM_CLOSE (PARAM_REF:/2/1))) (BOOLEAN:1))",__r_make_addr(0,TO_ADDRESS,r->addr));
754  T *err_handler = _t_parse(r->sem,0,"(CONTINUE (POP_PATH (PARAM_REF:/4/1/1) (RESULT_SYMBOL:CONTINUE_LOCATION) (POP_COUNT:2)) (CONTINUE_VALUE (BOOLEAN:0)))");
755  // listen and then send the received LINE directly back to your self. Acts like "echo."
756  SocketListener *l = _r_addListener(r,8888,code,0,err_handler,DELIM_LF);
757  _v_activate(v,edge);
758 
759  //@todo currently we don't actually have a real symbol for the EDGE_SPEC and we're just using PARAMS. FIXME!
760  spec_is_str_equal(_t2s(v->sem,r->edge),"(PARAMS (EDGE_LISTENER) (process:CONVERSE (SCOPE (process:LISTEN (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE) (PATTERN (SEMTREX_SYMBOL_ANY)) (ACTION:echo2stream) (PARAMS (PARAM_REF:/2/1) (SLOT (USAGE:NULL_SYMBOL)))) (process:ITERATE (PARAMS) (process:STREAM_ALIVE (PARAM_REF:/2/1)) (process:SAY (TO_ADDRESS (RECEPTOR_ADDR:3)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE) (process:STREAM_READ (PARAM_REF:/2/1) (RESULT_SYMBOL:LINE)))) (process:STREAM_CLOSE (PARAM_REF:/2/1))) (BOOLEAN:1)) (PARAMS) (process:CONTINUE (process:POP_PATH (PARAM_REF:/4/1/1) (RESULT_SYMBOL:CONTINUE_LOCATION) (POP_COUNT:2)) (CONTINUE_VALUE (BOOLEAN:0))))");
761  _v_start_vmhost(v);
762  //debug_enable(D_STREAM+D_SOCKET+D_SIGNALS+D_STEP);//+D_REDUCE+D_REDUCEV
763 
764  G_done = false;
765  pthread_t thread;
766  int rc;
767  rc = pthread_create(&thread,0,_ltester,NULL);
768  if (rc){
769  raise_error("ERROR; return code from pthread_create() is %d\n", rc);
770  }
771  pthread_detach(thread);
772  if (rc){
773  raise_error("Error detaching tester thread; return code from pthread_detach() is %d\n", rc);
774  }
775  while(!G_done) sleepms(1);
776  __r_kill(v->r);
777  _v_join_thread(&v->vm_thread);
778 
779  debug_disable(D_STREAM+D_SOCKET+D_SIGNALS+D_STEP+D_REDUCE+D_REDUCEV);
780  spec_is_str_equal(t2s(r->flux),"(FLUX (DEFAULT_ASPECT (EXPECTATIONS (EXPECTATION (CARRIER:LINE) (PATTERN (SEMTREX_SYMBOL_ANY)) (ACTION:echo2stream) (PARAMS (EDGE_STREAM) (SLOT (USAGE:NULL_SYMBOL))) (END_CONDITIONS (UNLIMITED)) (CONVERSATION_IDENT (CONVERSATION_UUID)))) (SIGNALS (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:3)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE) (CONVERSATION_IDENT (CONVERSATION_UUID))) (BODY:{(LINE:testing!)})) (RUN_TREE (REDUCTION_ERROR_SYMBOL:NULL_SYMBOL) (PARAMS (EDGE_STREAM) (LINE:testing!)))) (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:3)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE) (CONVERSATION_IDENT (CONVERSATION_UUID))) (BODY:{(LINE:fish)})) (RUN_TREE (REDUCTION_ERROR_SYMBOL:NULL_SYMBOL) (PARAMS (EDGE_STREAM) (LINE:fish)))) (SIGNAL (ENVELOPE (SIGNAL_UUID)) (MESSAGE (HEAD (FROM_ADDRESS (RECEPTOR_ADDR:3)) (TO_ADDRESS (RECEPTOR_ADDR:3)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:LINE) (CONVERSATION_IDENT (CONVERSATION_UUID))) (BODY:{(LINE:)})) (RUN_TREE (REDUCTION_ERROR_SYMBOL:NULL_SYMBOL) (PARAMS (EDGE_STREAM) (LINE:)))))))");
781 
782  _v_free(v);
783 
784 }
785 
786 void testReceptorClock() {
787  Receptor *r = _r_makeClockReceptor(G_sem);
788  spec_is_str_equal(_td(r,r->root),"(RECEPTOR_INSTANCE (INSTANCE_OF:CLOCK_RECEPTOR) (CONTEXT_NUM:4) (PARENT_CONTEXT_NUM:0) (RECEPTOR_STATE (FLUX (DEFAULT_ASPECT (EXPECTATIONS (EXPECTATION (CARRIER:tell_time) (PATTERN (SEMTREX_SYMBOL_LITERAL (SEMTREX_SYMBOL:CLOCK_TELL_TIME))) (ACTION:respond with current time) (PARAMS) (END_CONDITIONS (UNLIMITED)))) (SIGNALS))) (PENDING_SIGNALS) (PENDING_RESPONSES) (CONVERSATIONS) (RECEPTOR_ELAPSED_TIME:0)))");
789 
790  /*
791  The clock receptor should do two things: respond to CLOCK_TELL_TIME signals with the current time, and also allow you to plant a listener based on a semtrex for any kind of time you want. If you want the current time just plant a listener for TICK. If you want to listen for every second plant a listener on the Symbol literal SECOND, and the clock receptor will trigger the listener every time the SECOND changes. You can also listen for particular intervals and times by adding specificity to the semtrex, so to trigger a 3:30am action a-la-cron listen for: "/<TICK:(%HOUR=3,MINUTE=30)>"
792  @todo we should also make the clock receptor also respond to other semantic formats, i.e. so it's easy to listen for things like "on Wednesdays", or other semantic date/time identifiers.
793  */
794  Protocol time;
795  __sem_get_by_label(G_sem,"time",&time,r->context);
796  T *def = _sem_get_def(G_sem,time);
797  spec_is_str_equal(_td(r,def),"(PROTOCOL_DEFINITION (PROTOCOL_LABEL (ENGLISH_LABEL:time)) (PROTOCOL_SEMANTICS (ROLE:TIME_TELLER) (ROLE:TIME_HEARER) (GOAL:RESPONSE_HANDLER)) (tell_time (INITIATE (ROLE:TIME_HEARER) (DESTINATION (ROLE:TIME_TELLER)) (ACTION:time_request)) (EXPECT (ROLE:TIME_TELLER) (SOURCE (ROLE:TIME_HEARER)) (PATTERN (SEMTREX_SYMBOL_LITERAL (SEMTREX_SYMBOL:CLOCK_TELL_TIME))) (ACTION:respond with current time))))");
798 
799  // debug_enable(D_SIGNALS);
800 
801  // send the clock receptor a "tell me the time" request by initiating the tell_time interaction in the protocol
802 
803  T *bindings = _t_new_root(PROTOCOL_BINDINGS);
804  T *res = _t_newr(bindings,RESOLUTION);
805  T *w = _t_newr(res,WHICH_RECEPTOR);
806  _t_news(w,ROLE,TIME_TELLER);
807  __r_make_addr(w,ACTUAL_RECEPTOR,r->addr);
808  res = _t_newr(bindings,RESOLUTION);
809  w = _t_newr(res,WHICH_RECEPTOR);
810  _t_news(w,ROLE,TIME_HEARER);
811  __r_make_addr(w,ACTUAL_RECEPTOR,r->addr);
812  res = _t_newr(bindings,RESOLUTION);
813  w = _t_newr(res,WHICH_PROCESS);
814  _t_news(w,GOAL,RESPONSE_HANDLER);
815 
816  // @todo bleah, this should be a better proc, at least with a SIGNAL_REF
817  // or something.
818  T *noop = _t_new_root(NOOP);
819  _t_newi(noop,TEST_INT_SYMBOL,314);
820  Process proc = _r_define_process(r,noop,"do nothing","long desc...",NULL,NULL);
821  _t_news(w,ACTUAL_PROCESS,proc);
822 
823  _o_initiate(r,time,tell_time,bindings);
824 
825  spec_is_str_equal(_td(r,r->q->active->context->run_tree),"(RUN_TREE (process:do nothing (process:REQUEST (TO_ADDRESS (RECEPTOR_ADDR:4)) (ASPECT_IDENT:DEFAULT_ASPECT) (CARRIER:tell_time) (CLOCK_TELL_TIME) (RESPONSE_CARRIER:tell_time))) (PARAMS))");
826 
827  _test_reduce_signals(r);
828 
829  // we need a better indicator of success, but this at least shows that pending signals and
830  // pending responses created should have been cleaned up.
831  spec_is_str_equal(_td(r,r->pending_signals),"(PENDING_SIGNALS)");
832  spec_is_str_equal(_td(r,r->pending_responses),"(PENDING_RESPONSES)");
833 
834  debug_disable(D_SIGNALS);
835 
836  Xaddr x = {TICK,1};
837  T* tick = _r_get_instance(r,x);
838 
839  // clone the initial tick for later comparison
840  tick = _t_clone(tick);
841 
842  // "run" the receptor and verify that the tick instance keeps getting updated
843  // we wait a second first so that the first update will be a second later
844  sleepms(1005);
845  pthread_t thread;
846  int rc = 0;
847  rc = pthread_create(&thread,0,___clock_thread,r);
848  if (rc){
849  raise_error("ERROR; return code from pthread_create() is %d\n", rc);
850  }
851 
852  sleepms(1);
853  T* ntick = _r_get_instance(r,x);
854  int p[] = {2,3,TREE_PATH_TERMINATOR};
855  spec_is_equal(*(int *)_t_surface(_t_get(ntick,p)),
856  1+*(int *)_t_surface(_t_get(tick,p)) // should be 1 second later!
857  );
858 
859  __r_kill(r);
860 
861  void *status;
862  rc = pthread_join(thread, &status);
863 
864  if (rc) {
865  raise_error("ERROR; return code from pthread_join() is %d\n", rc);
866  }
867 
868  debug_disable(D_SIGNALS);
869  _t_free(tick);
870  _r_free(r);
871 }
872 
873 void testReceptor() {
875  testReceptorAddRemoveExpectation();
876  testReceptorSignal();
877  testReceptorSignalDeliver();
878  testReceptorResponseDeliver();
879  testReceptorDeliverConversation();
880  testReceptorConversations();
881  testReceptorEndCondition();
883  testReceptorDef();
887  testReceptorNums();
888  testReceptorEdgeStream();
889  testReceptorEdgeListener();
890  testReceptorClock();
891 }
T * _t_new_root(Symbol symbol)
Definition: tree.c:160
T * edge
data store for edge receptors
Definition: ceptr_types.h:252
Definition: ceptr_types.h:114
Structure __r_get_symbol_structure(Receptor *r, Symbol s)
find a symbol's structure
Definition: receptor.c:299
void _r_serialize(Receptor *r, void **surfaceP, size_t *lengthP)
Definition: receptor.c:432
Definition: stream.h:30
void testReceptorCreate()
Definition: receptor_spec.h:17
Definition: ceptr_types.h:206
T * _t_get(T *t, int *p)
Definition: tree.c:1441
T * _t_detach_by_idx(T *t, int i)
Definition: tree.c:278
void testReceptorDefMatch()
[defineHouseLocation]
void testReceptorInstances()
T * _t_new_receptor(T *parent, Symbol symbol, Receptor *r)
Definition: tree.c:204
void testReceptorSerialize()
Definition: ceptr_types.h:68
T * _t_clone(T *t)
Definition: tree.c:589
void _r_free(Receptor *r)
Definition: receptor.c:186
Error _p_reduceq(Q *q)
Definition: process.c:2126
Symbol _t_symbol(T *t)
Definition: tree.c:1228
T * _t_child(T *t, int i)
Definition: tree.c:1251
Receptor * __r_get_receptor(T *installed_receptor)
Definition: receptor.c:1039
T * _t_newp(T *parent, Symbol symbol, Process surface)
Definition: tree.c:251
int err
process error value
Definition: ceptr_types.h:170
void _v_free(VMHost *v)
Definition: vmhost.c:71
Context context
the context this receptor's definition creates
Definition: ceptr_types.h:240
ReceptorAddress addr
the address by which to get messages to this receptor instance
Definition: ceptr_types.h:241
Definition: vmhost.h:20
Structure _r_define_structure(Receptor *r, char *label, int num_params,...)
Definition: receptor.c:236
void _r_add_expectation(Receptor *r, Aspect aspect, Symbol carrier, T *pattern, T *action, T *with, T *until, T *using, T *cid)
Adds an expectation to a receptor's aspect.
Definition: receptor.c:164
VMHost * _v_new()
Creates a new virtual machine host.
Definition: vmhost.c:41
Q * q
process queue
Definition: ceptr_types.h:250
void * _t_surface(T *t)
Definition: tree.c:1215
T * _t_get_match(T *match, Symbol group)
Definition: semtrex.c:848
T * flux
pointer for quick access to the flux
Definition: ceptr_types.h:243
void _v_activate(VMHost *v, Xaddr x)
Definition: vmhost.c:172
Receptor * _r_new(SemTable *sem, SemanticID r)
Creates a new receptor.
Definition: receptor.c:88
void testReceptorExpectation()
SemTable * sem
Semantic Table for definitions on this host.
Definition: vmhost.h:44
void _makeTestHTTPResponseProcess(Receptor *r, T **paramsP, Process *pP)
[makeTestHTTPRequestTree]
Definition: http_example.h:51
Receptor * _r_unserialize(SemTable *sem, void *surface)
Definition: receptor.c:459
Qe * active
active processes
Definition: ceptr_types.h:209
Symbol _r_get_sem_by_label(Receptor *r, char *label)
Definition: receptor.c:288
int contexts_count
number of active processes
Definition: ceptr_types.h:208
void _st_free(Stream *st)
Definition: stream.c:507
void _o_initiate(Receptor *r, SemanticID protocol, SemanticID interaction, T *bindings)
Definition: protocol.c:506
int _t_matchr(T *semtrex, T *t, T **rP)
Definition: semtrex.c:798
Definition: vmhost.h:40
T * __r_make_signal(ReceptorAddress from, ReceptorAddress to, Aspect aspect, Symbol carrier, T *signal_contents, UUIDt *in_response_to, T *until, T *cid)
Definition: receptor.c:515
T * _r_build_def_semtrex(Receptor *r, Symbol s)
Definition: receptor.c:325
void defineHouseLocation(Receptor *r, Symbol *lat, Symbol *lon, Structure *latlong, Symbol *house_loc)
[defineHouseLocation]
T * root
RECEPTOR_INSTANCE semantic tree.
Definition: ceptr_types.h:238
Qe * blocked
blocked processes
Definition: ceptr_types.h:211
SemTable * sem
pointer back to the genotype table for this receptor's vmhost instance
Definition: ceptr_types.h:242
size_t __r_get_symbol_size(Receptor *r, Symbol s, void *surface)
Definition: receptor.c:314
T * _makeTestHTTPRequestTree()
[makeTestHTTPRequestTree]
Definition: http_example.h:26
T * _r_get_instance(Receptor *r, Xaddr x)
Definition: receptor.c:379
void * ___clock_thread(void *arg)
Definition: receptor.c:1250
Receptor * r
Receptor data for this vm host.
Definition: vmhost.h:43
#define _sl(t, s)
macro to add a single symbol literal to semtrex tree
Definition: semtrex.h:122
T * parseSemtrex(SemTable *sem, char *stx)
Definition: semtrex.c:1298
Qe * completed
completed processes (pending cleanup)
Definition: ceptr_types.h:210
T * _t_parse(SemTable *sem, T *parent, char *s,...)
Definition: tree.c:919
T * run_tree
pointer to the root of the run_tree
Definition: ceptr_types.h:172
void _t_add(T *t, T *c)
Definition: tree.c:261
Symbol _r_define_symbol(Receptor *r, Structure s, char *label)
Definition: receptor.c:218
void _v_deliver_signals(VMHost *v, Receptor *sender)
Definition: vmhost.c:235
Error _r_deliver(Receptor *r, T *signal)
Definition: receptor.c:954
char * _dump_semtrex(SemTable *sem, T *s, char *buf)
Definition: semtrex.c:1096
Process _r_define_process(Receptor *r, T *code, char *name, char *intention, T *signature, T *link)
Definition: receptor.c:275
void _t_free(T *t)
Definition: tree.c:526
T * _r_delete_instance(Receptor *r, Xaddr x)
Definition: receptor.c:407
int _r_def_match(Receptor *r, Symbol s, T *t)
Definition: receptor.c:343
Xaddr _r_new_instance(Receptor *r, T *t)
Definition: receptor.c:365