diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..fe8227c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://editorconfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..abd53ef --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,3 @@ +# git config blame.ignoreRevsFile .git-blame-ignore-revs +# ignore codestyle commits +1a6aebd9d208d77f161b50a74fd0c673c1746e70 \ No newline at end of file diff --git a/Makefile b/Makefile index 9508db3..4e9960c 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,7 @@ clean: blob-stamper-clean $(MAKE) -C t clean $(MAKE) -C examples clean $(MAKE) -C libtappp clean + $(MAKE) -C console_demo clean @echo Clean done! test: diff --git a/README.md b/README.md index eb92668..e010713 100644 --- a/README.md +++ b/README.md @@ -411,6 +411,17 @@ result = (complex_short *) malloc(sizeof(complex_short) * result_size); memcpy((void*) result, (void*) &vec[0], sizeof(complex_short) * result_size); ``` +## Trophies + +### PostgreSQL + +* [BUG #18214](https://www.postgresql.org/message-id/flat/18214-891f77caa80a35cc%40postgresql.org): +`poly_contain` (`@>`) hangs forever for input data with zeros and infinities in +PosrgreSQL 14-16 +* [BUG #17962](https://www.postgresql.org/message-id/17962-4f00b6f26724858d%40postgresql.org): PostgreSQL 11 hangs on `poly_contain` (`@>`) with specific data + + + ## Further reading 1. Read examples. They are in `examples` directory. diff --git a/blobstamper/dict.cpp b/blobstamper/dict.cpp index 85481e1..5ecf856 100644 --- a/blobstamper/dict.cpp +++ b/blobstamper/dict.cpp @@ -16,7 +16,7 @@ * ******************************************************************************/ -#include"dict.h" +#include "dict.h" size_t diff --git a/blobstamper/dict.h b/blobstamper/dict.h index 688e754..0098a41 100644 --- a/blobstamper/dict.h +++ b/blobstamper/dict.h @@ -20,8 +20,8 @@ #define DICT_H -#include -#include +#include +#include class DictBase @@ -31,10 +31,10 @@ class DictBase public: size_t size(); std::string get(size_t n); // FIXME May be it would be good to use operator[] later. - DictBase() {data = {};}; + DictBase() { data = {}; }; }; -class DictLCAlphaSmall : public DictBase +class DictLCAlphaSmall: public DictBase { public: DictLCAlphaSmall(); diff --git a/blobstamper/galley.cpp b/blobstamper/galley.cpp index 7c86b20..7dba7a5 100644 --- a/blobstamper/galley.cpp +++ b/blobstamper/galley.cpp @@ -161,7 +161,6 @@ GalleyVectorBase::extract_internal(std::shared_ptr blob) /* Stamp is variated size */ int fixed_size = stamp->minSize(); int var_size = stamp->maxSize() - fixed_size; -fprintf(stderr, "fixed = %i, var_size = %i\n", fixed_size, var_size); ORACLE_STAMP stamp_oracle; while(1) @@ -175,7 +174,6 @@ fprintf(stderr, "fixed = %i, var_size = %i\n", fixed_size, var_size); if (size > blob->Size()) size = blob->Size(); // Getting what have been left, if not as much as we wanted -fprintf(stderr,"---- %i %i\n", size, blob->Size()); std::shared_ptr blob2 = blob->Chop(size); res.push_back(blob2); } @@ -346,7 +344,7 @@ GalleySetBase::extract_internal(std::shared_ptr blob) unbounded_remainder = len - el_size; el_size +=s->minSize(); } - std::shared_ptr blob2 = blob->Chop(el_size); + std::shared_ptr blob2 = blob->Chop(el_size); res.push_back(blob2); } return res; @@ -358,7 +356,7 @@ GalleySetBase::LoadAll(std::shared_ptr blob) std::vector> blobs = extract_internal(blob); for(int i=0; i blob = blobs[i]; + std::shared_ptr blob = blobs[i]; std::shared_ptr s = stamps[i]; s->Load(blob); } @@ -372,7 +370,7 @@ GalleySetStr::ExtractStrSet(std::shared_ptr blob) std::vector> blobs = extract_internal(blob); for(int i=0; i blob = blobs[i]; + std::shared_ptr blob = blobs[i]; auto stamp = std::dynamic_pointer_cast(stamps[i]); std::string str = stamp->ExtractStr(blob); res.push_back(str); @@ -387,7 +385,7 @@ GalleySetBin::ExtractBinSet(std::shared_ptr blob) std::vector> blobs = extract_internal(blob); for(int i=0; i blob = blobs[i]; + std::shared_ptr blob = blobs[i]; auto stamp = std::dynamic_pointer_cast(stamps[i]); std::vector v = stamp->ExtractBin(blob); res.push_back(v); @@ -429,7 +427,7 @@ GalleySetBase::minSize() if (unbounded_count > 1) /* One unbounded stamp will take all data. Nothing to predict */ res += ORACLE_SIZE * unbounded_count; - return res; + return res; } int diff --git a/blobstamper/galley.h b/blobstamper/galley.h index a5b5080..563fd2c 100644 --- a/blobstamper/galley.h +++ b/blobstamper/galley.h @@ -81,7 +81,7 @@ GalleyVectorV::ExtractValuesVector(std::shared_ptr blob) std::vector> blobs = extract_internal(blob); std::vector res(blobs.size()); - for(int i=0; i>(stamp)->ExtractValue(blobs[i]); } diff --git a/blobstamper/oracle.cpp b/blobstamper/oracle.cpp index 149186f..f640647 100644 --- a/blobstamper/oracle.cpp +++ b/blobstamper/oracle.cpp @@ -31,7 +31,7 @@ OracleProportion(ORACLE_TYPE oracle, size_t min, size_t max) * хвоста диапазона предсказания не попасть никогда и тогда он не округлиться * в max + 1*/ size_t delta = max - min + 1; - size_t res = floor(((float) oracle) / ((float) ORACLE_MAX + 1) * delta ); + size_t res = floor(((float) oracle) / ((float) ORACLE_MAX + 1) * delta); return min + res; } diff --git a/blobstamper/stamp.cpp b/blobstamper/stamp.cpp index 7fd3221..1b1adc6 100644 --- a/blobstamper/stamp.cpp +++ b/blobstamper/stamp.cpp @@ -43,7 +43,7 @@ StampBase::Load(std::shared_ptr blob) { res_size = maxSize(); if (res_size > blob->Size()) - res_size = blob->Size(); + res_size = blob->Size(); } bitten_blob = blob->Chop(res_size); } diff --git a/blobstamper/stamp.h b/blobstamper/stamp.h index 63465fa..97d7316 100644 --- a/blobstamper/stamp.h +++ b/blobstamper/stamp.h @@ -40,9 +40,9 @@ class StampBase void Load(std::shared_ptr blob); - bool isFixedSize() {return minSize() == maxSize();} - bool isVariated() {return ! isFixedSize() && ! isUnbounded();} - bool isUnbounded() {return maxSize() == -1;} + bool isFixedSize() { return minSize() == maxSize(); } + bool isVariated() { return !isFixedSize() && !isUnbounded(); } + bool isUnbounded() { return maxSize() == -1; } virtual bool isRecursive() {return is_recursive;} }; @@ -90,8 +90,8 @@ StampBasePV::ExtractBin(std::shared_ptr blob) return v; } -template class StampBaseV: public StampBasePV -,public virtual StampBase //FIXME I do not understand why do we need it here, but wihtout it, it does not build +template class StampBaseV: public StampBasePV, +public virtual StampBase //FIXME I do not understand why do we need it here, but wihtout it, it does not build { public: virtual T ExtractValue(std::shared_ptr blob) = 0;/* Should be defined by derived classes*/ diff --git a/blobstamper/stamp_dict.cpp b/blobstamper/stamp_dict.cpp index 7a0be53..3abbcf1 100644 --- a/blobstamper/stamp_dict.cpp +++ b/blobstamper/stamp_dict.cpp @@ -24,17 +24,17 @@ int StampDict::ChooseStampSize(std::shared_ptr dict) { - if (dict->size() <= UCHAR_MAX+1) + if (dict->size() <= UCHAR_MAX + 1) { stamp_max_value = UCHAR_MAX; return 1; } - if (dict->size() <= USHRT_MAX+1) + if (dict->size() <= USHRT_MAX + 1) { stamp_max_value = USHRT_MAX; return 2; } - if (dict->size() <= UINT_MAX+1) + if (dict->size() <= UINT_MAX + 1) { stamp_max_value = UINT_MAX; return 4; @@ -76,6 +76,6 @@ StampDict::ExtractStr(std::shared_ptr blob) exit(1); } long long actual_index = ((double) index_oracle) / stamp_max_value * dict->size(); - if ( actual_index == dict->size()) actual_index--; /* If we hit the boundary step inside a bit*/ + if (actual_index == dict->size()) actual_index--; /* If we hit the boundary step inside a bit*/ return dict->get(actual_index); } diff --git a/blobstamper/stamp_dict.h b/blobstamper/stamp_dict.h index 36ecad9..0c46311 100644 --- a/blobstamper/stamp_dict.h +++ b/blobstamper/stamp_dict.h @@ -47,19 +47,17 @@ class StampDict: public StampBaseStr int maxSize() override {return stamp_size;} }; -class StampDictLCAlphaSmall : public StampDict +class StampDictLCAlphaSmall: public StampDict { public: - StampDictLCAlphaSmall (): StampDict(std::make_shared()) {}; + StampDictLCAlphaSmall(): StampDict(std::make_shared()) {}; }; template class StampDictT: public StampDict { - protected: - std::shared_ptr dict; public: - StampDictT(): StampDict(dict = std::make_shared()) {}; + StampDictT(): StampDict(std::make_shared()) {}; }; diff --git a/blobstamper/stamp_enumerator.cpp b/blobstamper/stamp_enumerator.cpp index 9419dd1..8e1146c 100644 --- a/blobstamper/stamp_enumerator.cpp +++ b/blobstamper/stamp_enumerator.cpp @@ -29,13 +29,13 @@ std::string StampStrEnumerator::ExtractStr(std::shared_ptr blob) std::vector data = ExtractStrVector(blob); std::string res = ""; - for(std::string s : data) + for (std::string s : data) { if (!res.empty()) { - res+= separator; + res += separator; } - res+= s; + res += s; } res = left_bracket + res + right_bracket; return res; diff --git a/blobstamper/stamp_enumerator.h b/blobstamper/stamp_enumerator.h index 20c5761..dc30c6d 100644 --- a/blobstamper/stamp_enumerator.h +++ b/blobstamper/stamp_enumerator.h @@ -19,11 +19,11 @@ #ifndef STAMP_ENUMERATOR_H #define STAMP_ENUMERATOR_H -#include"galley.h" -#include"stamp.h" -#include"blob.h" +#include "galley.h" +#include "stamp.h" +#include "blob.h" -#include +#include class StampStrEnumerator: public GalleyVectorStr, public StampBaseStr { diff --git a/blobstamper/stamp_json.cpp b/blobstamper/stamp_json.cpp index baba678..9eb003c 100644 --- a/blobstamper/stamp_json.cpp +++ b/blobstamper/stamp_json.cpp @@ -27,7 +27,7 @@ PoolPickerStamp::PoolPickerStamp(std::vector> new_pool) : pool{new_pool} { - for(auto stamp : pool) + for (auto stamp : pool) { std::weak_ptr wp = stamp; weak_pool.push_back(wp); @@ -37,10 +37,10 @@ PoolPickerStamp::PoolPickerStamp(std::vector> new_ bool PoolPickerStamp::isRecursive() { - if(is_recursive || is_in_recursion) + if (is_recursive || is_in_recursion) return true; is_in_recursion = true; - for(auto stamp : weak_pool) + for (auto stamp : weak_pool) { if (stamp.lock()->isRecursive()) { @@ -62,7 +62,7 @@ PoolPickerStamp::ExtractStr(std::shared_ptr blob) std::vector> target_pool; std::vector> unbounded_pool; - for(auto stamp_w : weak_pool) + for (auto stamp_w : weak_pool) { auto stamp = stamp_w.lock(); if (stamp->minSize() <= blob->Size()) @@ -74,8 +74,27 @@ PoolPickerStamp::ExtractStr(std::shared_ptr blob) } } } - if (unbounded_pool.size()>0) - target_pool = unbounded_pool; + if (! unbounded_pool.empty()) + target_pool = unbounded_pool; + + if (target_pool.empty()) + { + /* Most probably we are in out of data situation. Check it + * and throw an exception. Or abort if something goes wrong + * + * Normally caller should not call this method when he is out of data + * so it is OK to do the check at the end, when get no success, and not + * in the beginning. + */ + if (blob->Size() < this->minSize()) + { + throw OutOfData(); + } else + { + fprintf(stderr, "Something is really wrong in PoolPickerStamp::ExtractStr\n"); + abort(); + } + } size_t index = OracleProportion(oracle, 0, target_pool.size() - 1); return target_pool[index].lock()->ExtractStr(blob); @@ -111,7 +130,7 @@ PoolPickerStamp::maxSize() if (is_recursive || is_in_recursion) return -1; is_in_recursion = true; /* Do not use isRecursive() inside as it uses same flag*/ - for(auto stamp : weak_pool) + for (auto stamp : weak_pool) { int candidat = stamp.lock()->maxSize(); if (candidat == -1) @@ -168,4 +187,3 @@ StampJSON::StampJSON() add_weak(stamp_a); add_weak(stamp_h); } - diff --git a/blobstamper/stamp_json.h b/blobstamper/stamp_json.h index af1a7f0..c2ede5b 100644 --- a/blobstamper/stamp_json.h +++ b/blobstamper/stamp_json.h @@ -27,7 +27,7 @@ #include "stamp_dict.h" #include "stamp_enumerator.h" -class PoolPickerStamp : public virtual StampBaseStr +class PoolPickerStamp: public virtual StampBaseStr { protected: std::vector> pool; @@ -39,20 +39,20 @@ class PoolPickerStamp : public virtual StampBaseStr std::string ExtractStr(std::shared_ptr blob) override; virtual void add_weak(std::shared_ptr stamp); - virtual bool isRecursive(); + virtual bool isRecursive() override; virtual int minSize() override; virtual int maxSize() override; }; -class StampJSONInt : public virtual StampArithm +class StampJSONInt: public virtual StampArithm { }; -class StampJSONFloat : public virtual StampArithm +class StampJSONFloat: public virtual StampArithm { }; -class StampJSONString : public virtual StampDictT +class StampJSONString: public virtual StampDictT { protected: public: @@ -64,10 +64,9 @@ class StampJSONString : public virtual StampDictT class StampJSONArray: public StampStrEnumerator { - private: public: - StampJSONArray(std::shared_ptr picker) - :StampStrEnumerator(picker, ", ", "[", "]") {}; + StampJSONArray(std::shared_ptr picker): + StampStrEnumerator(picker, ", ", "[", "]") {}; }; class StampJSONHashEl: public StampBaseStr @@ -76,8 +75,8 @@ class StampJSONHashEl: public StampBaseStr std::shared_ptr stamp_name; std::shared_ptr stamp_value; public: - StampJSONHashEl(std::shared_ptr picker) - :stamp_value(picker), stamp_name(std::make_shared()) {}; + StampJSONHashEl(std::shared_ptr picker): + stamp_value(picker), stamp_name(std::make_shared()) {}; virtual int minSize() override {return stamp_name->minSize() + stamp_value->minSize();}; virtual int maxSize() override {return -1;}; std::string ExtractStr(std::shared_ptr blob) override; @@ -85,11 +84,9 @@ class StampJSONHashEl: public StampBaseStr class StampJSONHash: public StampStrEnumerator { - private: - std::shared_ptr stamp_el; public: - StampJSONHash(std::shared_ptr picker) - :StampStrEnumerator(stamp_el = std::make_shared(picker), ", ", "{", "}") {}; + StampJSONHash(std::shared_ptr picker): + StampStrEnumerator(std::make_shared(picker), ", ", "{", "}") {}; }; diff --git a/blobstamper/stamp_lottery.h b/blobstamper/stamp_lottery.h index f315994..2a4af2e 100644 --- a/blobstamper/stamp_lottery.h +++ b/blobstamper/stamp_lottery.h @@ -19,6 +19,7 @@ #ifndef STAMP_LOTTERY_H #define STAMP_LOTTERY_H +#include template class StampLottery: public StampT { protected: @@ -61,10 +62,10 @@ template bool StampLottery4Recursion:: soft_maxsize_filter(StampT &stamp, int data_size) { - if ( stamp.isUnbounded() || // Unbounded is always ok - stamp.maxSize() > data_size || // Variated that can consume all data is ok - stamp.minSize() + stamp.maxSize() > data_size // Fixed or variated stamp that lefts less data then it's min size will also do - ) + if (stamp.isUnbounded() || // Unbounded is always ok + stamp.maxSize() > data_size || // Variated that can consume all data is ok + stamp.minSize() + stamp.maxSize() > data_size // Fixed or variated stamp that lefts less data then it's min size will also do + ) return true; return false; } @@ -75,7 +76,7 @@ init_stored_min(std::ref_vector stamps_arg) { int min = std::numeric_limits::max(); - for(StampT & stamp : stamps) + for (StampT & stamp : stamps) { if (min > stamp.minSize()) @@ -90,13 +91,13 @@ init_stored_max(std::ref_vector stamps_arg) { int max = 0; - for(StampT & stamp : stamps) + for (StampT & stamp : stamps) { if (stamp.maxSize() == -1) return -1; if (max < stamp.maxSize()) - max = stamp.maxSize(); + max = stamp.maxSize(); } return max; } diff --git a/blobstamper/stamp_math_op.cpp b/blobstamper/stamp_math_op.cpp index 9c8f0bd..50ef4a6 100644 --- a/blobstamper/stamp_math_op.cpp +++ b/blobstamper/stamp_math_op.cpp @@ -30,6 +30,6 @@ std::string StampMathBinaryOp::ExtractStr(std::shared_ptr blob) { std::vector> blobs = extract_internal(blob); - return (std::string)"(" + stamp1->ExtractStr(blobs[0]) + " "+ op_name + " " + stamp2->ExtractStr(blobs[1]) + ")"; + return (std::string)"(" + stamp1->ExtractStr(blobs[0]) + " " + op_name + " " + stamp2->ExtractStr(blobs[1]) + ")"; } diff --git a/blobstamper/stamp_math_op.h b/blobstamper/stamp_math_op.h index 59877c6..a9fbe7b 100644 --- a/blobstamper/stamp_math_op.h +++ b/blobstamper/stamp_math_op.h @@ -19,9 +19,9 @@ #ifndef STAMP_MATH_OP_H #define STAMP_MATH_OP_H -#include"blob.h" -#include"stamp.h" -#include"galley.h" +#include "blob.h" +#include "stamp.h" +#include "galley.h" class StampMathUnaryOp: public StampBaseStr @@ -31,7 +31,7 @@ class StampMathUnaryOp: public StampBaseStr std::shared_ptr stamp; public: virtual std::string ExtractStr(std::shared_ptr blob) override; - StampMathUnaryOp(std::string arg_op_name, std::shared_ptr arg_stamp) : op_name(arg_op_name), stamp(arg_stamp) {}; + StampMathUnaryOp(std::string arg_op_name, std::shared_ptr arg_stamp): op_name(arg_op_name), stamp(arg_stamp) {}; virtual int maxSize() override {return -1;}; virtual int minSize() override {return stamp->minSize();}; }; @@ -48,7 +48,7 @@ class StampMathBinaryOp: public StampBaseStr, public GalleySetBase virtual std::string ExtractStr(std::shared_ptr blob) override; StampMathBinaryOp(std::string arg_op_name, std::shared_ptr arg_stamp1, - std::shared_ptr arg_stamp2) : + std::shared_ptr arg_stamp2): GalleySetBase({arg_stamp1, arg_stamp2}), op_name(arg_op_name), stamp1(arg_stamp1), diff --git a/blobstamper/stamp_text.cpp b/blobstamper/stamp_text.cpp index 7d8ade7..546cf2a 100644 --- a/blobstamper/stamp_text.cpp +++ b/blobstamper/stamp_text.cpp @@ -16,55 +16,41 @@ * ******************************************************************************/ -#include"stamp_text.h" +#include "stamp_text.h" std::string -StampTextPulp::ExtractStr(std::shared_ptr blob) +StampStringLatin1::ExtractStr(std::shared_ptr blob) { std::vector data = blob->Chop(minSize(), maxSize())->AsByteVector(); - std::vector::iterator the_iterator; + std::vector::iterator iterator; - the_iterator = data.begin(); - std:: string res; - while (the_iterator != data.end()) + iterator = data.begin(); + std::string res; + while (iterator != data.end()) { - if (*the_iterator == '\0') { *the_iterator = ' '; } - res.push_back(*the_iterator++); + if (*iterator == '\0') { *iterator = ' '; } + res.push_back(*iterator++); } return res; } -std::string StampTextPulpWords::ExtractStr(std::shared_ptr blob) +std::string +StampStringASCII::ExtractStr(std::shared_ptr blob) { - std::vector data = ExtractStrVector(blob); - std::string res = ""; - - for(std::string s : data) - { - if (!res.empty()) - { - res+=" "; - } - res+= s; - } - return res; -} + std::vector data = blob->Chop(minSize(), maxSize())->AsByteVector(); -std::string StampTextDictWords::ExtractStr(std::shared_ptr blob) -{ - std::vector data = ExtractStrVector(blob); - std::string res = ""; + std::vector::iterator iterator; - for(std::string s : data) - { - if (!res.empty()) + iterator = data.begin(); + std::string res; + while (iterator != data.end()) { - res+=" "; + *iterator &= 0x7F; // Remove first bit. This will made it ASCII (or more precisely 7bit encoding including character 0x01..0x1F) + if (*iterator == '\0') { *iterator = ' '; } + res.push_back(*iterator++); } - res+= s; - } - return res; + return res; } diff --git a/blobstamper/stamp_text.h b/blobstamper/stamp_text.h index 3b5c7fa..9c3f699 100644 --- a/blobstamper/stamp_text.h +++ b/blobstamper/stamp_text.h @@ -24,24 +24,48 @@ #include "stamp_dict.h" -class StampTextPulp: public StampBaseStr +class StampStringLatin1: public StampBaseStr { public: - virtual int minSize() override {return 1;} - virtual int maxSize() override {return -1;} + virtual int minSize() override { return 1; } + virtual int maxSize() override { return -1; } std::string ExtractStr(std::shared_ptr blob) override; }; -class StampTextPulpWords: public GalleyVectorStrStampBase +class StampStringASCII: public StampBaseStr { public: - virtual std::string ExtractStr(std::shared_ptr blob) override; + virtual int minSize() override { return 1; } + virtual int maxSize() override { return -1; } + std::string ExtractStr(std::shared_ptr blob) override; }; -class StampTextDictWords: public GalleyVectorStrStampBase +template class StampText: public GalleyVectorStrStampBase { public: virtual std::string ExtractStr(std::shared_ptr blob) override; }; + +/* StampText create a string that consist of word that are separated by spaces. + * Each word is created by T stamp, (T is template parameter, you can set any + * stamp type there */ + +template +std::string StampText::ExtractStr(std::shared_ptr blob) +{ + std::vector data = this->ExtractStrVector(blob); + std::string res = ""; + + for(std::string s : data) + { + if (!res.empty()) + { + res+=" "; + } + res+= s; + } + return res; +} + #endif /* STAMP_TEXT_H */ diff --git a/libtappp/README.md b/libtappp/README.md new file mode 100644 index 0000000..99c6a2f --- /dev/null +++ b/libtappp/README.md @@ -0,0 +1,323 @@ +# NAME + +libtap++ - C++ unit tests for the Test Anything Protocol + +# SYNOPSIS + + #include + #include + + using namespace TAP; + + int foo(int ronkle = 1) { + return ronkle; + } + + std::string bar() { + return "a string"; + } + + int main() { + plan(4); + ok(true, "This test passes"); + is(foo(), 1, "foo() should be 1"); + is(bar(), "a string", "bar() should be \"a string\""); + + TODO="Foo is not completely implemented"; + is(foo(2), 5, "foo(2) should be 5"); + TODO=""; + + return exit_status(); + } + +# DESCRIPTION + +`libtap++` is a TAP producer for C++ programs. + +# HISTORY + +libtap++ was originally developed as a part of +[libperl++](https://github.com/Leont/libperl--) project by Leon Timmermans + +Then forked into separate [libtap++](https://github.com/cbab/libtappp) +project by Christian Babeux + +Now libtap++ us supported by Nikolay Shaplov at +[https://gitlab.com/dhyannataraj/libtappp](https://gitlab.com/dhyannataraj/libtappp) + +# FUNCTIONS + +All functions and variables are defined in the `TAP` namespace. + +## I love it when a plan comes together + +Before anything else, you need a testing plan. This basically declares +how many tests your script is going to run to protect against premature +failure. + +- **plan()** + + void plan(int number_of_tests); + void plan(skip_all, const std::string& reason=""); + void plan(no_plan); + + The function `plan` is used to indicate the plan of your test run. Usually you + will just give it the number of tests as argument. + + Alternatively, you can give it the `skip_all` or `no_plan` constants as + arguments. The first means you will not run the tests at all, the second means + you will run an unknown number of tests (the latter is not recommended). + +- **done\_testing()** + + void done_testing(); + void done_testing(int number_of_tests); + + If you don't know how many tests you're going to run, you can issue the plan + when you're done running tests. + + number\_of\_tests is the same as plan(), it's the number of tests you expected to + run. You can omit this, in which case the number of tests you ran doesn't + matter, just the fact that your tests ran to conclusion. + + This is safer than and replaces the "no\_plan" plan. + +## Test names + +By convention, each test is assigned a number in order. This is +largely done automatically for you. However, it's often very useful to +assign a name to each test. Which would you rather see: + + ok 4 + not ok 5 + ok 6 + +or + + ok 4 - basic multi-variable + not ok 5 - simple exponential + ok 6 - force == mass * acceleration + +The later gives you some idea of what failed. It also makes it easier +to find the test in your script, simply search for "simple +exponential". + +All test functions take a name argument. It's optional, but highly +suggested that you use it. + +## I'm ok, you're not ok. + +The basic purpose of this module is to print out either "ok #" or "not +ok #" depending on if a given test succeeded or failed. Everything +else is just gravy. + +All of the following print "ok" or "not ok" depending on if the test +succeeded or failed. They all also return true or false, +respectively. + +- **ok()** + + bool ok(bool condition, const std::string& test_name = ""); + + `ok` is the basic test expression in TAP. It simply evaluates any expression, + for example, _got == expected_, taking a true value to mean that the test + passed and a false value to mean that the test failed. + + `test_name` is a very short description of the test that will be printed out. + It makes it very easy to find a test in your script when it fails and gives + others an idea of your intentions. `test_name` is optional, but we very + strongly encourage its use. + +- **is()** +- **isnt()** + + template bool is(const T& got, const U& expected, std::string& test_name = ""); + template bool isnt(const T& got, const U& expected, std::string& test_name = ""); + + Similar to ok(), is() and isnt() compare their two arguments + with `==` and `!=` respectively and use the result of that to + determine if the test succeeded or failed. So these: + + # Is the ultimate answer 42? + is( ultimate_answer(), 42, "Meaning of Life" ); + + # foo isn't empty + isnt( foo, "", "Got some foo" ); + + are similar to these: + + ok( ultimate_answer() == 42, "Meaning of Life" ); + ok( foo != "", "Got some foo" ); + + (Mnemonic: "This is that." "This isn't that.") + + So why use these? They produce better diagnostics on failure. ok() cannot know + what you are testing for (beyond the name), but is() and isnt() know what the + test was and why it failed. For example this test: + + std::string foo("waffle"), bar("yarblokos"); + is( foo, bar, 'Is foo the same as bar?' ); + + Will produce something like this: + + not ok 17 - Is foo the same as bar? + # Failed test 'Is foo the same as bar?' + # got: 'waffle' + # expected: 'yarblokos' + +- **pass()** +- **fail()** + + bool pass(const std::string& test_name = ""); + bool fail(const std::string& test_name = ""); + + Sometimes you just want to say that the tests have passed. Usually + the case is you've got some complicated condition that is difficult to + wedge into an ok(). In this case, you can simply use pass() (to + declare the test ok) or fail (for not ok). They are synonyms for + ok(true, test\_name) and ok(false, test\_name). + + Use these very, very, very sparingly. + +## Conditional testing + +- **skip()** + + void skip(int number, const std::string& reason = ""); + + `skip` tells the TAP harness that you're skipping a _number_ of tests for the + given _reason_. Note that you have to do the skipping yourself. + +- **TODO** + + { + todo_guard why; + TODO="why" + my_tests_here ... + } + + `TODO` is a global string variable that tells TAP harness the reason + the current test is expected to fail. You set TODO before a block of + tests that you expect to fail and then unset it afterwards. When TODO + is the empty string, then the harness considers that there is no + reason for the test to fail. However, when TODO is non-empty, any + failing test is not counted against the test suite and any succeeding + test is reported as an unexpected success. + + The nice part about todo tests, as opposed to simply commenting out a + block of tests, is it's like having a programmatic todo list. You know + how much work is left to be done, you're aware of what bugs there are, + and you'll know immediately when they're fixed. + + Note that TODO manipulates a global variable. Thus, you should be + careful to set it to "" before going to another section of the + program. An easy mistake to make is to have a failing section of code + that throws an exception, taking you out of the current scope without + resetting TODO. To make it easier to deal with this in a thread-safe + manner, the todo\_guard class is provided. Objects of this class will + reset TODO when they fall out of scope. + +## Diagnostics + +If you pick the right test function, you'll usually get a good idea of +what went wrong when it failed. But sometimes it doesn't work out +that way. So here we have ways for you to write your own diagnostic +messages which are safer than just `print STDERR`. + +- **diag** + + diag(diagnostic_message...); + + Prints a diagnostic message which is guaranteed not to interfere with + test output. The arguments are simply concatenated together. + + Returns false, so as to preserve failure. + + Handy for this sort of thing: + + ok( has_user("foo"), "There's a foo user" ) or + diag("Since there's no foo, check that /etc/bar is set up right"); + + which would produce: + + not ok 42 - There's a foo user + # Failed test 'There's a foo user' + # Since there's no foo, check that /etc/bar is set up right. + + You might remember `ok() or diag()` with the mnemonic `open() or + die()`. + + **NOTE** The exact formatting of the diagnostic output is still + changing, but it is guaranteed that whatever you throw at it it won't + interfere with the test. + +- **note** + + note(diagnostic_message...); + + Like diag(), except the message will not be seen when the test is run + in a harness. It will only be visible in the verbose TAP stream. + + Handy for putting in notes which might be useful for debugging, but + don't indicate a problem. + + note("Tempfile is ", tempfile); + + `diag` simply catenates its arguments to the error output, while `note` + prints diagnostics to the TAP stream. + +- **set\_output()** +- **set\_error()** + + void set_output(std::ofstream& new_output); + void set_error(std::ofstream& new_error); + + These set the filehandle of the TAP stream and the error stream. They default + to `std::cout` and `std::cerr`, respectively. These can only be set before any + output is written to them. + +## Ending a test run + +- **exit\_status()** + + If all your tests passed, Test::Builder will exit with zero (which is + normal). If anything failed it will exit with how many failed. If + you run less (or more) tests than you planned, the missing (or extras) + will be considered failures. If the test died, even after having + successfully completed all its tests, it will still be considered a failure + and will exit with 255. + + So the exit codes are... + + 0 all tests successful + 255 test died or all passed but wrong # of tests run + any other number how many failed (including missing or extras) + + If you fail more than 254 tests, it will be reported as 254. + +- **bail\_out()** + + int exit_status(); + void bail_out(const std::string& reason); + + **bail\_out** terminates the current test program with exit code 255, indicating + to the test harness that all subsequent testing should halt. Typically this + is used to indicate that testing cannot continue at all. + +# SEE ALSO + +[http://www.testanything.org](http://www.testanything.org) + +[Test::More](https://metacpan.org/pod/Test%3A%3AMore) and [prove(1)](http://man.he.net/man1/prove) are the traditional perl client library and TAP +harness, respectively. This library is modeled after Test::More. + +# AUTHORS + +Leon Timmermans wrote `libtap++`. He stole much of this documentation from +Test::More. Mike Pomraning also contributed this documentation. + +# COPYRIGHT + +Copyright (c) 2008, 2009, 2010 Leon Timmermans. + +See the LICENSE file for details. diff --git a/libtappp/README.pod b/libtappp/README.pod index ffaf33d..cd832e6 100644 --- a/libtappp/README.pod +++ b/libtappp/README.pod @@ -36,6 +36,17 @@ libtap++ - C++ unit tests for the Test Anything Protocol C is a TAP producer for C++ programs. +=head1 HISTORY + +libtap++ was originally developed as a part of +L project by Leon Timmermans + +Then forked into separate L +project by Christian Babeux + +Now libtap++ us supported by Nikolay Shaplov at +L + =head1 FUNCTIONS All functions and variables are defined in the C namespace. diff --git a/libtappp/include/tap++/tap++.h b/libtappp/include/tap++/tap++.h index 7ad6d8d..f9adb99 100644 --- a/libtappp/include/tap++/tap++.h +++ b/libtappp/include/tap++/tap++.h @@ -11,6 +11,13 @@ #pragma warning( disable : 4290 ) // MSVC: https://msdn.microsoft.com/en-us/library/sa28fef8.aspx #endif +#if __cplusplus >= 201103L +#define NOEXCEPT noexcept(true) +#else +#define NOEXCEPT throw() +#endif + + namespace TAP { namespace details { struct skip_all_type {}; @@ -20,7 +27,7 @@ namespace TAP { /* Return the variant of "Failed test" or "Failed */ /* (TODO) test" required by whether the current test is a todo test */ - char const * failed_test_msg() throw(); + char const * failed_test_msg() NOEXCEPT; } class fatal_exception : public std::exception { std::string message; @@ -30,64 +37,64 @@ namespace TAP { const char* what() const throw() { return message.c_str(); } - ~fatal_exception() throw() { + ~fatal_exception() NOEXCEPT { } }; extern const details::skip_all_type skip_all; extern const details::no_plan_type no_plan; - void plan(unsigned) throw(fatal_exception); - void plan(const details::skip_all_type&, const std::string& = "") throw(fatal_exception); - void plan(const details::no_plan_type&) throw(); - void done_testing() throw(fatal_exception); - void done_testing(unsigned) throw(fatal_exception); + void plan(unsigned); + void plan(const details::skip_all_type&, const std::string& = ""); + void plan(const details::no_plan_type&) NOEXCEPT; + void done_testing(); + void done_testing(unsigned); - unsigned planned() throw(); - unsigned encountered() throw(); + unsigned planned() NOEXCEPT; + unsigned encountered() NOEXCEPT; - bool ok(bool, const std::string& = "") throw(); - bool not_ok(bool, const std::string& = "") throw(); + bool ok(bool, const std::string& = "") NOEXCEPT; + bool not_ok(bool, const std::string& = "") NOEXCEPT; - bool pass(const std::string& = "") throw(); - bool fail(const std::string& = "") throw(); + bool pass(const std::string& = "") NOEXCEPT; + bool fail(const std::string& = "") NOEXCEPT; - void skip(unsigned, const std::string& = "") throw(); - void bail_out(const std::string& reason) throw(); + void skip(unsigned, const std::string& = "") NOEXCEPT; + void bail_out(const std::string& reason) NOEXCEPT; - int exit_status() throw(); - bool summary() throw(); + int exit_status() NOEXCEPT; + bool summary() NOEXCEPT; - void set_output(std::ostream&) throw(fatal_exception); - void set_error(std::ostream&) throw(fatal_exception); + void set_output(std::ostream&); + void set_error(std::ostream&); - template void diag(const T& first) throw() { + template void diag(const T& first) NOEXCEPT { *details::error << "# " << first << std::endl; } - template void diag(const T1& first, const T2& second) throw() { + template void diag(const T1& first, const T2& second) NOEXCEPT { *details::error << "# " << first << second << std::endl; } - template void diag(const T1& first, const T2& second, const T3& third) throw() { + template void diag(const T1& first, const T2& second, const T3& third) NOEXCEPT { *details::error << "# " << first << second << third << std::endl; } - template void diag(const T1& first, const T2& second, const T3& third, const T4& fourth) throw() { + template void diag(const T1& first, const T2& second, const T3& third, const T4& fourth) NOEXCEPT { *details::error << "# " << first << second << third << fourth << std::endl; } - template void diag(const T1& first, const T2& second, const T3& third, const T4& fourth, const T5& fifth) throw() { + template void diag(const T1& first, const T2& second, const T3& third, const T4& fourth, const T5& fifth) NOEXCEPT { *details::error << "# " << first << second << third << fourth << fifth << std::endl; } - template void note(const T& first) throw() { + template void note(const T& first) NOEXCEPT { *details::output << "# " << first << std::endl; } - template void note(const T1& first, const T2& second) throw() { + template void note(const T1& first, const T2& second) NOEXCEPT { *details::output << "# " << first << second << std::endl; } - template void note(const T1& first, const T2& second, const T3& third) throw() { + template void note(const T1& first, const T2& second, const T3& third) NOEXCEPT { *details::output << "# " << first << second << third << std::endl; } - template void note(const T1& first, const T2& second, const T3& third, const T4& fourth) throw() { + template void note(const T1& first, const T2& second, const T3& third, const T4& fourth) NOEXCEPT { *details::output << "# " << first << second << third << fourth << std::endl; } - template void note(const T1& first, const T2& second, const T3& third, const T4& fourth, const T5& fifth) throw() { + template void note(const T1& first, const T2& second, const T3& third, const T4& fourth, const T5& fifth) NOEXCEPT { *details::output << "# " << first << second << third << fourth << fifth << std::endl; } @@ -246,8 +253,8 @@ namespace TAP { class todo_guard { const std::string value; public: - todo_guard() throw(); - ~todo_guard() throw(); + todo_guard() NOEXCEPT; + ~todo_guard() NOEXCEPT; }; } @@ -257,22 +264,22 @@ namespace TAP { namespace details { struct Skip_exception { const std::string reason; - Skip_exception(const std::string& _reason) throw() : reason(_reason) { + Skip_exception(const std::string& _reason) NOEXCEPT : reason(_reason) { } }; struct Todo_exception { const std::string reason; - Todo_exception(const std::string& _reason) throw() : reason(_reason) { + Todo_exception(const std::string& _reason) NOEXCEPT : reason(_reason) { } }; - void start_block(unsigned) throw(); - unsigned stop_block() throw(fatal_exception); + void start_block(unsigned) NOEXCEPT; + unsigned stop_block(); } - void skip(const std::string& reason) throw(details::Skip_exception); - void skip_todo(const std::string& reason) throw(details::Todo_exception); + void skip(const std::string& reason); + void skip_todo(const std::string& reason); } #define TRY(action, name) do {\ diff --git a/libtappp/src/tap++.cpp b/libtappp/src/tap++.cpp index 8898ddf..34a4876 100644 --- a/libtappp/src/tap++.cpp +++ b/libtappp/src/tap++.cpp @@ -18,7 +18,7 @@ namespace TAP { unsigned counter = 0; unsigned not_oks = 0; - std::string todo_test() throw() { + std::string todo_test() NOEXCEPT { if (TODO == "") { return TODO; } @@ -27,26 +27,26 @@ namespace TAP { } } - bool is_todo_test() throw() { return TODO != ""; } + bool is_todo_test() NOEXCEPT { return TODO != ""; } bool is_planned = false; bool no_planned = false; bool has_output_plan = false; - void output_plan(unsigned tests, const std::string& extra = "") throw(fatal_exception) { + void output_plan(unsigned tests, const std::string& extra = "") { if (has_output_plan) { throw fatal_exception("Can't plan twice"); } *details::output << "1.." << tests << extra << std::endl; has_output_plan = true; } - inline const std::string to_string(unsigned num) throw() { + inline const std::string to_string(unsigned num) NOEXCEPT { std::stringstream out; out << num; return out.str(); } - inline void _done_testing(unsigned tests) throw(fatal_exception) { + inline void _done_testing(unsigned tests) { static bool is_done = false; if (is_done) { fail("done_testing() was already called"); @@ -68,7 +68,7 @@ namespace TAP { } - void plan(unsigned tests) throw(fatal_exception) { + void plan(unsigned tests) { if (is_planned) { bail_out("Can't plan again!"); } @@ -76,32 +76,32 @@ namespace TAP { output_plan(tests); expected = tests; } - void plan(const details::skip_all_type&, const std::string& reason) throw(fatal_exception) { + void plan(const details::skip_all_type&, const std::string& reason) { output_plan(0, " #skip " + reason); std::exit(0); } - void plan(const details::no_plan_type&) throw() { + void plan(const details::no_plan_type&) NOEXCEPT { is_planned = true; no_planned = true; } - void done_testing() throw(fatal_exception) { + void done_testing() { _done_testing(encountered()); } - void done_testing(unsigned tests) throw(fatal_exception) { + void done_testing(unsigned tests) { no_planned = false; _done_testing(tests); } - unsigned planned() throw() { + unsigned planned() NOEXCEPT { return expected; } - unsigned encountered() throw() { + unsigned encountered() NOEXCEPT { return counter; } - int exit_status() throw () { + int exit_status() NOEXCEPT { // bool passing; if (!is_planned && encountered()) { diag("Tests were run but no plan was declared and done_testing() was not seen."); @@ -117,16 +117,16 @@ namespace TAP { return 255; } } - bool summary() throw() { + bool summary() NOEXCEPT { return (not_oks != 0); } - void bail_out(const std::string& reason) throw() { + void bail_out(const std::string& reason) NOEXCEPT { *details::output << "Bail out! " << reason << std::endl; std::exit(255); // Does not unwind stack! } - bool ok(bool is_ok, const std::string& message) throw() { + bool ok(bool is_ok, const std::string& message) NOEXCEPT { const char* hot_or_not = is_ok ? "" : "not "; *details::output << hot_or_not << "ok " << ++counter<< " - " << message << todo_test() << std::endl; if (!is_ok && !is_todo_test()) { @@ -134,63 +134,63 @@ namespace TAP { } return is_ok; } - bool not_ok(bool is_not_ok, const std::string& message) throw() { + bool not_ok(bool is_not_ok, const std::string& message) NOEXCEPT { return !ok(!is_not_ok, message); } - bool pass(const std::string& message) throw() { + bool pass(const std::string& message) NOEXCEPT { return ok(true, message); } - bool fail(const std::string& message) throw() { + bool fail(const std::string& message) NOEXCEPT { return ok(false, message); } - void skip(unsigned num, const std::string& reason) throw () { + void skip(unsigned num, const std::string& reason) NOEXCEPT { for(unsigned i = 0; i < num; ++i) { pass(" # skip " + reason); } } - void set_output(std::ostream& new_output) throw (fatal_exception) { + void set_output(std::ostream& new_output) { if (is_planned) { throw fatal_exception("Can't set output after plan()"); } details::output = &new_output; } - void set_error(std::ostream& new_error) throw(fatal_exception) { + void set_error(std::ostream& new_error) { if (is_planned) { throw fatal_exception("Can't set error after plan()"); } details::error = &new_error; } - todo_guard::todo_guard() throw() : value(TODO) { + todo_guard::todo_guard() NOEXCEPT : value(TODO) { } - todo_guard::~todo_guard() throw() { + todo_guard::~todo_guard() NOEXCEPT { TODO = value; } namespace details { std::ostream* output = &std::cout; std::ostream* error = &std::cout; static std::stack block_expected; - void start_block(unsigned expected) throw() { + void start_block(unsigned expected) NOEXCEPT { block_expected.push(encountered() + expected); } - unsigned stop_block() throw(fatal_exception) { + unsigned stop_block() { unsigned ret = block_expected.top(); block_expected.pop(); return ret; } - char const * failed_test_msg() throw() { + char const * failed_test_msg() NOEXCEPT { return is_todo_test()?"Failed (TODO) test":"Failed test"; } } - void skip(const std::string& reason) throw(details::Skip_exception) { + void skip(const std::string& reason) { throw details::Skip_exception(reason); } - void skip_todo(const std::string& reason) throw(details::Todo_exception) { + void skip_todo(const std::string& reason) { throw details::Todo_exception(reason); } diff --git a/t/150-stamp_text.cpp b/t/150-stamp_text.cpp index 9bd2165..c3212df 100644 --- a/t/150-stamp_text.cpp +++ b/t/150-stamp_text.cpp @@ -31,30 +31,48 @@ using namespace TAP; int main() { - TEST_START(3); - { /* 1..1 */ - char data[] = "папа\0мама\0бабушка\0дедушка\0братик\0сестричка"; - std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); - StampTextPulp stamp; - std::string s = stamp.ExtractStr(blob); - is(s, "папа мама бабушка дедушка братик сестричка", "StampTextSimple"); - - } - { /* 2..2 */ - char data[] = "dad\0mam\0granddad\0grandmam\0brother\0sister"; - std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); - StampTextPulpWords stamp; - std::string s = stamp.ExtractStr(blob); - is(s, "d dad gra n dmam broth er siste", "GalleyTextSimple"); - - } - { /* 3..3 */ - char data[] = "abcdef" "abcdef" "ABCDEF" "012345"; - std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); - StampTextDictWords stamp; - std::string s = stamp.ExtractStr(blob); - is(s, "gleam godfather graffiti greened grouping gunshots gleam godfather graffiti greened grouping gunshots dismally dissented divested doorstep dread drunks convertors corpulent counterparts cranking crippled crusades", "GalleyLCAlphaSmall"); - - } - TEST_END; + TEST_START(5); + { /* 1..1 */ + char data[] = "папа\0мама\0бабушка\0дедушка\0братик\0сестричка"; + std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); + StampStringLatin1 stamp_str_l1; + std::string s = stamp_str_l1.ExtractStr(blob); + is(s, "папа мама бабушка дедушка братик сестричка", "StampStringLatin1"); + } + + { /* 2..2 */ + char data[] = "папа\0мама\0бабушка\0дедушка\0братик\0сестричка"; + std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); + StampStringASCII stamp_str_ascii; + std::string s = stamp_str_ascii.ExtractStr(blob); + is(s, + "P?P0P?P0 P blob = std::make_shared(data, (sizeof data)-1); + StampText stamp; + std::string s = stamp.ExtractStr(blob); + is(s, "d dad gra n dmam broth er siste", "StampText"); + } + + { /* 4..4 */ + char data[] = "abcdef" "abcdef" "ABCDEF" "012345"; + std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); + StampText stamp; + std::string s = stamp.ExtractStr(blob); + is(s, "gleam godfather graffiti greened grouping gunshots gleam godfather graffiti greened grouping gunshots dismally dissented divested doorstep dread drunks convertors corpulent counterparts cranking crippled crusades", "StampText"); + } + + { /* 5..5 */ + char data[] = "Некоторый текст написанный русскими буквами в кодировке utf-8"; + std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); + StampText stamp; + std::string s = stamp.ExtractStr(blob); + is(s, "P9 Q Q\x3Q \x1Q \x1P: P8 P

