00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <basis/istring.h>
00020 #include <data_struct/static_memory_gremlin.h>
00021 #include <octopus/entity_defs.h>
00022 #include <octopus/infoton.h>
00023 #include <octopus/octopus.h>
00024 #include <octopus/tentacle_helper.h>
00025 #include <opsystem/application_shell.h>
00026 #include <loggers/console_logger.h>
00027 #include <loggers/file_logger.h>
00028 #include <data_struct/static_memory_gremlin.h>
00029 #include <sockets/address.h>
00030
00031
00032
00033
00034 class test_unpacker : public application_shell
00035 {
00036 public:
00037 test_unpacker() : application_shell(class_name()) {}
00038 IMPLEMENT_CLASS_NAME("test_unpacker");
00039 virtual int execute();
00040 void test_unpacking();
00041 };
00042
00044
00045
00046
00047
00048
00049
00050
00051
00052 const char *base_list[] = { "gruntiak" };
00053
00054 SAFE_STATIC_CONST(string_array, base_classifier, (1, base_list))
00055
00056 const char *math_list[] = { "math" };
00057
00058 SAFE_STATIC_CONST(string_array, math_classifier, (base_classifier()
00059 + string_array(1, math_list)))
00060
00061 const char *addr_list[] = { "address" };
00062
00063 SAFE_STATIC_CONST(string_array, addr_classifier, (base_classifier()
00064 + string_array(1, addr_list)))
00065
00066 class address_ton : public infoton, public network_address
00067 {
00068 public:
00069 address_ton() : infoton(addr_classifier() + "leaf") {}
00070
00071 virtual void pack(byte_array &packed_form) const {
00072 network_address::pack(packed_form);
00073 }
00074
00075 virtual bool unpack(byte_array &packed_form) {
00076 return network_address::unpack(packed_form);
00077 }
00078
00079 virtual int packed_size() const {
00080 return 5 * sizeof(int) + 128 ;
00081 }
00082
00083 virtual clonable *clone() const {
00084 return new address_ton(*this);
00085 }
00086 };
00087
00088
00089 class float_ton : public infoton
00090 {
00091 public:
00092 float f1;
00093 double d1;
00094
00095 float_ton() : infoton(math_classifier() + "float") {}
00096
00097 virtual void pack(byte_array &packed_form) const {
00098 basis::attach(packed_form, f1);
00099 basis::attach(packed_form, d1);
00100 }
00101
00102 virtual int packed_size() const {
00103 return sizeof(double) + sizeof(float);
00104 }
00105
00106 virtual bool unpack(byte_array &packed_form) {
00107 double hold;
00108 if (!basis::detach(packed_form, hold)) return false;
00109 f1 = float(hold);
00110 if (!basis::detach(packed_form, d1)) return false;
00111 return true;
00112 }
00113
00114 virtual clonable *clone() const {
00115 return new float_ton(*this);
00116 }
00117 };
00118
00119
00120 class int_set_ton : public infoton
00121 {
00122 public:
00123 int_set nums;
00124
00125 int_set_ton() : infoton(math_classifier() + "intset") {}
00126
00127 virtual void pack(byte_array &packed_form) const {
00128 basis::attach(packed_form, nums.elements());
00129 for (int i = 0; i < nums.elements(); i++)
00130 basis::attach(packed_form, nums[i]);
00131 }
00132
00133 virtual int packed_size() const {
00134 return sizeof(int) + nums.elements() * sizeof(int);
00135 }
00136
00137 virtual bool unpack(byte_array &packed_form) {
00138 int len = 0;
00139 nums.reset();
00140 if (!basis::detach(packed_form, len)) return false;
00141 for (int i = 0; i < len; i++) {
00142 int got = 0;
00143 if (!basis::detach(packed_form, got)) return false;
00144 nums += got;
00145 }
00146 return true;
00147 }
00148
00149 virtual clonable *clone() const {
00150 return new int_set_ton(*this);
00151 }
00152 };
00153
00155
00156
00157 class address_chomper : public tentacle_helper<address_ton>
00158 {
00159 public:
00160 address_chomper()
00161 : tentacle_helper<address_ton>(addr_classifier().subarray(1, 1), true) {}
00162 };
00163
00164
00165 class numerical_chomper : public tentacle
00166 {
00167 public:
00168 numerical_chomper() : tentacle(math_classifier().subarray(1, 1), true) {}
00169
00170 outcome reconstitute(const string_array &classifier, byte_array &packed_form,
00171 infoton * &reformed)
00172 {
00173 reformed = NIL;
00174 if (classifier.length() < 2) return BAD_INPUT;
00175 istring key = classifier[1];
00176 if (key == "float") {
00177 float_ton *to_return = new float_ton;
00178 if (!to_return->unpack(packed_form)) {
00179 WHACK(to_return);
00180 return NIL;
00181 }
00182 reformed = to_return;
00183 return OKAY;
00184 } else if (key == "intset") {
00185 int_set_ton *to_return = new int_set_ton;
00186 if (!to_return->unpack(packed_form)) {
00187 WHACK(to_return);
00188 return NIL;
00189 }
00190 reformed = to_return;
00191 return OKAY;
00192 } else
00193 return NO_HANDLER;
00194 }
00195
00196 outcome consume(infoton &formal(to_chow), const octopus_request_id &formal(item_id),
00197 byte_array &transformed)
00198 { transformed.reset(); return tentacle::BAD_INPUT; }
00199
00200 virtual void expunge(const octopus_entity &formal(zapola)) {}
00201 };
00202
00204
00205
00206
00207 class outer_arm : public tentacle
00208 {
00209 public:
00210 outer_arm()
00211 : tentacle(base_classifier(), true),
00212 _unpackers("local", 10 * MEGABYTE),
00213 _numer(new numerical_chomper),
00214 _addron(new address_chomper)
00215 {
00216
00217 outcome ret = _unpackers.add_tentacle(_numer);
00218 if (ret != tentacle::OKAY)
00219 deadly_error(class_name(), "adding numerical tentacle",
00220 istring("failed to add: ") + tentacle::outcome_name(ret));
00221 ret = _unpackers.add_tentacle(_addron);
00222 if (ret != tentacle::OKAY)
00223 deadly_error(class_name(), "adding address tentacle",
00224 istring("failed to add: ") + tentacle::outcome_name(ret));
00225 }
00226
00227 ~outer_arm() {
00228
00229
00230 _numer = NIL;
00231 _addron = NIL;
00232 }
00233
00234 outcome reconstitute(const string_array &classifier, byte_array &packed_form,
00235 infoton * &reformed)
00236 {
00237
00238 string_array real_class = classifier;
00239 real_class.zap(0, 0);
00240
00241 return _unpackers.restore(real_class, packed_form, reformed);
00242 }
00243
00244 outcome consume(infoton &to_chow, const octopus_request_id &item_id,
00245 byte_array &transformed)
00246 {
00247 transformed.reset();
00248
00249 string_array real_class = to_chow.classifier();
00250 real_class.zap(0, 0);
00251 to_chow.set_classifier(real_class);
00252
00253 return _unpackers.evaluate((infoton *)to_chow.clone(), item_id);
00254 }
00255
00256 void expunge(const octopus_entity &formal(whackola)) {}
00257
00258 private:
00259 octopus _unpackers;
00260 numerical_chomper *_numer;
00261 address_chomper *_addron;
00262 };
00263
00265
00266 void test_unpacker::test_unpacking()
00267 {
00268 octopus unpacky("local", 10 * MEGABYTE);
00269 outer_arm *outer = new outer_arm;
00270 outcome ret = unpacky.add_tentacle(outer);
00271 if (ret != tentacle::OKAY)
00272 deadly_error(class_name(), "adding outer tentacle",
00273 istring("failed to add: ") + tentacle::outcome_name(ret));
00274
00275
00276 int_set_ton jubjub;
00277 jubjub.nums.add(299);
00278 jubjub.nums.add(39274);
00279 jubjub.nums.add(25182);
00280 byte_array packed(10388);
00281 infoton::fast_pack(packed, jubjub);
00282 if (jubjub.packed_size() + infoton::fast_pack_overhead(jubjub.classifier())
00283 != packed.length() - 10388)
00284 deadly_error(class_name(), "packing test",
00285 istring("erroneous size calculated for first fast_pack"));
00286 string_array shirley_class;
00287 byte_array shirley_data;
00288 packed.zap(0, 10387);
00289
00290
00291 byte_array junk_jub;
00292 jubjub.pack(junk_jub);
00293 if (packed.length() != junk_jub.length()
00294 + infoton::fast_pack_overhead(jubjub.classifier()))
00295 deadly_error(class_name(), "test fast pack overhead",
00296 "sizes differed from calculated");
00297
00298 if (!infoton::fast_unpack(packed, shirley_class, shirley_data))
00299 deadly_error(class_name(), "test infoton fast pack",
00300 "failed shirley unpack");
00301 if (packed.length() != 0)
00302 deadly_error(class_name(), "test infoton fast pack",
00303 "shirley didn't consume all");
00304 if (shirley_class != jubjub.classifier())
00305 deadly_error(class_name(), "test infoton fast pack",
00306 "inequal orig classifier");
00307 int_set_ton scroop;
00308 if (!scroop.unpack(shirley_data))
00309 deadly_error(class_name(), "test infoton fast pack",
00310 "failed scroop unpack");
00311 if (shirley_data.length())
00312 deadly_error(class_name(), "test infoton fast pack",
00313 "scroop didn't consume all");
00314 if (scroop.nums.length() != 3)
00315 deadly_error(class_name(), "test infoton fast pack",
00316 "wrong length in scroop");
00317 if ( (scroop.nums[0] != jubjub.nums[0]) || (scroop.nums[1] != jubjub.nums[1])
00318 || (scroop.nums[2] != jubjub.nums[2]) )
00319 deadly_error(class_name(), "test infoton fast pack",
00320 "erroneous information");
00321
00322 byte_array fasting;
00323 infoton::fast_pack(fasting, jubjub);
00324 if (jubjub.packed_size() + infoton::fast_pack_overhead(jubjub.classifier())
00325 != fasting.length())
00326 deadly_error(class_name(), "packing test",
00327 istring("erroneous size calculated for second fast_pack"));
00328
00329
00330 byte_array junk_fast;
00331 jubjub.pack(junk_fast);
00332 if (fasting.length() != junk_fast.length()
00333 + infoton::fast_pack_overhead(jubjub.classifier()))
00334 deadly_error(class_name(), "test fast pack overhead 2",
00335 "sizes differed from calculated");
00336
00337 string_array nudge_class;
00338 byte_array nudge_data;
00339 if (!infoton::fast_unpack(fasting, nudge_class, nudge_data))
00340 deadly_error(class_name(), "test infoton fast pack", "fast pack failed to unpack");
00341 if (fasting.length())
00342 deadly_error(class_name(), "test infoton fast pack", "fast pack didn't consume all");
00343 int_set_ton croup;
00344 if (!croup.unpack(nudge_data))
00345 deadly_error(class_name(), "test infoton fast pack", "croup wouldn't unpack");
00346 if ( (croup.nums[0] != jubjub.nums[0]) || (croup.nums[1] != jubjub.nums[1])
00347 || (croup.nums[2] != jubjub.nums[2]) )
00348 deadly_error(class_name(), "test infoton fast pack", "croup has errors");
00349 byte_array chunkmo;
00350 chunkmo += 0x23;
00351 chunkmo += 0xf8;
00352 chunkmo += 0x37;
00353 chunkmo += 0x65;
00354 address_ton norf;
00355 (network_address &)norf = network_address(internet_address
00356 (chunkmo, "urp", 23841));
00357 chunkmo.reset();
00358 infoton::fast_pack(chunkmo, norf);
00359 string_array clarfiator;
00360 byte_array pacula;
00361 if (!infoton::fast_unpack(chunkmo, clarfiator, pacula))
00362 deadly_error(class_name(), "test fast_unpack", "chunkmo has errors");
00363 infoton *scrung = NIL;
00364
00365
00366 outcome scrung_ret = unpacky.restore(clarfiator, pacula, scrung);
00367 if (scrung_ret != tentacle::OKAY)
00368 deadly_error(class_name(), "test fast_unpack",
00369 isprintf("can't restore scrung: %s",
00370 tentacle::outcome_name(scrung_ret)));
00371 address_ton *rescrung = dynamic_cast<address_ton *>(scrung);
00372 if (!rescrung)
00373 deadly_error(class_name(), "test fast_unpack", "wrong dynamic type for scrung");
00374 address_ton &prescrung = *rescrung;
00375 if ((network_address &)prescrung != (network_address &)norf)
00376 deadly_error(class_name(), "test fast_unpack", "wrong network address restored");
00377 WHACK(scrung);
00378 }
00379
00380 const int MAXIMUM_TESTS = 10;
00381
00382
00383 int test_unpacker::execute()
00384 {
00385 int iters = 0;
00386 while (iters++ < MAXIMUM_TESTS) {
00387
00388 test_unpacking();
00389 }
00390 log("unpacking octopus:: works for all functions tested.");
00391
00392 return 0;
00393 }
00394
00395 HOOPLE_MAIN(test_unpacker, )
00396