feisty meow concerns codebase  2.140
test_cromp_server.cpp
Go to the documentation of this file.
1 /*****************************************************************************\
2 * *
3 * Name : test_cromp_server *
4 * Author : Chris Koeritz *
5 * *
6 *******************************************************************************
7 * Copyright (c) 2002-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
14 
15 #include "crompish_pax.h"
16 
20 #include <basis/astring.h>
21 #include <basis/byte_array.h>
22 #include <basis/functions.h>
23 #include <cromp/cromp_server.h>
24 #include <loggers/console_logger.h>
25 #include <loggers/file_logger.h>
27 #include <octopus/tentacle.h>
29 #include <sockets/machine_uid.h>
30 #include <sockets/tcpip_stack.h>
32 #include <timely/time_control.h>
33 #include <timely/time_stamp.h>
34 #include <unit_test/unit_base.h>
35 
36 using namespace application;
37 using namespace basis;
38 using namespace configuration;
39 using namespace cromp;
40 using namespace mathematics;
41 using namespace filesystem;
42 using namespace loggers;
43 using namespace octopi;
44 using namespace processes;
45 using namespace sockets;
46 using namespace structures;
47 using namespace textual;
48 using namespace timely;
49 using namespace unit_test;
50 
51 #define LOG(a) CLASS_EMERGENCY_LOG(program_wide_logger::get(), a)
52 
53 const int REPORTING_INTERVAL = 28 * SECOND_ms; // how often to squawk.
54 
55 //const int ACCEPTING_THREADS = 5;
56 const int ACCEPTING_THREADS = 1;
57 
58 // specifies whether to support lazy evaluation by tentacles.
59 //const bool SUPPORT_BACKGROUNDING = true;
60 const bool SUPPORT_BACKGROUNDING = false;
61 
62 // determines whether the octopus will do immediate evaluation or not.
63 //const bool IMMEDIATE_EVALUATION = true;
64 const bool IMMEDIATE_EVALUATION = false;
65 
67 
68 // forward.
69 class cromp_server_tester;
70 
71 class our_cromp_server : public cromp_server
72 {
73 public:
74  our_cromp_server(cromp_server_tester &parent, const internet_address &addr)
76  _parent(parent) {}
77 
78  ~our_cromp_server() {}
79 
80  DEFINE_CLASS_NAME("our_cromp_server");
81 
82 private:
83  cromp_server_tester &_parent;
84 };
85 
87 
88 class cromp_server_tester : virtual public unit_base, virtual public application_shell
89 {
90 public:
91  bool _saw_clients; // true if we ever got a connection.
92 
93  cromp_server_tester();
94  ~cromp_server_tester();
95 
96  virtual int execute();
97 
98  DEFINE_CLASS_NAME("cromp_server_tester");
99 
100 private:
101  our_cromp_server *_uplink;
102  // provides the connection and transmission services.
103  bool _leave_when_no_clients; // true if we should just do one run.
104  bool _encryption; // true if we should do an encrypted connection.
105  internet_address c_address;
106 };
107 
109 
110 class real_bubbles_tentacle : public bubbles_tentacle
111 {
112 public:
113  real_bubbles_tentacle(cromp_server_tester &parent, bool backgrounding)
114  : bubbles_tentacle(backgrounding), _parent(parent) {}
115 
116  virtual outcome consume(infoton &to_chow, const octopus_request_id &item_id,
117  byte_array &transformed)
118  {
119  transformed.reset();
120  _parent._saw_clients = true; // we saw someone.
121 //LOG("got to our cromp's bubble tentacle.");
122  bubble *inf = dynamic_cast<bubble *>(&to_chow);
123  if (!inf) return NO_HANDLER;
124 //LOG("caching product! success getting unpacked etc.");
125  bubble *junk = dynamic_cast<bubble *>(inf->clone());
126  store_product(junk, item_id);
127  return OKAY;
128  }
129 
130 private:
131  cromp_server_tester &_parent;
132 };
133 
135 
136 cromp_server_tester::cromp_server_tester()
139  _saw_clients(false),
140  _uplink(NULL_POINTER),
141  _leave_when_no_clients(false),
142  _encryption(false)
143 {
144  FUNCDEF("constructor");
146  LOG("");
147  LOG("");
148 
150  // check for a port on the command line.
151  astring port_text;
152  int port = 5678;
153  if (args.get_value("port", port_text, false)) {
154  LOG(astring("using port: ") + port_text);
155  port = port_text.convert(5678);
156  }
157  int posn = 0;
158  if (args.find("exit", posn)) {
159  LOG("seeing the 'exit without clients' flag set.");
160  _leave_when_no_clients = true;
161  }
162 
163 //hmmm:normalize host so this can take either name or IP.
164 
165  // check for a hostname on the command line.
166  astring hostname("local");
167  astring host_temp;
168  if (args.get_value("host", host_temp, false)) {
169  LOG(astring("using host: ") + host_temp);
170  hostname = host_temp;
171  }
172  strcpy(c_address.hostname, hostname.s());
173 
174 //LOG(astring("here's the command line:") + parser_bits::platform_eol_to_chars() + args.text_form());
175 
176  int indy = 0;
177  if (args.find("encrypt", indy) || (args.find('e', indy)) ) {
178  // they're saying that we should encrypt the communication.
179  LOG("turning on encryption.");
180  _encryption = true;
181  }
182 
183 // tcpip_stack stack;
184 // machine_uid host = stack.this_host(machine_uid::TCPIP_LOCATION);
185  c_address.port = port;
186 // host.native().stuff(internet_address::ADDRESS_SIZE, c_address.ip_address);
187  LOG("starting cromp_server");
188  _uplink = new our_cromp_server(*this, c_address);
189  _uplink->add_tentacle(new real_bubbles_tentacle(*this, SUPPORT_BACKGROUNDING));
190  _uplink->enable_servers(_encryption);
191 }
192 
193 cromp_server_tester::~cromp_server_tester()
194 {
195  WHACK(_uplink);
196 }
197 
198 int cromp_server_tester::execute()
199 {
200  FUNCDEF("execute");
201 
202  time_stamp next_report(REPORTING_INTERVAL);
203 
204  while (true) {
205  // make sure we didn't see our exit condition.
206  if (!_uplink->clients() && _leave_when_no_clients && _saw_clients) {
207  LOG("exiting now");
208  break;
209  }
210 
211  if (time_stamp() > next_report) {
212  int client_count = _uplink->clients();
213  const char *verb = "are";
214  if (client_count == 1) verb = "is";
215  const char *ending = "s";
216  if (client_count == 1) ending = "";
217  LOG(a_sprintf("There %s %d client%s.", verb, client_count, ending));
218  next_report.reset(REPORTING_INTERVAL);
219  }
220 
221 // new test case; rip out server while still possibly connected.
222 if (randomizer().inclusive(1, 200) == 32) {
223 LOG("tearing down entire server and re-creating.");
224 WHACK(_uplink);
225 _uplink = new our_cromp_server(*this, c_address);
226 _uplink->add_tentacle(new real_bubbles_tentacle(*this, SUPPORT_BACKGROUNDING));
227 _uplink->enable_servers(_encryption);
228 }
229 
230  time_control::sleep_ms(100);
231  }
232  return 0;
233 }
234 
236 
237 HOOPLE_MAIN(cromp_server_tester, )
238 
The application_shell is a base object for console programs.
a_sprintf is a specialization of astring that provides printf style support.
Definition: astring.h:440
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition: array.h:349
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
int convert(int default_value) const
Converts the string into a corresponding integer.
Definition: astring.cpp:760
A very common template for a dynamic array of bytes.
Definition: byte_array.h:36
Outcomes describe the state of completion for an operation.
Definition: outcome.h:31
virtual clonable * clone() const
must be provided to allow creation of a copy of this object.
Definition: crompish_pax.h:59
An infoton is an individual request parcel with accompanying information.
Definition: infoton.h:32
Identifies requests made on an octopus by users.
Definition: entity_defs.h:114
this type of address describes a destination out on the internet.
Represents a point in time relative to the operating system startup time.
Definition: time_stamp.h:38
#define NULL_POINTER
The value representing a pointer to nothing.
Definition: definitions.h:32
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Definition: enhance_cpp.h:42
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:54
Provides macros that implement the 'main' program of an application.
#define HOOPLE_MAIN(obj_name, obj_args)
options that should work for most unix and linux apps.
Definition: hoople_main.h:61
Implements an application lock to ensure only one is running at once.
char ** _global_argv
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition: functions.h:121
const int SECOND_ms
Number of milliseconds in a second.
Definition: definitions.h:120
A platform independent way to obtain the timestamp of a file.
Definition: byte_filer.cpp:37
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
Definition: averager.h:21
Provides access to the operating system's socket methods.
Definition: base_address.h:26
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
#include <time.h>
Definition: earth_time.cpp:37
Useful support functions for unit testing, especially within hoople.
Definition: unit_base.cpp:35
#define randomizer()
const bool SUPPORT_BACKGROUNDING
#define LOG(a)
const bool IMMEDIATE_EVALUATION
const int REPORTING_INTERVAL
const int ACCEPTING_THREADS