tentacles \
cromp \
synchronic \
- tests_sockets
+ tests_sockets
+
+# tests_octopus
include rules.def
--- /dev/null
+CONSOLE_MODE = t
+
+include cpp/variables.def
+
+PROJECT = tests_octopus
+TYPE = test
+TARGETS = t_bin.exe t_bin_threaded.exe t_entity.exe t_identity.exe \
+ t_security.exe t_unpacker.exe t_file_transfer.exe
+LOCAL_LIBS_USED = tentacles octopus sockets unit_test application configuration loggers \
+ textual timely processes filesystem structures basis
+VCPP_USE_SOCK = t
+RUN_TARGETS = $(ACTUAL_TARGETS)
+
+include cpp/rules.def
+
--- /dev/null
+/*****************************************************************************\
+* *
+* Name : entity_data_bin tester *
+* Author : Chris Koeritz *
+* *
+* Purpose: *
+* *
+* Checks that the entity_data_bin class is behaving as expected. *
+* *
+*******************************************************************************
+* Copyright (c) 2002-$now By Author. This program is free software; you can *
+* redistribute it and/or modify it under the terms of the GNU General Public *
+* License as published by the Free Software Foundation; either version 2 of *
+* the License or (at your option) any later version. This is online at: *
+* http://www.fsf.org/copyleft/gpl.html *
+* Please send any updates to: fred@gruntose.com *
+\*****************************************************************************/
+
+#include <application/hoople_main.h>
+#include <basis/byte_array.h>
+#include <mathematics/chaos.h>
+#include <basis/functions.h>
+#include <basis/guards.h>
+#include <basis/astring.h>
+#include <application/application_shell.h>
+#include <loggers/console_logger.h>
+#include <loggers/program_wide_logger.h>
+#include <structures/static_memory_gremlin.h>
+#include <octopus/entity_data_bin.h>
+#include <octopus/entity_defs.h>
+#include <tentacles/security_infoton.h>
+#include <textual/string_manipulation.h>
+
+#include <stdio.h>
+
+using namespace application;
+using namespace basis;
+using namespace loggers;
+using namespace octopi;
+using namespace textual;
+
+const int ITEM_COUNT = 10000;
+ // the number of times to repeat each test operation.
+
+#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger().get(), astring(s))
+#define BASE_LOG(s) EMERGENCY_LOG(program_wide_logger().get(), astring(s))
+
+class test_bin : public application_shell
+{
+public:
+ test_bin() : application_shell() {}
+ DEFINE_CLASS_NAME("test_bin");
+ int execute();
+};
+
+//////////////
+
+int test_bin::execute()
+{
+ FUNCDEF("execute");
+ char c = '\0';
+
+ array<octopus_request_id> item_list;
+
+ entity_data_bin *bing = new entity_data_bin(10 * MEGABYTE);
+
+ enum test_types { ANY = 1, ENT, ID };
+
+ for (int q = ANY; q <= ID; q++) {
+LOG(a_sprintf("test type %d beginning...%c", q, c));
+ // using c just shuts up warnings.
+//LOG("note memory usage and hit a key:");
+//c = getchar();
+
+ program_wide_logger().get().eol(parser_bits::NO_ENDING);
+ for (int i = 1; i <= ITEM_COUNT; i++) {
+ // test the basic filling of the values in an entity.
+ octopus_request_id req_id;
+ int sequencer = randomizer().inclusive(1, MAXINT32 - 10);
+ int add_in = randomizer().inclusive(0, MAXINT32 - 10);
+ int process_id = randomizer().inclusive(0, MAXINT32 - 10);
+ req_id._entity = octopus_entity(string_manipulation::make_random_name(),
+ process_id, sequencer, add_in);
+ req_id._request_num = randomizer().inclusive(1, MAXINT32 - 10);
+ infoton *torp = new security_infoton;
+ bing->add_item(torp, req_id);
+ item_list += req_id;
+
+ if (! (i % 50) ) {
+ printf("^");
+ fflush(NIL);
+ }
+ }
+ program_wide_logger().get().eol(parser_bits::CRLF_AT_END);
+ LOG("");
+
+ int items_seen = 0;
+
+ program_wide_logger().get().eol(parser_bits::NO_ENDING);
+ if (q == ANY) {
+ while (item_list.length()) {
+ octopus_request_id id;
+ infoton *found = bing->acquire_for_any(id);
+ if (!found)
+ deadly_error(class_name(), "ANY", "item was missing");
+ WHACK(found);
+ items_seen++;
+ if (! (items_seen % 50) ) {
+ printf("v");
+ fflush(NIL);
+ }
+ bool saw_it = false;
+ for (int q = 0; q < item_list.length(); q++) {
+ if (item_list[q] == id) {
+ saw_it = true;
+ item_list.zap(q, q);
+ break;
+ }
+ }
+ if (!saw_it)
+ deadly_error(class_name(), "ANY", "didn't see id for the item");
+ }
+ } else if (q == ENT) {
+ while (item_list.length()) {
+ octopus_request_id id;
+ infoton *found = bing->acquire_for_entity(item_list[0]._entity, id);
+ if (!found)
+ deadly_error(class_name(), "ENT", "item was missing");
+ WHACK(found);
+ items_seen++;
+ if (! (items_seen % 50) ) {
+ printf("v");
+ fflush(NIL);
+ }
+ bool saw_it = false;
+ for (int q = 0; q < item_list.length(); q++) {
+ if (item_list[q] == id) {
+ saw_it = true;
+ item_list.zap(q, q);
+ break;
+ }
+ }
+ if (!saw_it)
+ deadly_error(class_name(), "ENT", "didn't see id for the item");
+ }
+ } else if (q == ID) {
+ for (int j = 0; j < item_list.length(); j++) {
+ infoton *found = bing->acquire_for_identifier(item_list[j]);
+ if (!found)
+ deadly_error(class_name(), "ENT", "item was missing");
+ WHACK(found);
+ items_seen++;
+ if (! (items_seen % 50) ) {
+ printf("v");
+ fflush(NIL);
+ }
+ item_list.zap(j, j);
+ j--; // skip back.
+ }
+ } else {
+ deadly_error(class_name(), "looping", "bad enum value");
+ }
+ program_wide_logger().get().eol(parser_bits::CRLF_AT_END);
+ LOG("");
+ item_list.reset();
+ item_list.shrink();
+
+ if (bing->entities())
+ deadly_error(class_name(), "check left", "there are still contents in table!");
+
+ bing->clean_out_deadwood();
+
+LOG(a_sprintf("test type %d ending...", q));
+//LOG("note memory usage and hit a key:");
+//c = getchar();
+ }
+
+ WHACK(bing);
+LOG("done testing, zapped bin, now should be low memory.");
+//c = getchar();
+
+ LOG("octopus_entity:: works for those functions tested.");
+ return 0;
+}
+
+HOOPLE_MAIN(test_bin, )
+
--- /dev/null
+/*****************************************************************************\
+* *
+* Name : test_entity_data_bin_threaded *
+* Author : Chris Koeritz *
+* *
+*******************************************************************************
+* Copyright (c) 2010-$now By Author. This program is free software; you can *
+* redistribute it and/or modify it under the terms of the GNU General Public *
+* License as published by the Free Software Foundation; either version 2 of *
+* the License or (at your option) any later version. This is online at: *
+* http://www.fsf.org/copyleft/gpl.html *
+* Please send any updates to: fred@gruntose.com *
+\*****************************************************************************/
+
+#include <application/hoople_main.h>
+#include <basis/byte_array.h>
+#include <mathematics/chaos.h>
+#include <basis/functions.h>
+#include <basis/guards.h>
+#include <basis/astring.h>
+#include <basis/mutex.h>
+#include <structures/amorph.h>
+#include <structures/static_memory_gremlin.h>
+#include <loggers/console_logger.h>
+#include <processes/ethread.h>
+#include <processes/safe_roller.h>
+#include <timely/time_control.h>
+#include <timely/time_stamp.h>
+#include <octopus/entity_data_bin.h>
+#include <octopus/entity_defs.h>
+#include <octopus/unhandled_request.h>
+#include <application/application_shell.h>
+#include <configuration/application_configuration.h>
+#include <textual/string_manipulation.h>
+
+#include <stdio.h>
+
+#ifdef __WIN32__
+ #include <process.h>
+#endif
+
+using namespace application;
+using namespace loggers;
+using namespace octopi;
+using namespace processes;
+using namespace timely;
+
+// global constants...
+
+// how much data is the entity data bin allowed to hold at one time.
+const int MAXIMUM_DATA_PER_ENTITY = 1 * KILOBYTE;
+//tiny limit to test having too much data.
+
+// controls the timing of the thread that adds items.
+const int MIN_ADDER_THREAD_PAUSE = 3;
+const int MAX_ADDER_THREAD_PAUSE = 20;
+
+// controls the timing of the item deleting thread.
+const int MIN_WHACKER_THREAD_PAUSE = 8;
+const int MAX_WHACKER_THREAD_PAUSE = 70;
+
+// bound the randomly chosen pause time for the cleanup thread.
+const int MIN_TIDIER_THREAD_PAUSE = 60;
+const int MAX_TIDIER_THREAD_PAUSE = 500;
+
+// monk is kept asleep most of the time or he'd be trashing
+// all our data too frequently.
+const int MIN_MONK_THREAD_PAUSE = 2 * MINUTE_ms;
+const int MAX_MONK_THREAD_PAUSE = 4 * MINUTE_ms;
+
+// the range of new items added whenever the creator thread is hit.
+const int MINIMUM_ITEMS_ADDED = 1;
+const int MAXIMUM_ITEMS_ADDED = 20;
+
+const int DEFAULT_THREADS = 90;
+ // the number of threads we create by default.
+
+const int DEFAULT_RUN_TIME = 80 * MINUTE_ms;
+//2 * MINUTE_ms;
+ // the length of time to run the program.
+
+const int DATA_DECAY_TIME = 1 * MINUTE_ms;
+ // how long we retain unclaimed data.
+
+const int MONKS_CLEANING_TIME = 10 * SECOND_ms;
+ // a very short duration for data to live.
+
+#define LOG(to_print) printf("%s\n", (char *)astring(to_print).s());
+//CLASS_EMERGENCY_LOG(program_wide_logger().get(), to_print)
+ // our macro for logging with a timestamp.
+
+// global objects...
+
+chaos _rando; // our randomizer.
+
+// replace app_shell version with local randomizer, so all the static
+// functions can employ it also.
+#define randomizer() _rando
+
+entity_data_bin binger(MAXIMUM_DATA_PER_ENTITY);
+
+octopus_request_id create_request_id()
+{
+ // test the basic filling of the values in an entity.
+ octopus_request_id req_id;
+ if (randomizer().inclusive(1, 100) < 25) {
+ // some of the time we make a totally random entity id.
+ int sequencer = randomizer().inclusive(1, MAXINT - 10);
+ int add_in = randomizer().inclusive(0, MAXINT - 10);
+ int process_id = randomizer().inclusive(0, MAXINT - 10);
+ req_id._entity = octopus_entity(string_manipulation::make_random_name(),
+ process_id, sequencer, add_in);
+ } else {
+ // sometimes we use a less random identity.
+ int sequencer = randomizer().inclusive(1, 3);
+ int add_in = 12;
+ int process_id = randomizer().inclusive(1, 4);
+ req_id._entity = octopus_entity("boringentity",
+ process_id, sequencer, add_in);
+ }
+ req_id._request_num = randomizer().inclusive(1, MAXINT - 10);
+ return req_id;
+}
+
+// this thread creates new items for the entity data bin.
+class ballot_box_stuffer : public ethread
+{
+public:
+ ballot_box_stuffer() : ethread(0) {
+ FUNCDEF("constructor");
+ LOG("+creator");
+ }
+
+ virtual ~ballot_box_stuffer() {
+ FUNCDEF("destructor");
+ LOG("~creator");
+ }
+
+ DEFINE_CLASS_NAME("ballot_box_stuffer");
+
+ void perform_activity(void *formal(data)) {
+ FUNCDEF("perform_activity");
+ while (!should_stop()) {
+ // add a new item to the cache.
+ int how_many = randomizer().inclusive(MINIMUM_ITEMS_ADDED,
+ MAXIMUM_ITEMS_ADDED);
+ for (int i = 0; i < how_many; i++) {
+ string_array random_strings;
+ int string_count = randomizer().inclusive(1, 10);
+ // we create a random classifier, just to use up some space.
+ for (int q = 0; q < string_count; q++) {
+ random_strings += string_manipulation::make_random_name();
+ }
+ unhandled_request *newbert = new unhandled_request(create_request_id(),
+ random_strings);
+ binger.add_item(newbert, create_request_id());
+ }
+ // snooze.
+ int sleepy_time = randomizer().inclusive(MIN_ADDER_THREAD_PAUSE,
+ MAX_ADDER_THREAD_PAUSE);
+ time_control::sleep_ms(sleepy_time);
+ }
+ }
+
+};
+
+// this thread eliminates entries in the ballot box.
+class vote_destroyer : public ethread
+{
+public:
+ vote_destroyer() : ethread(0) {
+ FUNCDEF("constructor");
+ LOG("+destroyer");
+ }
+
+ virtual ~vote_destroyer() {
+ FUNCDEF("destructor");
+ LOG("~destroyer");
+ }
+
+ DEFINE_CLASS_NAME("vote_destroyer");
+
+ void perform_activity(void *formal(data)) {
+ FUNCDEF("perform_activity");
+ while (!should_stop()) {
+ // snag any old item and drop it on the floor.
+ octopus_request_id id;
+ infoton *found = binger.acquire_for_any(id);
+ WHACK(found);
+ // snooze.
+ int sleepy_time = randomizer().inclusive(MIN_WHACKER_THREAD_PAUSE,
+ MAX_WHACKER_THREAD_PAUSE);
+ time_control::sleep_ms(sleepy_time);
+ }
+ }
+};
+
+// this class makes sure the deadwood is cleaned out of the entity bin.
+class obsessive_compulsive : public ethread
+{
+public:
+ obsessive_compulsive() : ethread(0) {
+ FUNCDEF("constructor");
+ LOG("+cleaner");
+ }
+
+ virtual ~obsessive_compulsive() {
+ FUNCDEF("destructor");
+ LOG("~cleaner");
+ }
+
+ DEFINE_CLASS_NAME("obsessive_compulsive");
+
+ void perform_activity(void *formal(data)) {
+ FUNCDEF("perform_activity");
+ while (!should_stop()) {
+ // make sure there's nothing rotting too long.
+ binger.clean_out_deadwood(DATA_DECAY_TIME);
+ // snooze.
+ int sleepy_time = randomizer().inclusive(MIN_TIDIER_THREAD_PAUSE,
+ MAX_TIDIER_THREAD_PAUSE);
+ time_control::sleep_ms(sleepy_time);
+ }
+ }
+};
+
+// this thread will destroy all data in the bins while cleaning furiously.
+class monk_the_detective : public ethread
+{
+public:
+ monk_the_detective() : ethread(0) {
+ FUNCDEF("constructor");
+ LOG("+monk");
+ }
+
+ virtual ~monk_the_detective() {
+ FUNCDEF("destructor");
+ LOG("~monk");
+ }
+
+ DEFINE_CLASS_NAME("monk_the_detective");
+
+ void perform_activity(void *formal(data)) {
+ FUNCDEF("perform_activity");
+ while (!should_stop()) {
+ // one activation of monk has devastating consequences. we empty out
+ // the data one item at a time until we see no data at all. after
+ // cleaning each item, we ensure that the deadwood is cleaned out.
+ binger._ent_lock->lock();
+LOG(a_sprintf("monk sees %d items.", binger.items_held()));
+ while (binger.items_held()) {
+ // grab one instance of any item in the bin.
+ octopus_request_id id;
+ infoton *found = binger.acquire_for_any(id);
+ WHACK(found);
+ // also clean out things a lot faster than normal.
+ binger.clean_out_deadwood(MONKS_CLEANING_TIME);
+ }
+ binger._ent_lock->unlock();
+LOG(a_sprintf("after a little cleaning, monk sees %d items.", binger.items_held()));
+ // snooze.
+ int sleepy_time = randomizer().inclusive(MIN_MONK_THREAD_PAUSE,
+ MAX_MONK_THREAD_PAUSE);
+ time_control::sleep_ms(sleepy_time);
+ }
+ }
+};
+
+//////////////
+
+class test_entity_data_bin_threaded : public application_shell
+{
+public:
+ test_entity_data_bin_threaded() : application_shell(class_name()) {}
+
+ DEFINE_CLASS_NAME("test_entity_data_bin_threaded");
+
+ int execute();
+};
+
+int test_entity_data_bin_threaded::execute()
+{
+ FUNCDEF("execute");
+
+ amorph<ethread> thread_list;
+
+ for (int i = 0; i < DEFAULT_THREADS; i++) {
+ ethread *t = NIL;
+ if (i == DEFAULT_THREADS - 1) {
+ // last item gets special treatment; we reserve this space for monk.
+ t = new monk_the_detective;
+ } else if (i % 3 == 0) {
+ t = new ballot_box_stuffer;
+ } else if (i % 3 == 1) {
+ t = new vote_destroyer;
+ } else { // i % 3 must = 2.
+ t = new obsessive_compulsive;
+ }
+ thread_list.append(t);
+ ethread *q = thread_list[thread_list.elements() - 1];
+ if (q != t)
+ deadly_error(class_name(), func, "amorph has incorrect pointer!");
+ // start the thread we added.
+ thread_list[thread_list.elements() - 1]->start(NIL);
+ }
+
+ time_stamp when_to_leave(DEFAULT_RUN_TIME);
+ while (when_to_leave > time_stamp()) {
+ time_control::sleep_ms(100);
+ }
+
+// LOG("now cancelling all threads....");
+
+// for (int j = 0; j < thread_list.elements(); j++) thread_list[j]->cancel();
+
+// LOG("now stopping all threads....");
+
+// for (int k = 0; k < thread_list.elements(); k++) thread_list[k]->stop();
+
+// LOG("resetting thread list....");
+
+ thread_list.reset(); // should whack all threads.
+
+ LOG("done exiting from all threads....");
+
+//report the results:
+// how many objects created.
+// how many got destroyed.
+// how many evaporated due to timeout.
+
+
+ guards::alert_message("t_bin_threaded:: works for all functions tested.");
+ return 0;
+}
+
+HOOPLE_MAIN(test_entity_data_bin_threaded, )
+
--- /dev/null
+/*****************************************************************************\
+* *
+* Name : octopus_entity tester *
+* Author : Chris Koeritz *
+* *
+* Purpose: *
+* *
+* Checks that the octopus_entity class is behaving as expected. *
+* *
+*******************************************************************************
+* Copyright (c) 2002-$now By Author. This program is free software; you can *
+* redistribute it and/or modify it under the terms of the GNU General Public *
+* License as published by the Free Software Foundation; either version 2 of *
+* the License or (at your option) any later version. This is online at: *
+* http://www.fsf.org/copyleft/gpl.html *
+* Please send any updates to: fred@gruntose.com *
+\*****************************************************************************/
+
+#include <basis/byte_array.h>
+#include <mathematics/chaos.h>
+#include <basis/guards.h>
+#include <basis/astring.h>
+#include <octopus/entity_defs.h>
+#include <application/application_shell.h>
+#include <loggers/console_logger.h>
+#include <loggers/file_logger.h>
+#include <structures/static_memory_gremlin.h>
+#include <sockets/tcpip_stack.h>
+#include <textual/string_manipulation.h>
+
+#ifdef __WIN32__
+ #include <process.h>
+#else
+ #include <unistd.h>
+#endif
+
+const int ITERATE_EACH_TEST = 1000;
+ // the number of times to repeat each test operation.
+
+class test_entity : public application_shell
+{
+public:
+ test_entity() : application_shell(class_name()) {}
+ DEFINE_CLASS_NAME("test_entity");
+ virtual int execute();
+};
+
+int test_entity::execute()
+{
+ chaos rando;
+ SET_DEFAULT_COMBO_LOGGER;
+ tcpip_stack stack;
+
+ octopus_entity blankie;
+ if (!blankie.blank())
+ deadly_error(class_name(), "emptiness test",
+ "the blank entity was not seen as empty.");
+ octopus_entity fullish("gurp", 28, 39, 4);
+ if (fullish.blank())
+ deadly_error(class_name(), "emptiness test",
+ "the non-blank entity was seen as empty.");
+
+ for (int i = 0; i < ITERATE_EACH_TEST; i++) {
+ // test the basic filling of the values in an entity.
+ octopus_entity blank_ent;
+ int sequencer = rando.inclusive(1, MAXINT - 10);
+ int add_in = rando.inclusive(0, MAXINT - 10);
+ octopus_entity filled_ent(stack.hostname(), application_configuration::process_id(), sequencer,
+ add_in);
+ blank_ent = octopus_entity(stack.hostname(), application_configuration::process_id(), sequencer,
+ add_in);
+ if (blank_ent != filled_ent)
+ deadly_error(class_name(), "simple reset test",
+ "failed to resolve to same id");
+ astring text1 = filled_ent.to_text();
+ astring text2 = blank_ent.to_text();
+ if (text1 != text2)
+ deadly_error(class_name(), "to_text test", "strings are different");
+///log(text1);
+ octopus_entity georgio = octopus_entity::from_text(text2);
+///log(georgio.to_text());
+ if (georgio != filled_ent)
+ deadly_error(class_name(), "from_text test",
+ "entity is different after from_text");
+
+ octopus_request_id fudnix(filled_ent, 8232390);
+ astring text3 = fudnix.to_text();
+ octopus_request_id resur = octopus_request_id::from_text(text3);
+ if (resur != fudnix)
+ deadly_error(class_name(), "from_text test",
+ "request id is different after from_text");
+
+ blank_ent = octopus_entity(); // reset it again forcefully.
+ blank_ent = octopus_entity(filled_ent.hostname(), filled_ent.process_id(),
+ filled_ent.sequencer(), filled_ent.add_in());
+ if (blank_ent != filled_ent)
+ deadly_error(class_name(), "reset from attribs test",
+ "failed to resolve to same id");
+// log(a_sprintf("%d: ", i + 1) + filled_ent.mangled_form());
+
+ byte_array chunk1;
+ filled_ent.pack(chunk1);
+ octopus_entity unpacked1;
+ unpacked1.unpack(chunk1);
+ if (unpacked1 != filled_ent)
+ deadly_error(class_name(), "pack/unpack test",
+ "failed to return same values");
+
+ // test of entity packing and size calculation.
+ octopus_entity ent(string_manipulation::make_random_name(1, 428),
+ randomizer().inclusive(0, MAXINT/2),
+ randomizer().inclusive(0, MAXINT/2),
+ randomizer().inclusive(0, MAXINT/2));
+ octopus_request_id bobo(ent, randomizer().inclusive(0, MAXINT/2));
+ int packed_estimate = bobo.packed_size();
+ byte_array packed_bobo;
+ bobo.pack(packed_bobo);
+ if (packed_bobo.length() != packed_estimate)
+ deadly_error(class_name(), "entity packed_size test",
+ "calculated incorrect packed size");
+ }
+
+
+ log("octopus_entity:: works for those functions tested.");
+ return 0;
+}
+
+//hmmm: tests the octopus entity object,
+// can do exact text check if want but that's not guaranteed to be useful
+// in the future.
+
+HOOPLE_MAIN(test_entity, )
+
--- /dev/null
+/*****************************************************************************\
+* *
+* Name : test_file_transfer_tentacle *
+* Author : Chris Koeritz *
+* *
+* Purpose: *
+* *
+* Tests the file_transfer_tentacle without any networking involved. *
+* *
+*******************************************************************************
+* Copyright (c) 2005-$now By Author. This program is free software; you can *
+* redistribute it and/or modify it under the terms of the GNU General Public *
+* License as published by the Free Software Foundation; either version 2 of *
+* the License or (at your option) any later version. This is online at: *
+* http://www.fsf.org/copyleft/gpl.html *
+* Please send any updates to: fred@gruntose.com *
+\*****************************************************************************/
+
+#include <basis/functions.h>
+#include <structures/string_array.h>
+#include <structures/static_memory_gremlin.h>
+#include <loggers/console_logger.h>
+#include <application/application_shell.h>
+#include <tentacles/file_transfer_tentacle.h>
+#include <tentacles/recursive_file_copy.h>
+
+#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
+
+class test_file_transfer_tentacle : public application_shell
+{
+public:
+ test_file_transfer_tentacle() : application_shell(static_class_name()) {}
+ DEFINE_CLASS_NAME("test_dirtree_fcopy");
+ int execute();
+};
+
+int test_file_transfer_tentacle::execute()
+{
+ FUNCDEF("execute");
+
+ if (__argc < 3) {
+ log("\
+This program needs two parameters:\n\
+a directory for the source root and one for the target root.\n\
+Optionally, a third parameter may specify a starting point within the\n\
+source root.\n\
+Further, if fourth or more parameters are found, they are taken to be\n\
+files to include; only they will be transferred.\n");
+ return 23;
+ }
+
+ astring source_dir = __argv[1];
+ astring target_dir = __argv[2];
+
+ astring source_start = "";
+ if (__argc >= 4) {
+ source_start = __argv[3];
+ }
+
+ string_array includes;
+ if (__argc >= 5) {
+ for (int i = 4; i < __argc; i++) {
+ includes += __argv[i];
+ }
+ }
+
+
+ outcome returned = recursive_file_copy::copy_hierarchy
+ (file_transfer_tentacle::COMPARE_SIZE_AND_TIME, source_dir,
+ target_dir, includes, source_start);
+
+/*
+ astring source_root = "snootums";
+ if (source_start.t()) {
+ source_root += filename::default_separator() + source_start;
+ }
+
+ tcpip_stack stack;
+ octopus ring_leader(stack.hostname(), 10 * MEGABYTE);
+ file_transfer_tentacle *tran = new file_transfer_tentacle(MAX_CHUNK, false);
+ ring_leader.add_tentacle(tran);
+
+ outcome add_ret = tran->add_correspondence("snootums", source_dir,
+ 10 * MINUTE_ms);
+ if (add_ret != tentacle::OKAY)
+ deadly_error(class_name(), func, "failed to add the correspondence");
+
+ file_transfer_infoton *initiate = new file_transfer_infoton;
+ initiate->_request = true;
+ initiate->_command = file_transfer_infoton::TREE_COMPARISON;
+ initiate->_src_root = source_root;
+ initiate->_dest_root = target_dir;
+ directory_tree target_area(target_dir);
+ target_area.calculate();
+ initiate->package_tree_info(target_area, includes);
+
+ octopus_entity ent = ring_leader.issue_identity();
+ octopus_request_id req_id(ent, 1);
+ outcome start_ret = ring_leader.evaluate(initiate, req_id);
+ if (start_ret != tentacle::OKAY)
+ deadly_error(class_name(), func, "failed to start the comparison");
+
+ file_transfer_infoton *reply_from_init
+ = (file_transfer_infoton *)ring_leader.acquire_specific_result(req_id);
+ if (!reply_from_init)
+ deadly_error(class_name(), func, "no response to tree compare start");
+
+ filename_list diffs;
+ byte_array pack_copy = reply_from_init->_packed_data;
+ if (!diffs.unpack(pack_copy))
+ deadly_error(class_name(), func, "could not unpack filename list!");
+// LOG(astring("got list of diffs:\n") + diffs.text_form());
+
+ octopus client_spider(stack.hostname(), 10 * MEGABYTE);
+ file_transfer_tentacle *tran2 = new file_transfer_tentacle(MAX_CHUNK, false);
+ tran2->register_file_transfer(ent, source_root, target_dir, includes);
+ client_spider.add_tentacle(tran2);
+
+ octopus_request_id resp_id(ent, 2);
+ outcome ini_resp_ret = client_spider.evaluate(reply_from_init, resp_id);
+ if (ini_resp_ret != tentacle::OKAY)
+ deadly_error(class_name(), func, "failed to process the start response!");
+
+ infoton *junk = client_spider.acquire_specific_result(resp_id);
+ if (junk)
+ deadly_error(class_name(), func, "got a response we shouldn't have!");
+
+ int iter = 0;
+ while (true) {
+LOG(a_sprintf("ongoing chunk %d", ++iter));
+
+ // keep going until we find a broken reply.
+ file_transfer_infoton *ongoing = new file_transfer_infoton;
+ ongoing->_request = true;
+ ongoing->_command = file_transfer_infoton::PLACE_FILE_CHUNKS;
+ ongoing->_src_root = source_root;
+ ongoing->_dest_root = target_dir;
+
+ octopus_request_id chunk_id(ent, iter + 10);
+ outcome place_ret = ring_leader.evaluate(ongoing, chunk_id);
+ if (place_ret != tentacle::OKAY)
+ deadly_error(class_name(), func, "failed to run ongoing transfer");
+
+ file_transfer_infoton *reply = (file_transfer_infoton *)ring_leader
+ .acquire_specific_result(chunk_id);
+ if (!reply)
+ deadly_error(class_name(), func, "failed to get ongoing transfer reply");
+
+ if (!reply->_packed_data.length()) {
+ LOG("hit termination condition: no data packed in for file chunks.");
+ break;
+ }
+
+ byte_array copy = reply->_packed_data;
+ while (copy.length()) {
+ file_transfer_header head;
+ if (!head.unpack(copy))
+ deadly_error(class_name(), func, "failed to unpack header");
+LOG(astring("header: ") + head.text_form());
+LOG(a_sprintf("size in array: %d", copy.length()));
+ if (copy.length() < head._length)
+ deadly_error(class_name(), func, "not enough length in array");
+ copy.zap(0, head._length - 1);
+LOG(a_sprintf("size in array now: %d", copy.length()));
+ }
+ if (copy.length())
+ deadly_error(class_name(), func, "still had data in array");
+
+ octopus_request_id resp_id(ent, iter + 11);
+ outcome resp_ret = client_spider.evaluate(reply, resp_id);
+ if (resp_ret != tentacle::OKAY)
+ deadly_error(class_name(), func, "failed to process the transfer reply!");
+
+ }
+*/
+
+ if (returned == common::OKAY)
+ guards::alert_message("file_transfer_tentacle:: works for those "
+ "functions tested.");
+ else
+ guards::alert_message(astring("file_transfer_tentacle:: failed with "
+ "outcome=") + recursive_file_copy::outcome_name(returned));
+ return 0;
+}
+
+HOOPLE_MAIN(test_file_transfer_tentacle, )
+
--- /dev/null
+/*****************************************************************************\
+* *
+* Name : octopus identity test *
+* Author : Chris Koeritz *
+* *
+* Purpose: *
+* *
+* Checks out the client identification methods in octopus. *
+* *
+*******************************************************************************
+* Copyright (c) 2002-$now By Author. This program is free software; you can *
+* redistribute it and/or modify it under the terms of the GNU General Public *
+* License as published by the Free Software Foundation; either version 2 of *
+* the License or (at your option) any later version. This is online at: *
+* http://www.fsf.org/copyleft/gpl.html *
+* Please send any updates to: fred@gruntose.com *
+\*****************************************************************************/
+
+#include <basis/astring.h>
+#include <octopus/entity_defs.h>
+#include <octopus/identity_infoton.h>
+#include <octopus/infoton.h>
+#include <octopus/octopus.h>
+#include <octopus/tentacle.h>
+#include <application/application_shell.h>
+#include <loggers/console_logger.h>
+#include <structures/static_memory_gremlin.h>
+
+//////////////
+
+class test_octopus_identity : public application_shell
+{
+public:
+ test_octopus_identity() : application_shell(class_name()) {}
+ DEFINE_CLASS_NAME("test_octopus_identity");
+ virtual int execute();
+};
+
+int test_octopus_identity::execute()
+{
+ octopus logos("local", 18 * MEGABYTE);
+
+ identity_infoton *ide = new identity_infoton;
+ octopus_request_id junk_id = octopus_request_id::randomized_id();
+ // bogus right now.
+
+ byte_array packed;
+ ide->pack(packed);
+ if (ide->packed_size() != packed.length())
+ deadly_error(class_name(), "packing test",
+ astring("the packed size was different than expected."));
+
+ outcome ret = logos.evaluate(ide, junk_id);
+ if (ret != tentacle::OKAY)
+ deadly_error(class_name(), "evaluate test",
+ astring("the evaluation failed with an error ")
+ + tentacle::outcome_name(ret));
+log("point a");
+
+ octopus_request_id response_id; // based on bogus from before.
+ infoton *response = logos.acquire_result(junk_id._entity, response_id);
+ if (!response)
+ deadly_error(class_name(), "acquire test",
+ astring("the acquire_result failed to produce a result."));
+
+ identity_infoton *new_id = dynamic_cast<identity_infoton *>(response);
+ if (!new_id)
+ deadly_error(class_name(), "casting",
+ astring("the returned infoton is not the right type."));
+
+ octopus_entity my_ide = new_id->_new_name;
+
+log(astring("new id is: ") + my_ide.text_form());
+
+ if (my_ide.blank())
+ deadly_error(class_name(), "retrieving id",
+ astring("the new entity id is blank."));
+
+
+ log("octopus:: identity works for those functions tested.");
+
+ return 0;
+}
+
+HOOPLE_MAIN(test_octopus_identity, )
+
--- /dev/null
+/*****************************************************************************\
+* *
+* Name : octopus security test *
+* Author : Chris Koeritz *
+* *
+* Purpose: *
+* *
+* Checks out the login support for octopus. This just exercises the base *
+* support which doesn't perform any extra verification on the user. *
+* *
+*******************************************************************************
+* Copyright (c) 2002-$now By Author. This program is free software; you can *
+* redistribute it and/or modify it under the terms of the GNU General Public *
+* License as published by the Free Software Foundation; either version 2 of *
+* the License or (at your option) any later version. This is online at: *
+* http://www.fsf.org/copyleft/gpl.html *
+* Please send any updates to: fred@gruntose.com *
+\*****************************************************************************/
+
+#include <basis/astring.h>
+#include <basis/mutex.h>
+#include <structures/static_memory_gremlin.h>
+#include <octopus/entity_defs.h>
+#include <octopus/infoton.h>
+#include <octopus/octopus.h>
+#include <octopus/tentacle.h>
+#include <application/application_shell.h>
+#include <loggers/console_logger.h>
+#include <structures/static_memory_gremlin.h>
+#include <sockets/internet_address.h>
+#include <tentacles/login_tentacle.h>
+#include <tentacles/simple_entity_registry.h>
+
+//////////////
+
+astring base_list[] = { "cli", "simp" };
+
+SAFE_STATIC_CONST(string_array, simp_classifier, (2, base_list))
+
+class simple_infoton : public infoton
+{
+public:
+ astring futzle;
+
+ simple_infoton() : infoton(simp_classifier()) {}
+
+ virtual void pack(byte_array &packed_form) const {
+ futzle.pack(packed_form);
+ }
+ virtual bool unpack(byte_array &packed_form) {
+ if (!futzle.unpack(packed_form)) return false;
+ return true;
+ }
+ virtual int packed_size() const { return futzle.length() + 1; }
+ virtual clonable *clone() const { return new simple_infoton(*this); }
+
+private:
+};
+
+//////////////
+
+// provides a simple service to allow us to test whether the security is
+// working or not.
+
+class simple_tentacle : public tentacle
+{
+public:
+ simple_tentacle() : tentacle(simp_classifier(), true) {}
+
+ virtual outcome reconstitute(const string_array &classifier,
+ byte_array &packed_form, infoton * &reformed) {
+ reformed = NIL;
+ if (classifier != simp_classifier()) return NO_HANDLER;
+ reformed = new simple_infoton;
+ if (!reformed->unpack(packed_form)) {
+ WHACK(reformed);
+ return GARBAGE;
+ }
+ return OKAY;
+ }
+
+ virtual outcome consume(infoton &to_chow,
+ const octopus_request_id &formal(item_id), byte_array &transformed) {
+ transformed.reset();
+ if (to_chow.classifier() != simp_classifier()) return NO_HANDLER;
+ // consume without doing anything.
+ return OKAY;
+ }
+
+ virtual void expunge(const octopus_entity &formal(to_zap)) {}
+};
+
+//////////////
+
+//hmmm: this test should do a sample login octopus and do a login, reside for
+// a while, log out, do another one, let it time out, try to access
+// something with dead id hoping to be rejected, etc.
+
+class test_octopus_security : public application_shell
+{
+public:
+ test_octopus_security() : application_shell(class_name()) {}
+ DEFINE_CLASS_NAME("test_octopus_security");
+ virtual int execute();
+};
+
+int test_octopus_security::execute()
+{
+ octopus logos("local", 18 * MEGABYTE);
+ simple_tentacle *tenty = new simple_tentacle;
+ logos.add_tentacle(tenty);
+ tenty = NIL; // octopus has charge of this now.
+
+ // turn on security in logos.
+ simple_entity_registry *guardian = new simple_entity_registry;
+ logos.add_tentacle(new login_tentacle(*guardian), true);
+
+ // create an entity to work with.
+ octopus_entity jimbo("localhost", application_configuration::process_id(), 128, 982938);
+ octopus_request_id req1(jimbo, 1);
+
+ // add the user jimbo.
+ guardian->add_entity(jimbo, byte_array());
+
+ // create a piece of data to try running on tentacle.
+ simple_infoton testose;
+ simple_infoton *testose_copy = new simple_infoton(testose);
+
+ // test that the simple tentacle allows the op.
+ outcome ret = logos.evaluate(testose_copy, req1);
+ if (ret != tentacle::OKAY)
+ deadly_error(class_name(), "first test",
+ astring("the operation failed with an error ")
+ + tentacle::outcome_name(ret));
+
+ // create another entity to work with.
+ octopus_entity burfo("localhost", application_configuration::process_id(), 372, 2989);
+ octopus_request_id req2(burfo, 1);
+
+ // try with an unlicensed user burfo...
+ testose_copy = new simple_infoton(testose);
+ ret = logos.evaluate(testose_copy, req2);
+ if (ret == tentacle::OKAY)
+ deadly_error(class_name(), "second test",
+ astring("the operation didn't fail when it should have."));
+ else if (ret != tentacle::DISALLOWED)
+ deadly_error(class_name(), "second test",
+ astring("the operation didn't provide the proper outcome, it gave: ")
+ + tentacle::outcome_name(ret));
+
+ // remove the user jimbo.
+ guardian->zap_entity(jimbo);
+
+ // test that jimbo fails too now.
+ testose_copy = new simple_infoton(testose);
+ ret = logos.evaluate(testose_copy, req1);
+ if (ret == tentacle::OKAY)
+ deadly_error(class_name(), "third test",
+ astring("the operation didn't fail when it should have."));
+ else if (ret != tentacle::DISALLOWED)
+ deadly_error(class_name(), "third test",
+ astring("the operation didn't provide the proper outcome, it gave: ")
+ + tentacle::outcome_name(ret));
+
+ // add the user burfo in now instead.
+ guardian->add_entity(burfo, byte_array());
+
+ // test that burfo works.
+ testose_copy = new simple_infoton(testose);
+ ret = logos.evaluate(testose_copy, req2);
+ if (ret != tentacle::OKAY)
+ deadly_error(class_name(), "fourth test",
+ astring("the operation failed with an error ")
+ + tentacle::outcome_name(ret));
+
+ log("octopus:: security works for those functions tested.");
+
+ WHACK(guardian);
+
+ return 0;
+}
+
+HOOPLE_MAIN(test_octopus_security, )
+
--- /dev/null
+/*****************************************************************************\
+* *
+* Name : unpacking octopus test *
+* Author : Chris Koeritz *
+* *
+* Purpose: *
+* *
+* A test of octopuses used for unpacking flat structures. *
+* *
+*******************************************************************************
+* Copyright (c) 2002-$now By Author. This program is free software; you can *
+* redistribute it and/or modify it under the terms of the GNU General Public *
+* License as published by the Free Software Foundation; either version 2 of *
+* the License or (at your option) any later version. This is online at: *
+* http://www.fsf.org/copyleft/gpl.html *
+* Please send any updates to: fred@gruntose.com *
+\*****************************************************************************/
+
+#include <basis/astring.h>
+#include <structures/static_memory_gremlin.h>
+#include <octopus/entity_defs.h>
+#include <octopus/infoton.h>
+#include <octopus/octopus.h>
+#include <octopus/tentacle_helper.h>
+#include <application/application_shell.h>
+#include <loggers/console_logger.h>
+#include <loggers/file_logger.h>
+#include <structures/static_memory_gremlin.h>
+#include <sockets/internet_address.h>
+
+//hmmm: provide equality ops to be able to check that same stuff
+// came back out that went in.
+
+class test_unpacker : public application_shell
+{
+public:
+ test_unpacker() : application_shell(class_name()) {}
+ DEFINE_CLASS_NAME("test_unpacker");
+ virtual int execute();
+ void test_unpacking();
+};
+
+//////////////
+
+// the infotons here have a three level classifier. the outer level is
+// for the benefit of the handler_arm tentacle that just checks that the
+// group name is correct before passing off the request to its internal
+// octopus. then the second level specifies which class of infotons are
+// being managed. the third level specifies the leaf type of the infoton--
+// the specific type of data being wrapped.
+
+const char *base_list[] = { "gruntiak" };
+
+SAFE_STATIC_CONST(string_array, base_classifier, (1, base_list))
+
+const char *math_list[] = { "math" };
+
+SAFE_STATIC_CONST(string_array, math_classifier, (base_classifier()
+ + string_array(1, math_list)))
+
+const char *addr_list[] = { "address" };
+
+SAFE_STATIC_CONST(string_array, addr_classifier, (base_classifier()
+ + string_array(1, addr_list)))
+
+class address_ton : public infoton, public network_address
+{
+public:
+ address_ton() : infoton(addr_classifier() + "leaf") {}
+
+ virtual void pack(byte_array &packed_form) const {
+ network_address::pack(packed_form);
+ }
+
+ virtual bool unpack(byte_array &packed_form) {
+ return network_address::unpack(packed_form);
+ }
+
+ virtual int packed_size() const {
+ return 5 * sizeof(int) + 128 /*address estimate*/;
+ }
+
+ virtual clonable *clone() const {
+ return new address_ton(*this);
+ }
+};
+
+//some floating point nums.
+class float_ton : public infoton
+{
+public:
+ float f1;
+ double d1;
+
+ float_ton() : infoton(math_classifier() + "float") {}
+
+ virtual void pack(byte_array &packed_form) const {
+ structures::attach(packed_form, f1);
+ structures::attach(packed_form, d1);
+ }
+
+ virtual int packed_size() const {
+ return sizeof(double) + sizeof(float);
+ }
+
+ virtual bool unpack(byte_array &packed_form) {
+ double hold;
+ if (!structures::detach(packed_form, hold)) return false;
+ f1 = float(hold);
+ if (!structures::detach(packed_form, d1)) return false;
+ return true;
+ }
+
+ virtual clonable *clone() const {
+ return new float_ton(*this);
+ }
+};
+
+//an integer set.
+class int_set_ton : public infoton
+{
+public:
+ int_set nums;
+
+ int_set_ton() : infoton(math_classifier() + "intset") {}
+
+ virtual void pack(byte_array &packed_form) const {
+ structures::attach(packed_form, nums.elements());
+ for (int i = 0; i < nums.elements(); i++)
+ structures::attach(packed_form, nums[i]);
+ }
+
+ virtual int packed_size() const {
+ return sizeof(int) + nums.elements() * sizeof(int);
+ }
+
+ virtual bool unpack(byte_array &packed_form) {
+ int len = 0;
+ nums.reset();
+ if (!structures::detach(packed_form, len)) return false;
+ for (int i = 0; i < len; i++) {
+ int got = 0;
+ if (!structures::detach(packed_form, got)) return false;
+ nums += got;
+ }
+ return true;
+ }
+
+ virtual clonable *clone() const {
+ return new int_set_ton(*this);
+ }
+};
+
+//////////////
+
+// handles network addresses.
+class address_chomper : public tentacle_helper<address_ton>
+{
+public:
+ address_chomper()
+ : tentacle_helper<address_ton>(addr_classifier().subarray(1, 1), true) {}
+};
+
+// handles floats and int_sets.
+class numerical_chomper : public tentacle
+{
+public:
+ numerical_chomper() : tentacle(math_classifier().subarray(1, 1), true) {}
+
+ outcome reconstitute(const string_array &classifier, byte_array &packed_form,
+ infoton * &reformed)
+ {
+ reformed = NIL;
+ if (classifier.length() < 2) return BAD_INPUT;
+ astring key = classifier[1];
+ if (key == "float") {
+ float_ton *to_return = new float_ton;
+ if (!to_return->unpack(packed_form)) {
+ WHACK(to_return);
+ return NIL;
+ }
+ reformed = to_return;
+ return OKAY;
+ } else if (key == "intset") {
+ int_set_ton *to_return = new int_set_ton;
+ if (!to_return->unpack(packed_form)) {
+ WHACK(to_return);
+ return NIL;
+ }
+ reformed = to_return;
+ return OKAY;
+ } else
+ return NO_HANDLER;
+ }
+
+ outcome consume(infoton &formal(to_chow), const octopus_request_id &formal(item_id),
+ byte_array &transformed)
+ { transformed.reset(); return tentacle::BAD_INPUT; }
+
+ virtual void expunge(const octopus_entity &formal(zapola)) {}
+};
+
+//////////////
+
+// delegates the unpacking to an internal tentacle. it peels off a level
+// of classifier to find the real handler.
+class outer_arm : public tentacle
+{
+public:
+ outer_arm()
+ : tentacle(base_classifier(), true),
+ _unpackers("local", 10 * MEGABYTE),
+ _numer(new numerical_chomper),
+ _addron(new address_chomper)
+ {
+ // register the two tentacles.
+ outcome ret = _unpackers.add_tentacle(_numer);
+ if (ret != tentacle::OKAY)
+ deadly_error(class_name(), "adding numerical tentacle",
+ astring("failed to add: ") + tentacle::outcome_name(ret));
+ ret = _unpackers.add_tentacle(_addron);
+ if (ret != tentacle::OKAY)
+ deadly_error(class_name(), "adding address tentacle",
+ astring("failed to add: ") + tentacle::outcome_name(ret));
+ }
+
+ ~outer_arm() {
+ // just reset the two tentacles, since the _unpackers octopus should
+ // clean them up.
+ _numer = NIL;
+ _addron = NIL;
+ }
+
+ outcome reconstitute(const string_array &classifier, byte_array &packed_form,
+ infoton * &reformed)
+ {
+ // strip first word of classifier.
+ string_array real_class = classifier;
+ real_class.zap(0, 0);
+ // route to octopus.
+ return _unpackers.restore(real_class, packed_form, reformed);
+ }
+
+ outcome consume(infoton &to_chow, const octopus_request_id &item_id,
+ byte_array &transformed)
+ {
+ transformed.reset();
+ // strip first word of classifier.
+ string_array real_class = to_chow.classifier();
+ real_class.zap(0, 0);
+ to_chow.set_classifier(real_class);
+ // route to octopus.
+ return _unpackers.evaluate((infoton *)to_chow.clone(), item_id);
+ }
+
+ void expunge(const octopus_entity &formal(whackola)) {}
+
+private:
+ octopus _unpackers;
+ numerical_chomper *_numer;
+ address_chomper *_addron;
+};
+
+//////////////
+
+void test_unpacker::test_unpacking()
+{
+ octopus unpacky("local", 10 * MEGABYTE);
+ outer_arm *outer = new outer_arm;
+ outcome ret = unpacky.add_tentacle(outer);
+ if (ret != tentacle::OKAY)
+ deadly_error(class_name(), "adding outer tentacle",
+ astring("failed to add: ") + tentacle::outcome_name(ret));
+
+ // test infoton fast packing.
+ int_set_ton jubjub;
+ jubjub.nums.add(299);
+ jubjub.nums.add(39274);
+ jubjub.nums.add(25182);
+ byte_array packed(10388); // have data in there to start.
+ infoton::fast_pack(packed, jubjub);
+ if (jubjub.packed_size() + infoton::fast_pack_overhead(jubjub.classifier())
+ != packed.length() - 10388)
+ deadly_error(class_name(), "packing test",
+ astring("erroneous size calculated for first fast_pack"));
+ string_array shirley_class;
+ byte_array shirley_data;
+ packed.zap(0, 10387); // remove the original data.
+
+ // testing the overhead calculation.
+ byte_array junk_jub;
+ jubjub.pack(junk_jub);
+ if (packed.length() != junk_jub.length()
+ + infoton::fast_pack_overhead(jubjub.classifier()))
+ deadly_error(class_name(), "test fast pack overhead",
+ "sizes differed from calculated");
+
+ if (!infoton::fast_unpack(packed, shirley_class, shirley_data))
+ deadly_error(class_name(), "test infoton fast pack",
+ "failed shirley unpack");
+ if (packed.length() != 0)
+ deadly_error(class_name(), "test infoton fast pack",
+ "shirley didn't consume all");
+ if (shirley_class != jubjub.classifier())
+ deadly_error(class_name(), "test infoton fast pack",
+ "inequal orig classifier");
+ int_set_ton scroop;
+ if (!scroop.unpack(shirley_data))
+ deadly_error(class_name(), "test infoton fast pack",
+ "failed scroop unpack");
+ if (shirley_data.length())
+ deadly_error(class_name(), "test infoton fast pack",
+ "scroop didn't consume all");
+ if (scroop.nums.length() != 3)
+ deadly_error(class_name(), "test infoton fast pack",
+ "wrong length in scroop");
+ if ( (scroop.nums[0] != jubjub.nums[0]) || (scroop.nums[1] != jubjub.nums[1])
+ || (scroop.nums[2] != jubjub.nums[2]) )
+ deadly_error(class_name(), "test infoton fast pack",
+ "erroneous information");
+
+ byte_array fasting;
+ infoton::fast_pack(fasting, jubjub);
+ if (jubjub.packed_size() + infoton::fast_pack_overhead(jubjub.classifier())
+ != fasting.length())
+ deadly_error(class_name(), "packing test",
+ astring("erroneous size calculated for second fast_pack"));
+
+ // another test of the overhead calculator.
+ byte_array junk_fast;
+ jubjub.pack(junk_fast);
+ if (fasting.length() != junk_fast.length()
+ + infoton::fast_pack_overhead(jubjub.classifier()))
+ deadly_error(class_name(), "test fast pack overhead 2",
+ "sizes differed from calculated");
+
+ string_array nudge_class;
+ byte_array nudge_data;
+ if (!infoton::fast_unpack(fasting, nudge_class, nudge_data))
+ deadly_error(class_name(), "test infoton fast pack", "fast pack failed to unpack");
+ if (fasting.length())
+ deadly_error(class_name(), "test infoton fast pack", "fast pack didn't consume all");
+ int_set_ton croup;
+ if (!croup.unpack(nudge_data))
+ deadly_error(class_name(), "test infoton fast pack", "croup wouldn't unpack");
+ if ( (croup.nums[0] != jubjub.nums[0]) || (croup.nums[1] != jubjub.nums[1])
+ || (croup.nums[2] != jubjub.nums[2]) )
+ deadly_error(class_name(), "test infoton fast pack", "croup has errors");
+ byte_array chunkmo;
+ chunkmo += 0x23;
+ chunkmo += 0xf8;
+ chunkmo += 0x37;
+ chunkmo += 0x65;
+ address_ton norf;
+ (network_address &)norf = network_address(internet_address
+ (chunkmo, "urp", 23841));
+ chunkmo.reset();
+ infoton::fast_pack(chunkmo, norf);
+ string_array clarfiator;
+ byte_array pacula;
+ if (!infoton::fast_unpack(chunkmo, clarfiator, pacula))
+ deadly_error(class_name(), "test fast_unpack", "chunkmo has errors");
+ infoton *scrung = NIL;
+//log(astring("classif is ") + clarfiator.text_form());
+
+ outcome scrung_ret = unpacky.restore(clarfiator, pacula, scrung);
+ if (scrung_ret != tentacle::OKAY)
+ deadly_error(class_name(), "test fast_unpack",
+ a_sprintf("can't restore scrung: %s",
+ tentacle::outcome_name(scrung_ret)));
+ address_ton *rescrung = dynamic_cast<address_ton *>(scrung);
+ if (!rescrung)
+ deadly_error(class_name(), "test fast_unpack", "wrong dynamic type for scrung");
+ address_ton &prescrung = *rescrung;
+ if ((network_address &)prescrung != (network_address &)norf)
+ deadly_error(class_name(), "test fast_unpack", "wrong network address restored");
+ WHACK(scrung);
+}
+
+const int MAXIMUM_TESTS = 10;
+ // was added to check for memory leaks.
+
+int test_unpacker::execute()
+{
+ int iters = 0;
+ while (iters++ < MAXIMUM_TESTS) {
+//log(a_sprintf("iter #%d", iters));
+ test_unpacking();
+ }
+ log("unpacking octopus:: works for all functions tested.");
+//time_control::sleep_ms(30000);
+ return 0;
+}
+
+HOOPLE_MAIN(test_unpacker, )
+