P 4P8 Q P>P 2P :P5 ut f-8", "StampText"); + } + + TEST_END; } diff --git a/t/321-galley-recursion-experiments_2.cpp b/t/321-galley-recursion-experiments_2.cpp index 2d14942..c995e22 100644 --- a/t/321-galley-recursion-experiments_2.cpp +++ b/t/321-galley-recursion-experiments_2.cpp @@ -18,13 +18,14 @@ #include #include +#include + + #define WANT_TEST_EXTRAS #include #include "blobstamper/stamp_json.h" - -// tmp -#include +#include "blobstamper/oracle.h" using namespace TAP; @@ -36,30 +37,78 @@ unsigned char bin_sample[]= {49, 22, 152, 226, 89, 119, 247, 115, 43, 42, 243, 7 int main() { - std::fstream f{"/dev/random"}; -// std::fstream f{"buf"}; - if (!f) - std::cerr << "Unable to open file"; - - std::vector buffer (128,0); - f.read(&buffer[0], buffer.size()); - -// auto blob = std::make_shared((char *)bin_sample, strlen((char *)bin_sample)); - auto blob = std::make_shared(&buffer[0], buffer.size()); - - - auto stamp_j = std::make_shared(); - - std::string s = stamp_j->ExtractStr(blob); - printf("%s\n", s.c_str()); +// If you uncomment this it will crash for reason I do not understand -/* +/* auto blob1 = std::make_shared((char *)bin_sample, strlen((char *)bin_sample)); + auto stamp_j1 = std::make_shared(); + std::string s1 = stamp_j1->ExtractStr(blob1); + printf("%s\n", s1.c_str()); +*/ - TEST_START(6); + TEST_START(5); { + auto blob = std::make_shared((char *)bin_sample, strlen((char *)bin_sample)); + auto stamp_j = std::make_shared(); + std::string s = stamp_j->ExtractStr(blob); + std::string expected = "[6850509402014839822, 3438255817691106319, \"resulted\", -2.684757453484730872673776686700739040682020879678934003695336094670709694419006239953740106372555463816175000634871124431422513570790242370232656601974908085084433064181237341375458199532539671263821862377193715039215799333468172751725903574125176464661297323397544866180407166347114750393787405005704461598334438005517341732432719884411807209593715412099886215291366653445948031730949878692626953125e-151, \"lushes\", -5199661808640109653, \"denomination\", -3.06532686549173138956803086330182850360870361328125, \"sedating\", \"robots\", -3.3696970613711244822470283884492113423278459359891097388748050077510095184860700081976239055565263066452656899596451722800338757224380970001220703125e-42, \"preface\", 9.55422367779008699072920786882312943145717681740324270561686674939552239415695463827122863940711666092367434557202401330797838517640477979352142678948212051182053983211517333984375e-56, 6300155112918555921, \"dams\", 2.411323842459936645124797826433320804619144161893916130561265623523643502350374626190490408739886564139366504029821786107467040377895714047017891228899122281601579488797245463600235576598531485903332393648607370715931713232242018751523644727805408352870771308312443806176048554264200149458533769648133943422986030732712523236966445578809656378067940216124429747414289524093606877704785435824362397944294729373146388523502884316004124548536154374326842524560415029933595880452289294570895862703927051929788804023836835074268010108198185051300394774230223405817676130206688777308144339841912135245325959771275736867526109676372404347501558868228887456576678950716422841427035057837446885287135955877602100372314453125e-287, 9188031415654983422, -5901895462997796268, \"blazer\"]"; + is(s, expected, "json stamp works well"); + } + /* Smallest sample giving sane output */ + { + auto blob = std::make_shared((char *)bin_sample, 10); /* ORACLE_SIZE = 2 + int = 8 */ + auto stamp_j = std::make_shared(); + std::string s = stamp_j->ExtractStr(blob); + std::string expected = "3038649880288027288"; + is(s, expected, "json stamp on shortest data works well"); + } + /* Check throw OutOfMemory when data length is less then ORACLE_SIZE */ + { + auto blob = std::make_shared((char *)bin_sample, ORACLE_SIZE - 1); + auto stamp_j = std::make_shared(); + + int cought = 0; + try{ + std::string s = stamp_j->ExtractStr(blob); + } + catch (OutOfData) + { + cought = 1; + } + ok(cought, "Throws OutOfData if have data size less then ORACLE_SIZE"); + } + /* Check throw OutOfMemory when data length is equal to ORACLE_SIZE */ + { + auto blob = std::make_shared((char *)bin_sample, ORACLE_SIZE); + auto stamp_j = std::make_shared(); + + int cought = 0; + try{ + std::string s = stamp_j->ExtractStr(blob); + } + catch (OutOfData) + { + cought = 1; + } + ok(cought, "Throws OutOfData if have data size equal to ORACLE_SIZE"); + } + /* Check throw OutOfMemory when data length is bit bigger than ORACLE_SIZE */ + /* But not big enough to give any output */ + { + auto blob = std::make_shared((char *)bin_sample, ORACLE_SIZE + 1); + auto stamp_j = std::make_shared(); + + int cought = 0; + try{ + std::string s = stamp_j->ExtractStr(blob); + } + catch (OutOfData) + { + cought = 1; + } + ok(cought, "Throws OutOfData if have data size is a bit bigger then ORACLE_SIZE"); } - TEST_END;*/ + TEST_END; } diff --git a/test_with_sanitizers.sh b/test_with_sanitizers.sh index 7f74d93..4ba2399 100755 --- a/test_with_sanitizers.sh +++ b/test_with_sanitizers.sh @@ -9,4 +9,6 @@ export LDFLAGS="-g -fsanitize=address -fsanitize=undefined -fno-sanitize-recove make clean make make examples +make -C console_demo make test +make -C t