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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy