├── .editorconfig ├── .git-blame-ignore-revs ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── blobstamper ├── Makefile ├── blob.cpp ├── blob.h ├── blobstamper.h ├── dict.cpp ├── dict.h ├── galley.cpp ├── galley.h ├── helpers.cpp ├── helpers.h ├── oracle.cpp ├── oracle.h ├── stamp.cpp ├── stamp.h ├── stamp_arithm.cpp ├── stamp_arithm.h ├── stamp_dict.cpp ├── stamp_dict.h ├── stamp_enumerator.cpp ├── stamp_enumerator.h ├── stamp_json.cpp ├── stamp_json.h ├── stamp_lottery.cpp ├── stamp_lottery.h ├── stamp_math_op.cpp ├── stamp_math_op.h ├── stamp_text.cpp └── stamp_text.h ├── console_demo ├── Makefile ├── _run.sh ├── pseudo_fuzz.pl ├── pulp2json.cpp └── run.sh ├── examples ├── Makefile ├── example01.cpp ├── example01a.cpp ├── example02.cpp ├── example02a.cpp ├── example03.cpp ├── example04.cpp ├── example05.cpp ├── example06.cpp ├── example07.cpp ├── example08.cpp └── exampleZZ.cpp ├── libtappp ├── .travis.yml ├── Makefile ├── README.md ├── README.pod ├── include │ └── tap++ │ │ └── tap++.h ├── run_tests.pl ├── src │ └── tap++.cpp └── t │ └── 00-sanity.cpp ├── t ├── 00-sanity.cpp ├── 001-blob-generic.cpp ├── 050-sized_prt_and_vsato_ptr.cpp ├── 060-oracle.cpp ├── 100-stamp-base.cpp ├── 110-stamp-arithm.cpp ├── 120-stamp_dict.cpp ├── 130-stamp_enumerator.cpp ├── 140-stamp_lottery.cpp ├── 150-stamp_text.cpp ├── 200-dict.cpp ├── 300-galley.cpp ├── 320-galley-recursion-experiments.cpp ├── 321-galley-recursion-experiments_2.cpp ├── Makefile ├── README.md └── test-chars-stamps.h └── test_with_sanitizers.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://editorconfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | charset = utf-8 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # git config blame.ignoreRevsFile .git-blame-ignore-revs 2 | # ignore codestyle commits 3 | 1a6aebd9d208d77f161b50a74fd0c673c1746e70 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.t 3 | *.so 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Guide used while writing this makefile is 3 | # https://stackoverflow.com/questions/68428103/how-to-create-a-makefile-for-a-c-project-with-multiple-directories 4 | 5 | 6 | # https://stackoverflow.com/questions/18007326/how-to-change-default-values-of-variables-like-cc-in-makefile 7 | ifeq ($(origin CC),default) 8 | CC = gcc 9 | endif 10 | 11 | BLOBSTAMPER_SRC := $(wildcard blobstamper/*.cpp) 12 | BLOBSTAMPER_OBJ := $(addsuffix .o, $(basename $(BLOBSTAMPER_SRC))) 13 | 14 | EXAMPLES_SRC = $(wildcard examples/*.cpp) 15 | EXAMPLES_BIN = $(basename $(EXAMPLES_SRC)) 16 | 17 | 18 | .PHONY: all blob-stamper-all blob-stamper-clean clean test gagaga 19 | 20 | all: $(BLOBSTAMPER_OBJ) 21 | @echo All done! 22 | 23 | blobstamper/%.o: blobstamper/%.cpp 24 | $(CXX) -c -g $(CXXFLAGS) $< -o $@ 25 | 26 | 27 | # blob-stamper-all: 28 | # $(MAKE) -C blobstamper 29 | 30 | #%.o: %.cpp $(DEPS) 31 | # $(CXX) -c -g $(CFLAGS) $< 32 | 33 | #%.o: %.c $(DEPS) 34 | # $(CC) -c -g $(CXXFLAGS) $< 35 | 36 | 37 | 38 | blob-stamper-clean: 39 | rm -f *.o 40 | 41 | clean: blob-stamper-clean 42 | $(MAKE) -C blobstamper clean 43 | $(MAKE) -C t clean 44 | $(MAKE) -C examples clean 45 | $(MAKE) -C libtappp clean 46 | $(MAKE) -C console_demo clean 47 | @echo Clean done! 48 | 49 | test: 50 | $(MAKE) -C t test 51 | 52 | #test_dict: test_dict.o blob-stamper-all 53 | # $(CXX) $(LDFLAGS) $@.o -o $@ $(BLOB_STAMPER_OBJ) 54 | 55 | examples: $(BLOBSTAMPER_OBJ) 56 | $(MAKE) -C examples 57 | 58 | gagaga: 59 | @echo ------- $(BLOBSTAMPER_OBJ) 60 | 61 | #all: blob-stamper-all test_dict $(WRAPPERS_OBJ) 62 | #all: blob-stamper-all $(WRAPPERS_OBJ) 63 | # @echo All done! 64 | -------------------------------------------------------------------------------- /blobstamper/Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | BLOBSTAMPER_SRC := $(wildcard ./*.cpp) 4 | BLOBSTAMPER_OBJ := $(addsuffix .o, $(basename $(BLOBSTAMPER_SRC))) 5 | 6 | 7 | %.o: %.cpp 8 | $(CXX) -c -g $(CXXFLAGS) -I .. $< -o $@ 9 | 10 | 11 | all: $(BLOBSTAMPER_OBJ) 12 | 13 | .PHONY: clean 14 | clean: 15 | rm -f *.o -------------------------------------------------------------------------------- /blobstamper/blob.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include "blob.h" 22 | #include "helpers.h" 23 | 24 | #include "stamp.h" 25 | 26 | 27 | Blob::Blob (char * data_in, size_t size_in) 28 | { 29 | data = data_in; 30 | begin = 0; 31 | end = size_in - 1; /* i.e. size=1 means begin=0 && end=0 */ 32 | } 33 | 34 | bool 35 | Blob::isEmpty () 36 | { 37 | if (! data) return true; 38 | return false; 39 | } 40 | 41 | void 42 | Blob::Dump() 43 | { 44 | size_t length = end - begin +1 ; 45 | hexdump(data + begin, length); 46 | } 47 | 48 | 49 | std::shared_ptr 50 | Blob::Chop(size_t chop_size) 51 | { 52 | if (this->Size() < chop_size) 53 | { 54 | throw OutOfData(); 55 | } 56 | 57 | std::shared_ptr new_blob = std::make_shared(this->data + begin, chop_size); 58 | begin += chop_size; 59 | 60 | return new_blob; 61 | } 62 | 63 | std::shared_ptr 64 | Blob::Chop(size_t min_size, size_t max_size) 65 | { 66 | if (this->Size() < min_size) 67 | { 68 | throw OutOfData(); 69 | } 70 | if (this->Size() >= max_size) 71 | return this->Chop(max_size); 72 | 73 | return this->Chop(this->Size()); 74 | } 75 | 76 | std::vector 77 | Blob::AsByteVector() 78 | { 79 | std::vector res(data + begin, data + end + 1); 80 | return res; 81 | } 82 | 83 | size_t 84 | Blob::Size() 85 | { 86 | return end - begin + 1; 87 | } 88 | 89 | void 90 | Blob::DataDup(char *& data_out, size_t& size_out) 91 | { 92 | size_out = Size(); 93 | data_out = (char *)malloc(size_out); 94 | //FIXME add out of memory check here!!!! 95 | memcpy(data_out, data + begin, size_out); 96 | } 97 | 98 | std::vector 99 | Blob::asVector() 100 | { 101 | std::vector res( (char *)data + begin, (char*)data + begin + Size()); 102 | return res; 103 | } 104 | 105 | /* Do not use in prod. For tests and examples only */ 106 | std::string 107 | Blob::asString() 108 | { 109 | std::string res((char *)data + begin, Size()); 110 | return res; 111 | } 112 | -------------------------------------------------------------------------------- /blobstamper/blob.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef BLOB_H 20 | #define BLOB_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | 28 | class StampBase; 29 | 30 | class Blob 31 | { 32 | private: 33 | char* data; 34 | size_t begin; 35 | size_t end; 36 | public: 37 | Blob(char * data, size_t size); 38 | bool isEmpty (); 39 | size_t Size(); 40 | void Dump(); 41 | 42 | std::vector AsByteVector(); 43 | std::shared_ptr Chop(size_t chop_size); 44 | std::shared_ptr Chop(size_t min_size, size_t max_size); 45 | 46 | void DataDup(char *& data_out, size_t& size_out); 47 | std::vector asVector(); 48 | std::string asString(); /* Should not be used in prod, for tests and examples only*/ 49 | }; 50 | 51 | class OutOfData /*An exception. Experimental for now*/ 52 | { 53 | 54 | }; 55 | 56 | class NotImplemented /*An exception */ 57 | { 58 | 59 | }; 60 | 61 | #endif /*BLOB_H*/ 62 | -------------------------------------------------------------------------------- /blobstamper/blobstamper.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include "blob.h" 20 | #include "stamp.h" 21 | #include "stamp_arithm.h" 22 | #include "stamp_dict.h" 23 | #include "dict.h" 24 | #include "galley.h" 25 | #include "stamp_enumerator.h" 26 | #include "stamp_lottery.h" 27 | #include "stamp_math_op.h" 28 | #include "stamp_text.h" 29 | -------------------------------------------------------------------------------- /blobstamper/dict.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include "dict.h" 20 | 21 | 22 | size_t 23 | DictBase::size() 24 | { 25 | return data.size(); 26 | } 27 | 28 | std::string 29 | DictBase::get(size_t n) 30 | { 31 | return data[n]; 32 | } 33 | 34 | 35 | DictLCAlphaSmall::DictLCAlphaSmall() 36 | { 37 | /* List below was generated with following perl script 38 | 39 | open(my $fh, "/usr/share/dict/british-english-small"); 40 | my $i=0; 41 | while (my $s=<$fh>) 42 | { 43 | chomp $s; 44 | if ($s =~ /^[a-z]+$/) 45 | { 46 | print '"'.$s.'"'.",\n" if $i % 157 == 0; 47 | $i++; 48 | } 49 | } 50 | */ 51 | data = { 52 | "a", 53 | "abundances", 54 | "achieves", 55 | "adjunct", 56 | "affair", 57 | "aired", 58 | "ally", 59 | "amphitheatre", 60 | "annoyance", 61 | "appalled", 62 | "arbitrators", 63 | "artichokes", 64 | "assisting", 65 | "auctioneers", 66 | "awaked", 67 | "balanced", 68 | "barbiturates", 69 | "bawdier", 70 | "beggaring", 71 | "berserk", 72 | "biographies", 73 | "blazer", 74 | "blown", 75 | "bond", 76 | "boundless", 77 | "breaded", 78 | "broadsided", 79 | "buggy", 80 | "burping", 81 | "caches", 82 | "caned", 83 | "cards", 84 | "castoffs", 85 | "cellar", 86 | "chant", 87 | "cheetahs", 88 | "choral", 89 | "citizen", 90 | "cleft", 91 | "clues", 92 | "coined", 93 | "commanding", 94 | "competences", 95 | "concentrate", 96 | "configures", 97 | "conserve", 98 | "contemptuous", 99 | "convertors", 100 | "corpulent", 101 | "counterparts", 102 | "cranking", 103 | "crippled", 104 | "crusades", 105 | "cursing", 106 | "dams", 107 | "debate", 108 | "dedication", 109 | "deign", 110 | "denomination", 111 | "descents", 112 | "detonate", 113 | "differences", 114 | "dirt", 115 | "discouragement", 116 | "dismally", 117 | "dissented", 118 | "divested", 119 | "doorstep", 120 | "dread", 121 | "drunks", 122 | "dying", 123 | "edifices", 124 | "elegant", 125 | "emergency", 126 | "encyclopedia", 127 | "enshrine", 128 | "epitaph", 129 | "eternities", 130 | "excavates", 131 | "exists", 132 | "extends", 133 | "fact", 134 | "fashionably", 135 | "fellow", 136 | "fifteen", 137 | "firms", 138 | "flavourings", 139 | "floured", 140 | "followers", 141 | "forestalled", 142 | "fouler", 143 | "freshens", 144 | "fulfilling", 145 | "galaxy", 146 | "gaudier", 147 | "germs", 148 | "gleam", 149 | "godfather", 150 | "graffiti", 151 | "greened", 152 | "grouping", 153 | "gunshots", 154 | "halved", 155 | "harmonic", 156 | "headrest", 157 | "hems", 158 | "hims", 159 | "holy", 160 | "horrify", 161 | "humans", 162 | "hyphenates", 163 | "illustration", 164 | "impersonated", 165 | "inadequate", 166 | "increase", 167 | "industrious", 168 | "infuriate", 169 | "inquiry", 170 | "insulated", 171 | "intern", 172 | "intuitive", 173 | "irreverence", 174 | "jaws", 175 | "journals", 176 | "kegs", 177 | "kneecap", 178 | "lamentations", 179 | "launder", 180 | "lefts", 181 | "liberated", 182 | "lingoes", 183 | "lobes", 184 | "lords", 185 | "lushes", 186 | "maintaining", 187 | "mannequins", 188 | "mascot", 189 | "meadows", 190 | "men", 191 | "miaows", 192 | "minds", 193 | "misjudge", 194 | "modernise", 195 | "mop", 196 | "mourners", 197 | "muscles", 198 | "narrations", 199 | "neglects", 200 | "nightgowns", 201 | "nostalgia", 202 | "nymph", 203 | "oceans", 204 | "ooze", 205 | "ore", 206 | "outlasted", 207 | "overgrowing", 208 | "overwriting", 209 | "pamper", 210 | "pardon", 211 | "pastiche", 212 | "pearl", 213 | "people", 214 | "perplexity", 215 | "phenomenal", 216 | "pigged", 217 | "pivots", 218 | "pleasured", 219 | "pokers", 220 | "portables", 221 | "powders", 222 | "preface", 223 | "pretzels", 224 | "procedures", 225 | "prom", 226 | "protective", 227 | "puddles", 228 | "purr", 229 | "queasier", 230 | "racquets", 231 | "ranks", 232 | "readable", 233 | "receptionist", 234 | "recuperated", 235 | "refrigerate", 236 | "reiterate", 237 | "reminisces", 238 | "replenishes", 239 | "resemblances", 240 | "resulted", 241 | "reverenced", 242 | "ridiculing", 243 | "robots", 244 | "route", 245 | "rustlers", 246 | "salves", 247 | "savour", 248 | "schoolboy", 249 | "scrounging", 250 | "sedating", 251 | "separates", 252 | "shakiest", 253 | "shined", 254 | "shrewdness", 255 | "significance", 256 | "sitters", 257 | "slakes", 258 | "slogged", 259 | "smoothest", 260 | "snowfalls", 261 | "solidifies", 262 | "sow", 263 | "speeches", 264 | "spongiest", 265 | "squalled", 266 | "stammer", 267 | "stealthy", 268 | "stitches", 269 | "strangers", 270 | "stubbiest", 271 | "subside", 272 | "suitably", 273 | "supplemented", 274 | "swampiest", 275 | "sympathetically", 276 | "taken", 277 | "tattled", 278 | "temperate", 279 | "testicle", 280 | "thirteenths", 281 | "tickles", 282 | "tittered", 283 | "tormentors", 284 | "tragic", 285 | "trappings", 286 | "triggers", 287 | "trusty", 288 | "twigged", 289 | "unburdening", 290 | "undeserved", 291 | "unite", 292 | "unseemly", 293 | "upstream", 294 | "valved", 295 | "verbiage", 296 | "vindicating", 297 | "vortexes", 298 | "want", 299 | "waxes", 300 | "wets", 301 | "whom", 302 | "wipes", 303 | "woolliest", 304 | "wrinkles", 305 | "zanier" 306 | }; 307 | } 308 | -------------------------------------------------------------------------------- /blobstamper/dict.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef DICT_H 20 | #define DICT_H 21 | 22 | 23 | #include 24 | #include 25 | 26 | 27 | class DictBase 28 | { 29 | protected: 30 | std::vector data; 31 | public: 32 | size_t size(); 33 | std::string get(size_t n); // FIXME May be it would be good to use operator[] later. 34 | DictBase() { data = {}; }; 35 | }; 36 | 37 | class DictLCAlphaSmall: public DictBase 38 | { 39 | public: 40 | DictLCAlphaSmall(); 41 | }; 42 | 43 | #endif /* DICT_H */ -------------------------------------------------------------------------------- /blobstamper/galley.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef GALLEY_H 20 | #define GALLEY_H 21 | 22 | #include 23 | #include // for std::reference_wrapper 24 | 25 | #include "stamp.h" 26 | #include "blob.h" 27 | 28 | 29 | class GalleyBase: public virtual StampBase 30 | /* Galley is a kind of stamp, somwhere deep inside. */ 31 | /* You can inherit it, and make a stamp out of it*/ 32 | { 33 | 34 | }; 35 | 36 | class GalleyVectorBase : public GalleyBase 37 | { 38 | protected: 39 | std::shared_ptr stamp; 40 | public: 41 | GalleyVectorBase(std::shared_ptr stamp_arg) : stamp(stamp_arg) {}; 42 | std::vector> extract_internal(std::shared_ptr blob); 43 | int minSize() override; 44 | int maxSize() override {return -1;}; /* Sereies always takes as much data as it can take */ 45 | }; 46 | 47 | 48 | class GalleyVectorStr: public GalleyVectorBase 49 | { 50 | public: 51 | GalleyVectorStr(std::shared_ptr stamp_arg): GalleyVectorBase(stamp_arg) {}; 52 | std::vector ExtractStrVector(std::shared_ptr blob); 53 | }; 54 | 55 | template class GalleyVectorStrStampBase: public GalleyVectorStr, public StampBaseStr 56 | { 57 | public: 58 | GalleyVectorStrStampBase(): GalleyVectorStr(std::make_shared()) {}; 59 | }; 60 | 61 | 62 | class GalleyVectorBin: public GalleyVectorBase 63 | { 64 | public: 65 | GalleyVectorBin(std::shared_ptr stamp_arg): GalleyVectorBase(stamp_arg) {}; 66 | std::vector> ExtractBinVector(std::shared_ptr blob); 67 | }; 68 | 69 | 70 | template class GalleyVectorV: public GalleyVectorBase 71 | { 72 | public: 73 | GalleyVectorV(std::shared_ptr> stamp_arg): GalleyVectorBase(stamp_arg) {}; 74 | std::vector ExtractValuesVector(std::shared_ptr blob); 75 | }; 76 | 77 | 78 | template std::vector 79 | GalleyVectorV::ExtractValuesVector(std::shared_ptr blob) 80 | { 81 | std::vector> blobs = extract_internal(blob); 82 | std::vector res(blobs.size()); 83 | 84 | for (int i = 0; i < blobs.size(); i++) 85 | { 86 | res[i] = std::dynamic_pointer_cast>(stamp)->ExtractValue(blobs[i]); 87 | } 88 | return res; 89 | } 90 | 91 | 92 | class GalleySetBase : public GalleyBase 93 | { 94 | protected: 95 | std::vector> stamps; 96 | public: 97 | GalleySetBase(std::vector> arg) : stamps(arg) {}; 98 | std::vector> extract_internal(std::shared_ptr blob); 99 | void LoadAll(std::shared_ptr blob); 100 | 101 | int minSize() override; 102 | int maxSize() override; 103 | }; 104 | 105 | class GalleySetBin : public GalleySetBase 106 | { 107 | public: 108 | GalleySetBin(std::vector> arg) : GalleySetBase(cast_shared_vector(arg)) {}; 109 | std::vector> ExtractBinSet(std::shared_ptr blob); 110 | }; 111 | 112 | 113 | class GalleySetStr : public GalleySetBase 114 | { 115 | public: 116 | GalleySetStr(std::vector> arg) : GalleySetBase(cast_shared_vector(arg)){}; 117 | std::vector ExtractStrSet(std::shared_ptr blob); 118 | }; 119 | 120 | 121 | #endif /* GALLEY_H */ 122 | -------------------------------------------------------------------------------- /blobstamper/helpers.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | #include 21 | 22 | /* Borrowed from http://www.stahlworks.com/dev/index.php?tool=csc01 */ 23 | /* Code is not nice for support, better rewrite it */ 24 | 25 | void hexdump(void *pAddressIn, long lSize) 26 | { 27 | char szBuf[100]; 28 | long lIndent = 1; 29 | long lOutLen, lIndex, lIndex2, lOutLen2; 30 | long lRelPos; 31 | struct { char *pData; unsigned long lSize; } buf; 32 | unsigned char *pTmp,ucTmp; 33 | unsigned char *pAddress = (unsigned char *)pAddressIn; 34 | 35 | buf.pData = (char *)pAddress; 36 | buf.lSize = lSize; 37 | 38 | while (buf.lSize > 0) 39 | { 40 | pTmp = (unsigned char *)buf.pData; 41 | lOutLen = (int)buf.lSize; 42 | if (lOutLen > 16) 43 | lOutLen = 16; 44 | 45 | // create a 64-character formatted output line: 46 | sprintf(szBuf, " > " 47 | " " 48 | " %08lX", pTmp-pAddress); 49 | lOutLen2 = lOutLen; 50 | 51 | for(lIndex = 1+lIndent, lIndex2 = 53-15+lIndent, lRelPos = 0; 52 | lOutLen2; 53 | lOutLen2--, lIndex += 2, lIndex2++ 54 | ) 55 | { 56 | ucTmp = *pTmp++; 57 | 58 | sprintf(szBuf + lIndex, "%02X ", (unsigned short)ucTmp); 59 | if(!isprint(ucTmp)) ucTmp = '.'; // nonprintable char 60 | szBuf[lIndex2] = ucTmp; 61 | 62 | if (!(++lRelPos & 3)) // extra blank after 4 bytes 63 | { lIndex++; szBuf[lIndex+2] = ' '; } 64 | } 65 | 66 | if (!(lRelPos & 3)) lIndex--; 67 | 68 | szBuf[lIndex ] = '\t'; 69 | szBuf[lIndex+1] = '\t'; 70 | 71 | printf("%s\n", szBuf); 72 | 73 | buf.pData += lOutLen; 74 | buf.lSize -= lOutLen; 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /blobstamper/helpers.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef HELPERS_H 20 | #define HELPERS_H 21 | 22 | #include 23 | #include 24 | 25 | void hexdump(void *pAddressIn, long lSize); 26 | 27 | 28 | /* Set of functions to_string_precise that acts as glibc to_string but 29 | keeps maximym precision for float types, and ads char and signed char type */ 30 | 31 | /* For common int types just use to_string as is*/ 32 | inline std::string 33 | to_string_precise(int __val) 34 | { return std::to_string(__val); } 35 | 36 | inline std::string 37 | to_string_precise(unsigned __val) 38 | { return std::to_string(__val); } 39 | 40 | inline std::string 41 | to_string_precise(long __val) 42 | { return std::to_string(__val); } 43 | 44 | inline std::string 45 | to_string_precise(unsigned long __val) 46 | { return std::to_string(__val); } 47 | 48 | inline std::string 49 | to_string_precise(long long __val) 50 | { return std::to_string(__val); } 51 | 52 | inline std::string 53 | to_string_precise(unsigned long long __val) 54 | { return std::to_string(__val); } 55 | 56 | /* Code grabbed from /usr/include/c++/8/bits/basic_string.h and 57 | adapted both for char and signed char, and float, double etc with 58 | max precision 59 | */ 60 | 61 | inline std::string 62 | to_string_precise(char __val) 63 | { return __gnu_cxx::__to_xstring(&std::vsnprintf, 4 * sizeof(char), 64 | "%d", __val); } 65 | 66 | inline std::string 67 | to_string_precise(signed char __val) 68 | { return __gnu_cxx::__to_xstring(&std::vsnprintf, 4 * sizeof(signed char), 69 | "%d", __val); } 70 | 71 | 72 | /* 999 here is really bad idea, but for now I can't figure out better way*/ 73 | inline std::string 74 | to_string_precise(float __val) 75 | { 76 | const int __n = 77 | __gnu_cxx::__numeric_traits::__max_exponent10 + 999 + 20; 78 | return __gnu_cxx::__to_xstring(&std::vsnprintf, __n, 79 | "%.999g", __val); 80 | } 81 | 82 | inline std::string 83 | to_string_precise(double __val) 84 | { 85 | const int __n = 86 | __gnu_cxx::__numeric_traits::__max_exponent10 + 999 + 20; 87 | return __gnu_cxx::__to_xstring(&std::vsnprintf, __n, 88 | "%.999g", __val); 89 | } 90 | 91 | inline std::string 92 | to_string_precise(long double __val) 93 | { 94 | const int __n = 95 | __gnu_cxx::__numeric_traits::__max_exponent10 + 999 + 20; 96 | return __gnu_cxx::__to_xstring(&std::vsnprintf, __n, 97 | "%.999g", __val); 98 | } 99 | 100 | 101 | namespace std 102 | { 103 | template using ref_vector = vector>; 104 | } 105 | 106 | 107 | template class sized_ptr 108 | { 109 | private: 110 | T* _ptr{nullptr}; 111 | size_t _size; 112 | public: 113 | 114 | operator T*() const {return _ptr;}; 115 | size_t size() {return _size;}; 116 | sized_ptr(T* ptr, size_t size): _ptr{ptr}, _size{size} {}; 117 | ~sized_ptr() {if (_ptr) free(_ptr);}; 118 | }; 119 | 120 | template class VLATO_ptr 121 | { 122 | private: 123 | T* _ptr{nullptr}; 124 | size_t _length; 125 | size_t _offset; 126 | public: 127 | 128 | operator T*() const {return _ptr;}; 129 | operator sized_ptr() {sized_ptr res(_ptr,size()); _ptr=NULL; return res;}; 130 | 131 | size_t length() {return _length;}; 132 | size_t offset() {return _offset;}; 133 | size_t size() {return _offset + _length * sizeof(ArrayT);}; 134 | 135 | VLATO_ptr(size_t offsrt, size_t length); 136 | VLATO_ptr(T* ptr, size_t offset, size_t length): _ptr{ptr}, _offset{offset}, _length{length} {}; 137 | ~VLATO_ptr() {if (_ptr) free(_ptr);} 138 | }; 139 | 140 | 141 | template 142 | VLATO_ptr::VLATO_ptr(size_t offset, size_t length) 143 | { 144 | _ptr = (T*) malloc( offset + sizeof(ArrayT) * length); 145 | _length = length; 146 | _offset = offset; 147 | } 148 | 149 | template 150 | std::vector> cast_shared_vector(std::vector> v) 151 | { 152 | std::vector> res; 153 | for(auto e : v) 154 | { 155 | auto p = std::dynamic_pointer_cast(e); 156 | res.push_back(p); 157 | } 158 | return res; 159 | } 160 | 161 | #endif /*HELPERS_H*/ 162 | -------------------------------------------------------------------------------- /blobstamper/oracle.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include"oracle.h" 22 | 23 | size_t 24 | OracleProportion(ORACLE_TYPE oracle, size_t min, size_t max) 25 | { 26 | /* Sorry explanation is in Russian. PR translation if you can */ 27 | /* Считаем пропорацию, с округлением вниз. 28 | * Диапазон увиличиваем на единицу, чтобы хвост диапазона пресказания при 29 | * округлении вниз как раз попадал в последний элемент целевого диапозона. 30 | * Разброс предсказания увеличиваем на единицу, так чтобы ровно на конец 31 | * хвоста диапазона предсказания не попасть никогда и тогда он не округлиться 32 | * в max + 1*/ 33 | size_t delta = max - min + 1; 34 | size_t res = floor(((float) oracle) / ((float) ORACLE_MAX + 1) * delta); 35 | return min + res; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /blobstamper/oracle.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef STAMP_ORACLE_H 20 | #define STAMP_ORACLE_H 21 | 22 | #include 23 | #include 24 | 25 | #define ORACLE_TYPE unsigned short int 26 | #define ORACLE_STAMP StampArithm 27 | #define ORACLE_SIZE sizeof(ORACLE_TYPE) 28 | #define ORACLE_MAX std::numeric_limits::max() 29 | 30 | size_t OracleProportion(ORACLE_TYPE oracle, size_t min, size_t max); 31 | 32 | #endif /* STAMP_ORACLE_H */ 33 | 34 | -------------------------------------------------------------------------------- /blobstamper/stamp.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | #include "blob.h" 26 | #include "stamp.h" 27 | 28 | 29 | void 30 | StampBase::Load(std::shared_ptr blob) 31 | { 32 | 33 | if (minSize() > blob->Size()) 34 | { 35 | throw OutOfData(); 36 | } 37 | 38 | size_t res_size; 39 | if (isUnbounded()) 40 | { 41 | res_size = blob->Size(); 42 | } else 43 | { 44 | res_size = maxSize(); 45 | if (res_size > blob->Size()) 46 | res_size = blob->Size(); 47 | } 48 | bitten_blob = blob->Chop(res_size); 49 | } 50 | -------------------------------------------------------------------------------- /blobstamper/stamp.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef STAMP_H 20 | #define STAMP_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "helpers.h" 28 | #include "blob.h" 29 | 30 | 31 | class StampBase 32 | { 33 | protected: 34 | std::shared_ptr bitten_blob; 35 | bool is_recursive = 0; 36 | bool is_in_recursion = 0; 37 | public: 38 | virtual int minSize() = 0; 39 | virtual int maxSize() = 0; 40 | 41 | void Load(std::shared_ptr blob); 42 | 43 | bool isFixedSize() { return minSize() == maxSize(); } 44 | bool isVariated() { return !isFixedSize() && !isUnbounded(); } 45 | bool isUnbounded() { return maxSize() == -1; } 46 | virtual bool isRecursive() {return is_recursive;} 47 | }; 48 | 49 | class StampRecursive: public virtual StampBase 50 | { 51 | protected: 52 | // bool is_in_recursion = 0; 53 | public: 54 | StampRecursive() {is_recursive = 1;} 55 | virtual ssize_t minSizeNR() = 0; 56 | }; 57 | 58 | 59 | class StampBaseStr: public virtual StampBase 60 | { 61 | public: 62 | virtual std::string ExtractStr(std::shared_ptr blob) = 0; 63 | std::string UnloadStr() {return ExtractStr(bitten_blob);}; 64 | }; 65 | 66 | 67 | class StampBaseBin: public virtual StampBase 68 | { 69 | public: 70 | virtual std::vector ExtractBin(std::shared_ptr blob) = 0; 71 | std::vector UnloadBin() {return ExtractBin(bitten_blob);}; 72 | }; 73 | 74 | 75 | template class StampBasePV: public StampBaseBin 76 | { 77 | public: 78 | virtual sized_ptr ExtractPValue(std::shared_ptr blob) = 0;/* Should be defined by derived classes*/ 79 | sized_ptr UnloadPValue() {return ExtractPValue(bitten_blob);}; 80 | virtual std::vector ExtractBin(std::shared_ptr blob) override; 81 | }; 82 | 83 | /* If we have pointer and size, we can represent it std::vector for free */ 84 | template std::vector 85 | StampBasePV::ExtractBin(std::shared_ptr blob) 86 | { 87 | sized_ptr sp = this->ExtractPValue(blob); 88 | T* pval = sp; 89 | std::vector v((char *) pval, (char *) pval + sp.size()); 90 | return v; 91 | } 92 | 93 | template class StampBaseV: public StampBasePV, 94 | public virtual StampBase //FIXME I do not understand why do we need it here, but wihtout it, it does not build 95 | { 96 | public: 97 | virtual T ExtractValue(std::shared_ptr blob) = 0;/* Should be defined by derived classes*/ 98 | T UnloadValue() {return ExtractValue(bitten_blob);}; 99 | 100 | virtual std::vector ExtractBin(std::shared_ptr blob) override; 101 | virtual sized_ptr ExtractPValue(std::shared_ptr blob) override; 102 | }; 103 | 104 | template sized_ptr 105 | StampBaseV::ExtractPValue(std::shared_ptr blob) 106 | { 107 | T* p = (T*) malloc(sizeof(T)); 108 | *p = ExtractValue(blob); 109 | sized_ptr res(p,sizeof(T)); 110 | return res; 111 | } 112 | 113 | /* If we have value, we can represent it as binary */ 114 | template std::vector 115 | StampBaseV::ExtractBin(std::shared_ptr blob) 116 | { 117 | T value = this->ExtractValue(blob); 118 | std::vector v((char *) &value, (char *) &value + sizeof(T)); 119 | return v; 120 | } 121 | 122 | #endif /* STAMP_H */ 123 | -------------------------------------------------------------------------------- /blobstamper/stamp_arithm.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include "blob.h" 20 | #include "stamp.h" 21 | #include "stamp_arithm.h" 22 | 23 | -------------------------------------------------------------------------------- /blobstamper/stamp_arithm.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef STAMP_ARITHM_H 20 | #define STAMP_ARITHM_H 21 | 22 | #include 23 | #include "helpers.h" 24 | #include "stamp.h" 25 | 26 | template class StampArithm: public StampBaseStr, public StampBaseV 27 | { 28 | public: 29 | virtual int minSize() override {return sizeof(T);} 30 | virtual int maxSize() override {return sizeof(T);} 31 | virtual std::string ExtractStr(std::shared_ptr blob) override; 32 | virtual T ExtractValue(std::shared_ptr blob) override; 33 | }; 34 | 35 | template std::string 36 | StampArithm::ExtractStr(std::shared_ptr blob) 37 | { 38 | T value = this->ExtractValue(blob); 39 | return to_string_precise(value); 40 | } 41 | 42 | template T 43 | StampArithm::ExtractValue(std::shared_ptr blob) 44 | { 45 | std::vector v = blob->Chop(sizeof(T))->AsByteVector(); /* Chop out blank of type's size */ 46 | T *pT = (T *) &v[0]; /* And interpret it as value of arithmetic type */ 47 | return *pT; 48 | } 49 | 50 | 51 | #endif /* STAMP_ARITHM_H */ 52 | -------------------------------------------------------------------------------- /blobstamper/stamp_dict.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include "blob.h" 20 | #include "stamp.h" 21 | #include "stamp_arithm.h" 22 | #include "stamp_dict.h" 23 | 24 | int 25 | StampDict::ChooseStampSize(std::shared_ptr dict) 26 | { 27 | if (dict->size() <= UCHAR_MAX + 1) 28 | { 29 | stamp_max_value = UCHAR_MAX; 30 | return 1; 31 | } 32 | if (dict->size() <= USHRT_MAX + 1) 33 | { 34 | stamp_max_value = USHRT_MAX; 35 | return 2; 36 | } 37 | if (dict->size() <= UINT_MAX + 1) 38 | { 39 | stamp_max_value = UINT_MAX; 40 | return 4; 41 | } 42 | stamp_max_value = ULONG_MAX; 43 | return 8; 44 | } 45 | 46 | std::string 47 | StampDict::ExtractStr(std::shared_ptr blob) 48 | { 49 | unsigned long long index_oracle; 50 | 51 | /* Shifting index oracle according to size of dictionary index variable*/ 52 | switch (stamp_size) 53 | { 54 | case 1: 55 | { 56 | index_oracle = stamp8.ExtractValue(blob); 57 | break; 58 | } 59 | case 2: 60 | { 61 | index_oracle = stamp16.ExtractValue(blob); 62 | break; 63 | } 64 | case 4: 65 | { 66 | index_oracle = stamp32.ExtractValue(blob); 67 | break; 68 | } 69 | case 8: 70 | { 71 | index_oracle = stamp64.ExtractValue(blob); 72 | break; 73 | } 74 | default: 75 | printf("StampDict::ExtractStr: Something is really wrong\n"); // FIXME better to throw something here :-) 76 | exit(1); 77 | } 78 | long long actual_index = ((double) index_oracle) / stamp_max_value * dict->size(); 79 | if (actual_index == dict->size()) actual_index--; /* If we hit the boundary step inside a bit*/ 80 | return dict->get(actual_index); 81 | } 82 | -------------------------------------------------------------------------------- /blobstamper/stamp_dict.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef STAMP_DICT_H 20 | #define STAMP_DICT_H 21 | 22 | #include 23 | 24 | #include "blob.h" 25 | #include "stamp.h" 26 | #include "stamp_arithm.h" 27 | #include "dict.h" 28 | #include 29 | 30 | class StampDict: public StampBaseStr 31 | { 32 | protected: 33 | StampArithm stamp8; 34 | StampArithm stamp16; 35 | StampArithm stamp32; 36 | StampArithm stamp64; 37 | int stamp_size; 38 | std::shared_ptr dict; 39 | unsigned long long stamp_max_value; 40 | 41 | int ChooseStampSize(std::shared_ptr dict); 42 | 43 | public: 44 | StampDict(std::shared_ptr dict_arg) : dict(dict_arg), stamp_size(ChooseStampSize(dict_arg)) {}; 45 | std::string ExtractStr(std::shared_ptr blob) override; 46 | int minSize() override {return stamp_size;} 47 | int maxSize() override {return stamp_size;} 48 | }; 49 | 50 | class StampDictLCAlphaSmall: public StampDict 51 | { 52 | public: 53 | StampDictLCAlphaSmall(): StampDict(std::make_shared()) {}; 54 | }; 55 | 56 | 57 | template class StampDictT: public StampDict 58 | { 59 | protected: 60 | std::shared_ptr dict; 61 | public: 62 | StampDictT(): StampDict(dict = std::make_shared()) {}; 63 | }; 64 | 65 | 66 | #endif /* STAMP_DICT_H */ 67 | -------------------------------------------------------------------------------- /blobstamper/stamp_enumerator.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include "stamp_enumerator.h" 20 | 21 | #include"galley.h" 22 | #include"stamp.h" 23 | #include"blob.h" 24 | 25 | 26 | 27 | std::string StampStrEnumerator::ExtractStr(std::shared_ptr blob) 28 | { 29 | std::vector data = ExtractStrVector(blob); 30 | std::string res = ""; 31 | 32 | for (std::string s : data) 33 | { 34 | if (!res.empty()) 35 | { 36 | res += separator; 37 | } 38 | res += s; 39 | } 40 | res = left_bracket + res + right_bracket; 41 | return res; 42 | } 43 | -------------------------------------------------------------------------------- /blobstamper/stamp_enumerator.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef STAMP_ENUMERATOR_H 20 | #define STAMP_ENUMERATOR_H 21 | 22 | #include "galley.h" 23 | #include "stamp.h" 24 | #include "blob.h" 25 | 26 | #include 27 | 28 | class StampStrEnumerator: public GalleyVectorStr, public StampBaseStr 29 | { 30 | protected: 31 | std::shared_ptr stamp_str; 32 | const std::string separator; 33 | const std::string left_bracket; 34 | const std::string right_bracket; 35 | public: 36 | StampStrEnumerator(std::shared_ptr arg_stamp, 37 | const std::string arg_sep, 38 | const std::string arg_l, 39 | const std::string arg_r 40 | ): 41 | stamp_str(arg_stamp), 42 | separator(arg_sep), 43 | left_bracket(arg_l), 44 | right_bracket(arg_r), 45 | GalleyVectorStr(arg_stamp) {}; 46 | 47 | virtual std::string ExtractStr(std::shared_ptr blob) override; 48 | 49 | }; 50 | 51 | 52 | #endif //STAMP_ENUMERATOR_H 53 | -------------------------------------------------------------------------------- /blobstamper/stamp_json.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "stamp_json.h" 25 | #include "oracle.h" 26 | 27 | PoolPickerStamp::PoolPickerStamp(std::vector> new_pool) 28 | : pool{new_pool} 29 | { 30 | for (auto stamp : pool) 31 | { 32 | std::weak_ptr wp = stamp; 33 | weak_pool.push_back(wp); 34 | } 35 | } 36 | 37 | bool 38 | PoolPickerStamp::isRecursive() 39 | { 40 | if (is_recursive || is_in_recursion) 41 | return true; 42 | is_in_recursion = true; 43 | for (auto stamp : weak_pool) 44 | { 45 | if (stamp.lock()->isRecursive()) 46 | { 47 | is_recursive = true; // Once recursive -- recursive forever. 48 | is_in_recursion = false; 49 | return true; 50 | } 51 | } 52 | is_in_recursion = false; 53 | return false; 54 | } 55 | 56 | std::string 57 | PoolPickerStamp::ExtractStr(std::shared_ptr blob) 58 | { 59 | static ORACLE_STAMP stamp_oracle; 60 | ORACLE_TYPE oracle = stamp_oracle.ExtractValue(blob); 61 | 62 | std::vector> target_pool; 63 | std::vector> unbounded_pool; 64 | 65 | for (auto stamp_w : weak_pool) 66 | { 67 | auto stamp = stamp_w.lock(); 68 | if (stamp->minSize() <= blob->Size()) 69 | { 70 | target_pool.push_back(stamp_w); 71 | if (stamp->maxSize() == -1 || stamp->maxSize() >= blob->Size()) 72 | { 73 | unbounded_pool.push_back(stamp_w); 74 | } 75 | } 76 | } 77 | if (! unbounded_pool.empty()) 78 | target_pool = unbounded_pool; 79 | 80 | if (target_pool.empty()) 81 | { 82 | /* Most probably we are in out of data situation. Check it 83 | * and throw an exception. Or abort if something goes wrong 84 | * 85 | * Normally caller should not call this method when he is out of data 86 | * so it is OK to do the check at the end, when get no success, and not 87 | * in the beginning. 88 | */ 89 | if (blob->Size() < this->minSize()) 90 | { 91 | throw OutOfData(); 92 | } else 93 | { 94 | fprintf(stderr, "Something is really wrong in PoolPickerStamp::ExtractStr\n"); 95 | abort(); 96 | } 97 | } 98 | 99 | size_t index = OracleProportion(oracle, 0, target_pool.size() - 1); 100 | return target_pool[index].lock()->ExtractStr(blob); 101 | } 102 | 103 | int 104 | PoolPickerStamp::minSize() 105 | { 106 | int res = INT_MAX / 2; 107 | /* Do not check is_recursive here: even if stamp is known to be recursive we 108 | * still should iterate all his non-recursive children to find real minimal 109 | * size */ 110 | if (is_in_recursion) 111 | return res; 112 | is_in_recursion = true; /* Do not use isRecursive() inside as it uses same flag*/ 113 | for(auto stamp : weak_pool) 114 | { 115 | int candidat = stamp.lock()->minSize(); 116 | if (res > candidat) 117 | res = candidat; 118 | } 119 | is_in_recursion = false; 120 | if (res == INT_MAX / 2) 121 | return INT_MAX / 2; 122 | res += ORACLE_SIZE; 123 | return res; 124 | } 125 | 126 | int 127 | PoolPickerStamp::maxSize() 128 | { 129 | int res = 0; 130 | if (is_recursive || is_in_recursion) 131 | return -1; 132 | is_in_recursion = true; /* Do not use isRecursive() inside as it uses same flag*/ 133 | for (auto stamp : weak_pool) 134 | { 135 | int candidat = stamp.lock()->maxSize(); 136 | if (candidat == -1) 137 | { 138 | is_in_recursion = false; 139 | return -1; 140 | } 141 | if (res < candidat) 142 | res = candidat; 143 | } 144 | is_in_recursion = false; 145 | res += ORACLE_SIZE; 146 | return res; 147 | } 148 | 149 | void 150 | PoolPickerStamp::add_weak(std::shared_ptr stamp) 151 | { 152 | weak_pool.push_back(stamp); 153 | } 154 | 155 | std::string 156 | StampJSONString::ExtractStr(std::shared_ptr blob) 157 | { 158 | std::string res = "\"" + StampDictT::ExtractStr(blob) +"\""; 159 | return res; 160 | } 161 | 162 | 163 | std::string 164 | StampJSONHashEl::ExtractStr(std::shared_ptr blob) 165 | { 166 | std::string n = stamp_name->ExtractStr(blob); 167 | std::string v = stamp_value->ExtractStr(blob); 168 | return n + ": " + v; 169 | } 170 | 171 | void null_deleter(StampJSON *) {} 172 | 173 | StampJSON::StampJSON() 174 | : PoolPickerStamp({}) 175 | { 176 | stamp_i = std::make_shared(); 177 | stamp_f = std::make_shared(); 178 | stamp_s = std::make_shared(); 179 | 180 | // FIXME Так не надо делеать!!!! null_deleter -- зло. 181 | stamp_a = std::make_shared(std::shared_ptr(this, null_deleter)); 182 | stamp_h = std::make_shared(std::shared_ptr(this, null_deleter)); 183 | add_weak(stamp_i); 184 | add_weak(stamp_f); 185 | add_weak(stamp_s); 186 | 187 | add_weak(stamp_a); 188 | add_weak(stamp_h); 189 | } 190 | -------------------------------------------------------------------------------- /blobstamper/stamp_json.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef STAMP_JSON_H 20 | #define STAMP_JSON_H 21 | 22 | #include 23 | #include 24 | 25 | #include "stamp.h" 26 | #include "stamp_arithm.h" 27 | #include "stamp_dict.h" 28 | #include "stamp_enumerator.h" 29 | 30 | class PoolPickerStamp: public virtual StampBaseStr 31 | { 32 | protected: 33 | std::vector> pool; 34 | std::vector> weak_pool; 35 | 36 | public: 37 | PoolPickerStamp(std::vector> new_pool); 38 | // ~PoolPickerStamp() {fprintf(stderr, "DESTROY!\n");}; 39 | 40 | std::string ExtractStr(std::shared_ptr blob) override; 41 | virtual void add_weak(std::shared_ptr stamp); 42 | virtual bool isRecursive(); 43 | virtual int minSize() override; 44 | virtual int maxSize() override; 45 | }; 46 | 47 | class StampJSONInt: public virtual StampArithm 48 | { 49 | }; 50 | 51 | class StampJSONFloat: public virtual StampArithm 52 | { 53 | }; 54 | 55 | class StampJSONString: public virtual StampDictT 56 | { 57 | protected: 58 | public: 59 | std::string ExtractStr(std::shared_ptr blob) override; 60 | virtual int minSize() override {return 8;}; 61 | virtual int maxSize() override {return 8;}; 62 | 63 | }; 64 | 65 | class StampJSONArray: public StampStrEnumerator 66 | { 67 | private: 68 | public: 69 | StampJSONArray(std::shared_ptr picker): 70 | StampStrEnumerator(picker, ", ", "[", "]") {}; 71 | }; 72 | 73 | class StampJSONHashEl: public StampBaseStr 74 | { 75 | private: 76 | std::shared_ptr stamp_name; 77 | std::shared_ptr stamp_value; 78 | public: 79 | StampJSONHashEl(std::shared_ptr picker): 80 | stamp_value(picker), stamp_name(std::make_shared()) {}; 81 | virtual int minSize() override {return stamp_name->minSize() + stamp_value->minSize();}; 82 | virtual int maxSize() override {return -1;}; 83 | std::string ExtractStr(std::shared_ptr blob) override; 84 | }; 85 | 86 | class StampJSONHash: public StampStrEnumerator 87 | { 88 | private: 89 | std::shared_ptr stamp_el; 90 | public: 91 | StampJSONHash(std::shared_ptr picker): 92 | StampStrEnumerator(stamp_el = std::make_shared(picker), ", ", "{", "}") {}; 93 | }; 94 | 95 | 96 | class StampJSON: public PoolPickerStamp 97 | { 98 | private: 99 | std::shared_ptr stamp_s; 100 | std::shared_ptr stamp_i; 101 | std::shared_ptr stamp_f; 102 | std::shared_ptr stamp_a; 103 | std::shared_ptr stamp_h; 104 | 105 | public: 106 | StampJSON(); 107 | }; 108 | 109 | #endif /* STAMP_DICT_H */ 110 | 111 | -------------------------------------------------------------------------------- /blobstamper/stamp_lottery.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postgrespro/libblobstamper/18e28f3b1aebc5c774bc3a39be98e9367a34dcfd/blobstamper/stamp_lottery.cpp -------------------------------------------------------------------------------- /blobstamper/stamp_lottery.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef STAMP_LOTTERY_H 20 | #define STAMP_LOTTERY_H 21 | 22 | #include 23 | template class StampLottery: public StampT 24 | { 25 | protected: 26 | std::ref_vector stamps; 27 | int oracle_size; 28 | int init_oracle_size(std::ref_vector stamps_arg); 29 | 30 | int stored_min; 31 | int init_stored_min(std::ref_vector stamps_arg); 32 | int stored_max; 33 | int init_stored_max(std::ref_vector stamps_arg); 34 | 35 | public: 36 | StampLottery(std::ref_vector stamps_arg): stamps(stamps_arg), 37 | oracle_size(init_oracle_size(stamps_arg)), 38 | stored_min(init_stored_min(stamps_arg)), 39 | stored_max(init_stored_max(stamps_arg)) {}; 40 | StampLottery(): stored_min(-1), stored_max(-2), oracle_size(1) {}; 41 | 42 | virtual int minSize() override; 43 | virtual int maxSize() override; 44 | 45 | virtual bool soft_maxsize_filter(StampT &stamp, int data_size) {return true;}; /* Allow to skip stamps that would leave to much data unused. But not active here*/ 46 | 47 | virtual std::string ExtractStr(std::shared_ptr blob) override; 48 | void Append(StampT & stamp); 49 | }; 50 | 51 | 52 | template class StampLottery4Recursion: public StampLottery 53 | { 54 | public: 55 | StampLottery4Recursion(std::ref_vector stamps_arg): StampLottery(stamps_arg) {}; 56 | StampLottery4Recursion(): StampLottery() {}; 57 | virtual bool soft_maxsize_filter(StampT &stamp, int data_size) override; 58 | }; 59 | 60 | 61 | template bool 62 | StampLottery4Recursion:: 63 | soft_maxsize_filter(StampT &stamp, int data_size) 64 | { 65 | if (stamp.isUnbounded() || // Unbounded is always ok 66 | stamp.maxSize() > data_size || // Variated that can consume all data is ok 67 | stamp.minSize() + stamp.maxSize() > data_size // Fixed or variated stamp that lefts less data then it's min size will also do 68 | ) 69 | return true; 70 | return false; 71 | } 72 | 73 | template int 74 | StampLottery:: 75 | init_stored_min(std::ref_vector stamps_arg) 76 | { 77 | int min = std::numeric_limits::max(); 78 | 79 | for (StampT & stamp : stamps) 80 | { 81 | 82 | if (min > stamp.minSize()) 83 | min = stamp.minSize(); 84 | } 85 | return min; 86 | } 87 | 88 | template int 89 | StampLottery:: 90 | init_stored_max(std::ref_vector stamps_arg) 91 | { 92 | int max = 0; 93 | 94 | for (StampT & stamp : stamps) 95 | { 96 | if (stamp.maxSize() == -1) 97 | return -1; 98 | 99 | if (max < stamp.maxSize()) 100 | max = stamp.maxSize(); 101 | } 102 | return max; 103 | } 104 | 105 | 106 | template int 107 | StampLottery::init_oracle_size(std::ref_vector stamps_arg) 108 | { 109 | unsigned long size = stamps_arg.size(); 110 | if (size < std::numeric_limits::max()) 111 | return 1; 112 | if (size < std::numeric_limits::max()) 113 | return 2; 114 | if (size < std::numeric_limits::max()) 115 | return 4; 116 | return 8; 117 | } 118 | 119 | 120 | 121 | /* StampLottery is used for recustion. Lottery contains trams that uses this very lottery 122 | Calculating sizes on fly leads to infinite recrsion. So we calculate sizes when lottery 123 | item is added, and use stored value, when it is needed */ 124 | 125 | template int 126 | StampLottery::minSize() 127 | { 128 | return stored_min + oracle_size; 129 | } 130 | 131 | template int 132 | StampLottery::maxSize() 133 | { 134 | if (stored_max == -1) 135 | return -1; 136 | return stored_max + oracle_size; 137 | } 138 | 139 | 140 | template std::string 141 | StampLottery::ExtractStr(std::shared_ptr blob) 142 | { 143 | unsigned long oracle; 144 | unsigned long oracle_max; 145 | 146 | switch (oracle_size) 147 | { 148 | case 1: 149 | { 150 | StampArithm stamp; 151 | oracle = stamp.ExtractValue(blob); 152 | oracle_max = std::numeric_limits::max(); 153 | break; 154 | } 155 | case 2: 156 | { 157 | StampArithm stamp; 158 | oracle = stamp.ExtractValue(blob); 159 | oracle_max = std::numeric_limits::max(); 160 | break; 161 | } 162 | case 4: 163 | { 164 | StampArithm stamp; 165 | oracle = stamp.ExtractValue(blob); 166 | oracle_max = std::numeric_limits::max(); 167 | break; 168 | } 169 | case 8: 170 | { 171 | StampArithm stamp; 172 | oracle = stamp.ExtractValue(blob); 173 | oracle_max = std::numeric_limits::max(); 174 | break; 175 | } 176 | default: 177 | abort(); // Should never get here 178 | } 179 | 180 | /* Actually we use only stamps that short enogh to consume blob's available data*/ 181 | std::ref_vector actual_stamps; 182 | for(StampT & stamp : stamps) 183 | { 184 | if(blob->Size() < stamp.minSize()) // Skip all stamps that dose not fit 185 | continue; 186 | if (soft_maxsize_filter(stamp, blob->Size())) 187 | actual_stamps.push_back(stamp); 188 | } 189 | if (actual_stamps.empty()) 190 | { 191 | // Add just everything that fits 192 | for(StampT & stamp : stamps) 193 | { 194 | if(blob->Size() < stamp.minSize()) // Skip all stamps that dose not fit 195 | continue; 196 | actual_stamps.push_back(stamp); 197 | } 198 | } 199 | 200 | if (actual_stamps.empty()) 201 | throw OutOfData(); // This should never happen 202 | 203 | long long index = ((double) oracle) / oracle_max * actual_stamps.size(); 204 | if ( index == actual_stamps.size()) index--; /* If we hit the boundary step inside a bit*/ 205 | 206 | StampT& stamp = actual_stamps[index]; 207 | return stamp.ExtractStr(blob); 208 | } 209 | 210 | 211 | template void 212 | StampLottery::Append(StampT & stamp) 213 | { 214 | if (stamp.maxSize() == -1) 215 | { 216 | stored_max = -1; 217 | } else 218 | { 219 | if (stamp.maxSize() > stored_max) /* this case includes case when stored_max have not beed initialized (==-2)*/ 220 | stored_max = stamp.maxSize(); 221 | } 222 | 223 | if (stored_min == -1) /* stored_min have not been initializes*/ 224 | stored_min = stamp.minSize(); 225 | 226 | if (stamp.minSize() < stored_min) 227 | stored_min = stamp.minSize(); 228 | 229 | stamps.push_back(stamp); 230 | oracle_size = init_oracle_size(stamps); 231 | } 232 | 233 | #endif // STAMP_LOTTERY_H 234 | -------------------------------------------------------------------------------- /blobstamper/stamp_math_op.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | #include"stamp_math_op.h" 21 | 22 | std::string 23 | StampMathUnaryOp::ExtractStr(std::shared_ptr blob) 24 | { 25 | return op_name + "(" + stamp->ExtractStr(blob) + ")"; 26 | } 27 | 28 | 29 | std::string 30 | StampMathBinaryOp::ExtractStr(std::shared_ptr blob) 31 | { 32 | std::vector> blobs = extract_internal(blob); 33 | return (std::string)"(" + stamp1->ExtractStr(blobs[0]) + " " + op_name + " " + stamp2->ExtractStr(blobs[1]) + ")"; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /blobstamper/stamp_math_op.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef STAMP_MATH_OP_H 20 | #define STAMP_MATH_OP_H 21 | 22 | #include "blob.h" 23 | #include "stamp.h" 24 | #include "galley.h" 25 | 26 | 27 | class StampMathUnaryOp: public StampBaseStr 28 | { 29 | protected: 30 | std::string op_name; 31 | std::shared_ptr stamp; 32 | public: 33 | virtual std::string ExtractStr(std::shared_ptr blob) override; 34 | StampMathUnaryOp(std::string arg_op_name, std::shared_ptr arg_stamp): op_name(arg_op_name), stamp(arg_stamp) {}; 35 | virtual int maxSize() override {return -1;}; 36 | virtual int minSize() override {return stamp->minSize();}; 37 | }; 38 | 39 | 40 | 41 | class StampMathBinaryOp: public StampBaseStr, public GalleySetBase 42 | { 43 | protected: 44 | std::string op_name; 45 | std::shared_ptr stamp1; 46 | std::shared_ptr stamp2; 47 | public: 48 | virtual std::string ExtractStr(std::shared_ptr blob) override; 49 | StampMathBinaryOp(std::string arg_op_name, 50 | std::shared_ptr arg_stamp1, 51 | std::shared_ptr arg_stamp2): 52 | GalleySetBase({arg_stamp1, arg_stamp2}), 53 | op_name(arg_op_name), 54 | stamp1(arg_stamp1), 55 | stamp2(arg_stamp2) {}; 56 | virtual int maxSize() override {return -1;}; 57 | 58 | }; 59 | 60 | #endif // STAMP_MATH_OP_H 61 | -------------------------------------------------------------------------------- /blobstamper/stamp_text.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include "stamp_text.h" 20 | 21 | std::string 22 | StampTextPulp::ExtractStr(std::shared_ptr blob) 23 | { 24 | std::vector data = blob->Chop(minSize(), maxSize())->AsByteVector(); 25 | 26 | std::vector::iterator the_iterator; 27 | 28 | the_iterator = data.begin(); 29 | std::string res; 30 | while (the_iterator != data.end()) 31 | { 32 | if (*the_iterator == '\0') { *the_iterator = ' '; } 33 | res.push_back(*the_iterator++); 34 | } 35 | 36 | return res; 37 | } 38 | 39 | std::string StampTextPulpWords::ExtractStr(std::shared_ptr blob) 40 | { 41 | std::vector data = ExtractStrVector(blob); 42 | std::string res = ""; 43 | 44 | for(std::string s : data) 45 | { 46 | if (!res.empty()) 47 | { 48 | res+=" "; 49 | } 50 | res+= s; 51 | } 52 | return res; 53 | } 54 | 55 | std::string StampTextDictWords::ExtractStr(std::shared_ptr blob) 56 | { 57 | std::vector data = ExtractStrVector(blob); 58 | std::string res = ""; 59 | 60 | for(std::string s : data) 61 | { 62 | if (!res.empty()) 63 | { 64 | res+=" "; 65 | } 66 | res+= s; 67 | } 68 | return res; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /blobstamper/stamp_text.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef STAMP_TEXT_H 20 | #define STAMP_TEXT_H 21 | 22 | 23 | #include "galley.h" 24 | 25 | #include "stamp_dict.h" 26 | 27 | class StampTextPulp: public StampBaseStr 28 | { 29 | public: 30 | virtual int minSize() override { return 1; } 31 | virtual int maxSize() override { return -1; } 32 | std::string ExtractStr(std::shared_ptr blob) override; 33 | }; 34 | 35 | class StampTextPulpWords: public GalleyVectorStrStampBase 36 | { 37 | public: 38 | virtual std::string ExtractStr(std::shared_ptr blob) override; 39 | }; 40 | 41 | class StampTextDictWords: public GalleyVectorStrStampBase 42 | { 43 | public: 44 | virtual std::string ExtractStr(std::shared_ptr blob) override; 45 | }; 46 | 47 | #endif /* STAMP_TEXT_H */ 48 | -------------------------------------------------------------------------------- /console_demo/Makefile: -------------------------------------------------------------------------------- 1 | 2 | BLOBSTAMPER_SRC := $(wildcard ../blobstamper/*.cpp) 3 | BLOBSTAMPER_OBJ := $(addsuffix .o, $(basename $(BLOBSTAMPER_SRC))) 4 | 5 | EXAMPLES_SRC = $(wildcard *.cpp) 6 | EXAMPLES_BIN = $(basename $(EXAMPLES_SRC)) 7 | 8 | 9 | all: $(EXAMPLES_BIN) 10 | 11 | build-libtappp: 12 | $(MAKE) -C ../libtappp 13 | 14 | %: %.cpp $(BLOBSTAMPER_OBJ) $(BLOBSTAMPER_PG_OBJ) $(WRAPPERS_OBJ) 15 | $(CXX) $(CXXFLAGS) -I.. -o $@ $< $(BLOBSTAMPER_OBJ) 16 | 17 | clean: 18 | -rm $(EXAMPLES_BIN) 2>/dev/null 19 | 20 | .PHONY: test clean all 21 | 22 | -------------------------------------------------------------------------------- /console_demo/_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PLAY_TIME="1m 2s" 4 | SAMPLE_SIZE=256 5 | 6 | dd if=/dev/random of=buf count=1 bs=$SAMPLE_SIZE 7 | 8 | 9 | tmux split-window -v "watch -d -n0.1 -c './pulp2json buf| jq -C'"; 10 | tmux split-window -h "watch -d -n0.1 -c 'hexdump buf'" 11 | 12 | tmux new-window -P -d -n pseudo-fuzz "watch -d -n0.1 './pseudo_fuzz.pl'" 13 | tmux new-window -P -d -n watchdog "sleep $PLAY_TIME; tmux kill-session" 14 | 15 | 16 | -------------------------------------------------------------------------------- /console_demo/pseudo_fuzz.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Path::Tiny; 5 | use bytes; 6 | 7 | die "file 'buf' not found" unless -e "buf"; 8 | 9 | my $size = -s "buf"; 10 | 11 | my $offset = int(rand($size)); 12 | my $value = int(rand(256)); 13 | 14 | open(my $out, '+<:raw', 'buf'); 15 | seek($out, $offset, 0); 16 | print $out pack('C', $value); 17 | 18 | close $out; 19 | 20 | -------------------------------------------------------------------------------- /console_demo/pulp2json.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "blobstamper/stamp_json.h" 24 | #include 25 | 26 | #include 27 | 28 | 29 | long GetFileSize(std::string filename) 30 | { 31 | struct stat stat_buf; 32 | int rc = stat(filename.c_str(), &stat_buf); 33 | return rc == 0 ? stat_buf.st_size : -1; 34 | } 35 | 36 | int 37 | main(int argc, char *argv[]) 38 | { 39 | if (argc<2) 40 | { 41 | fprintf(stderr, "Please specify input file name as first argument\n"); 42 | exit(1); 43 | } 44 | std::string file_name = argv[1]; 45 | 46 | std::fstream f{file_name}; 47 | if (!f) 48 | { 49 | std::cerr << "Unable to open file '"< buffer (file_size,0); 55 | f.read(&buffer[0], buffer.size()); 56 | 57 | auto blob = std::make_shared(&buffer[0], buffer.size()); 58 | 59 | auto stamp_j = std::make_shared(); 60 | std::string s = stamp_j->ExtractStr(blob); 61 | 62 | printf("%s\n", s.c_str()); 63 | 64 | } 65 | -------------------------------------------------------------------------------- /console_demo/run.sh: -------------------------------------------------------------------------------- 1 | tmux new-session "bash _run.sh" 2 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | 2 | BLOBSTAMPER_SRC := $(wildcard ../blobstamper/*.cpp) 3 | BLOBSTAMPER_OBJ := $(addsuffix .o, $(basename $(BLOBSTAMPER_SRC))) 4 | 5 | EXAMPLES_SRC = $(wildcard *.cpp) 6 | EXAMPLES_BIN = $(basename $(EXAMPLES_SRC)) 7 | 8 | 9 | all: $(EXAMPLES_BIN) 10 | 11 | build-libtappp: 12 | $(MAKE) -C ../libtappp 13 | 14 | %: %.cpp $(BLOBSTAMPER_OBJ) $(BLOBSTAMPER_PG_OBJ) $(WRAPPERS_OBJ) 15 | $(CXX) $(CXXFLAGS) -I.. -o $@ $< $(BLOBSTAMPER_OBJ) 16 | 17 | clean: 18 | -rm $(EXAMPLES_BIN) 2>/dev/null 19 | 20 | .PHONY: test clean all 21 | 22 | -------------------------------------------------------------------------------- /examples/example01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | int main() 10 | { 11 | char data[] = "abcde"; 12 | auto blob = std::make_shared(data, strlen(data)); 13 | StampArithm stamp; 14 | std::string s = stamp.ExtractStr(blob); 15 | 16 | std::cout << "Stamp minSize: " << stamp.minSize() << "\n"; 17 | std::cout << "Stamp maxSize: " << stamp.maxSize() << "\n"; 18 | std::cout << "Extracted value: " << s <<"\n"; 19 | std::cout << "Remaining blob: " << blob->asString() << "\n"; 20 | } 21 | -------------------------------------------------------------------------------- /examples/example01a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | int main() 10 | { 11 | char data[] = "abcde"; 12 | auto blob = std::make_shared(data, strlen(data)); 13 | StampArithm stamp; 14 | stamp.Load(blob); 15 | 16 | std::string s = stamp.UnloadStr(); 17 | 18 | std::cout << "Stamp minSize: " << stamp.minSize() << "\n"; 19 | std::cout << "Stamp maxSize: " << stamp.maxSize() << "\n"; 20 | std::cout << "Extracted value: " << s <<"\n"; 21 | std::cout << "Remaining blob: " << blob->asString() << "\n"; 22 | } 23 | -------------------------------------------------------------------------------- /examples/example02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | int main() 10 | { 11 | char data[] = "abcdefjhi"; 12 | auto blob = std::make_shared(data, strlen(data)); 13 | StampArithm stamp; 14 | 15 | std::string s = stamp.ExtractStr(blob); 16 | std::vector vec= stamp.ExtractBin(blob); 17 | short int i = stamp.ExtractValue(blob); 18 | 19 | sized_ptr spi = stamp.ExtractPValue(blob); 20 | short int *pi = spi; 21 | 22 | std::cout << "String value: '" << s <<"'\n"; 23 | std::cout << "Bin value: '" << vec[0] <<"', '" << vec[1] <<"'\n"; 24 | std::cout << "Value: " << i <<"\n"; 25 | std::cout << "PValue: " << *pi <<"\n"; 26 | } 27 | -------------------------------------------------------------------------------- /examples/example02a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | int main() 10 | { 11 | char data[] = "abcdefjhi"; 12 | auto blob = std::make_shared(data, strlen(data)); 13 | StampArithm stamp1; 14 | StampArithm stamp2; 15 | StampArithm stamp3; 16 | StampArithm stamp4; 17 | 18 | stamp1.Load(blob); 19 | stamp2.Load(blob); 20 | stamp3.Load(blob); 21 | stamp4.Load(blob); 22 | 23 | std::string s = stamp1.UnloadStr(); 24 | std::vector vec= stamp2.UnloadBin(); 25 | short int i = stamp3.UnloadValue(); 26 | 27 | sized_ptr spi = stamp4.UnloadPValue(); 28 | short int *pi = spi; 29 | 30 | std::cout << "String value: '" << s <<"'\n"; 31 | std::cout << "Bin value: '" << vec[0] <<"', '" << vec[1] <<"'\n"; 32 | std::cout << "Value: " << i <<"\n"; 33 | std::cout << "PValue: " << *pi <<"\n"; 34 | } 35 | -------------------------------------------------------------------------------- /examples/example03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | class StampPoint3D: public StampBaseStr 10 | { 11 | protected: 12 | StampArithm stampX, stampY, stampZ; 13 | public: 14 | virtual int minSize() override; 15 | virtual int maxSize() override; 16 | virtual std::string ExtractStr(std::shared_ptr blob) override; 17 | }; 18 | 19 | int StampPoint3D::minSize() 20 | { 21 | return stampX.minSize() + stampY.minSize() + stampZ.minSize(); 22 | } 23 | 24 | int StampPoint3D::maxSize() 25 | { 26 | return stampX.maxSize() + stampY.maxSize() + stampZ.maxSize(); 27 | } 28 | 29 | std::string StampPoint3D::ExtractStr(std::shared_ptr blob) 30 | { 31 | std::string X,Y,Z; 32 | X = stampX.ExtractStr(blob); 33 | Y = stampY.ExtractStr(blob); 34 | Z = stampZ.ExtractStr(blob); 35 | return "(" + X + ", " + Y + ", " + Z + ")"; 36 | } 37 | 38 | 39 | int main() 40 | { 41 | char data[] = "abcdef"; 42 | auto blob = std::make_shared(data, strlen(data)); 43 | StampPoint3D stamp; 44 | 45 | std::string s = stamp.ExtractStr(blob); 46 | 47 | std::cout << "String value: '" << s <<"'\n"; 48 | } 49 | -------------------------------------------------------------------------------- /examples/example04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | typedef struct Point3D 10 | { 11 | short int X; 12 | short int Y; 13 | short int Z; 14 | } Point3D; 15 | 16 | class StampPoint3D: public StampBaseStr, public StampBaseV 17 | { 18 | protected: 19 | StampArithm stampX, stampY, stampZ; 20 | public: 21 | virtual int minSize() override; 22 | virtual int maxSize() override; 23 | virtual std::string ExtractStr(std::shared_ptr blob) override; 24 | virtual Point3D ExtractValue(std::shared_ptr blob) override; 25 | }; 26 | 27 | int StampPoint3D::minSize() 28 | { 29 | return stampX.minSize() + stampY.minSize() + stampZ.minSize(); 30 | } 31 | 32 | int StampPoint3D::maxSize() 33 | { 34 | return stampX.maxSize() + stampY.maxSize() + stampZ.maxSize(); 35 | } 36 | 37 | std::string StampPoint3D::ExtractStr(std::shared_ptr blob) 38 | { 39 | std::string X,Y,Z; 40 | X = stampX.ExtractStr(blob); 41 | Y = stampY.ExtractStr(blob); 42 | Z = stampZ.ExtractStr(blob); 43 | return "(" + X + ", " + Y + ", " + Z + ")"; 44 | } 45 | 46 | Point3D StampPoint3D::ExtractValue(std::shared_ptr blob) 47 | { 48 | Point3D res; 49 | res.X = stampX.ExtractValue(blob); 50 | res.Y = stampY.ExtractValue(blob); 51 | res.Z = stampZ.ExtractValue(blob); 52 | return res; 53 | } 54 | 55 | int main() 56 | { 57 | char data[] = "abcdef" "abcdef"; 58 | auto blob = std::make_shared(data, strlen(data)); 59 | StampPoint3D stamp; 60 | 61 | std::string s = stamp.ExtractStr(blob); 62 | Point3D p = stamp.ExtractValue(blob); 63 | 64 | std::cout << "String value: '" << s <<"'\n"; 65 | std::cout << "Point3D value: (" << p.X << ", " << p.Y << ", " << p.Z << ")\n"; 66 | } 67 | -------------------------------------------------------------------------------- /examples/example05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | typedef struct Point3D 10 | { 11 | short int X; 12 | short int Y; 13 | short int Z; 14 | } Point3D; 15 | 16 | class StampPoint3D: public StampBaseStr, public StampBaseV 17 | { 18 | protected: 19 | StampArithm stampX, stampY, stampZ; 20 | public: 21 | virtual int minSize() override; 22 | virtual int maxSize() override; 23 | virtual std::string ExtractStr(std::shared_ptr blob) override; 24 | virtual Point3D ExtractValue(std::shared_ptr blob) override; 25 | }; 26 | 27 | int StampPoint3D::minSize() 28 | { 29 | return stampX.minSize() + stampY.minSize() + stampZ.minSize(); 30 | } 31 | 32 | int StampPoint3D::maxSize() 33 | { 34 | return stampX.maxSize() + stampY.maxSize() + stampZ.maxSize(); 35 | } 36 | 37 | std::string StampPoint3D::ExtractStr(std::shared_ptr blob) 38 | { 39 | std::string X,Y,Z; 40 | X = stampX.ExtractStr(blob); 41 | Y = stampY.ExtractStr(blob); 42 | Z = stampZ.ExtractStr(blob); 43 | return "(" + X + ", " + Y + ", " + Z + ")"; 44 | } 45 | 46 | Point3D StampPoint3D::ExtractValue(std::shared_ptr blob) 47 | { 48 | Point3D res; 49 | res.X = stampX.ExtractValue(blob); 50 | res.Y = stampY.ExtractValue(blob); 51 | res.Z = stampZ.ExtractValue(blob); 52 | return res; 53 | } 54 | 55 | int main() 56 | { 57 | char data[] = "abcdef" "abcdef" "ABCDEF" "012345"; 58 | auto blob = std::make_shared(data, strlen(data)); 59 | auto stamp = std::make_shared(); 60 | 61 | GalleyVectorStr galley(stamp); 62 | 63 | std::vector res = galley.ExtractStrVector(blob); 64 | 65 | for(std::string s : res) 66 | std::cout << "'" << s <<"'\n"; 67 | } 68 | -------------------------------------------------------------------------------- /examples/example06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | typedef struct Point3D 10 | { 11 | short int X; 12 | short int Y; 13 | short int Z; 14 | } Point3D; 15 | 16 | class StampPoint3D: public StampBaseStr, public StampBaseV 17 | { 18 | protected: 19 | StampArithm stampX, stampY, stampZ; 20 | public: 21 | virtual int minSize() override; 22 | virtual int maxSize() override; 23 | virtual std::string ExtractStr(std::shared_ptr blob) override; 24 | virtual Point3D ExtractValue(std::shared_ptr blob) override; 25 | }; 26 | 27 | int StampPoint3D::minSize() 28 | { 29 | return stampX.minSize() + stampY.minSize() + stampZ.minSize(); 30 | } 31 | 32 | int StampPoint3D::maxSize() 33 | { 34 | return stampX.maxSize() + stampY.maxSize() + stampZ.maxSize(); 35 | } 36 | 37 | std::string StampPoint3D::ExtractStr(std::shared_ptr blob) 38 | { 39 | std::string X,Y,Z; 40 | X = stampX.ExtractStr(blob); 41 | Y = stampY.ExtractStr(blob); 42 | Z = stampZ.ExtractStr(blob); 43 | return "(" + X + ", " + Y + ", " + Z + ")"; 44 | } 45 | 46 | Point3D StampPoint3D::ExtractValue(std::shared_ptr blob) 47 | { 48 | Point3D res; 49 | res.X = stampX.ExtractValue(blob); 50 | res.Y = stampY.ExtractValue(blob); 51 | res.Z = stampZ.ExtractValue(blob); 52 | return res; 53 | } 54 | 55 | int main() 56 | { 57 | char data[] = "abcdef" "abcdef" "ABCDEF" "012345"; 58 | auto blob = std::make_shared(data, strlen(data)); 59 | auto stamp = std::make_shared(); 60 | 61 | GalleyVectorV galley(stamp); 62 | std::vector res = galley.ExtractValuesVector(blob); 63 | 64 | Point3D *p = &res[0]; 65 | int p_size = res.size(); 66 | 67 | for(int i=0; i 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | typedef struct Point3D 10 | { 11 | short int X; 12 | short int Y; 13 | short int Z; 14 | } Point3D; 15 | 16 | class StampPoint3D: public StampBaseStr, public StampBaseV 17 | { 18 | protected: 19 | StampArithm stampX, stampY, stampZ; 20 | public: 21 | virtual int minSize() override; 22 | virtual int maxSize() override; 23 | virtual std::string ExtractStr(std::shared_ptr blob) override; 24 | virtual Point3D ExtractValue(std::shared_ptr blob) override; 25 | }; 26 | 27 | int StampPoint3D::minSize() 28 | { 29 | return stampX.minSize() + stampY.minSize() + stampZ.minSize(); 30 | } 31 | 32 | int StampPoint3D::maxSize() 33 | { 34 | return stampX.maxSize() + stampY.maxSize() + stampZ.maxSize(); 35 | } 36 | 37 | std::string StampPoint3D::ExtractStr(std::shared_ptr blob) 38 | { 39 | std::string X,Y,Z; 40 | X = stampX.ExtractStr(blob); 41 | Y = stampY.ExtractStr(blob); 42 | Z = stampZ.ExtractStr(blob); 43 | return "(" + X + ", " + Y + ", " + Z + ")"; 44 | } 45 | 46 | Point3D StampPoint3D::ExtractValue(std::shared_ptr blob) 47 | { 48 | Point3D res; 49 | res.X = stampX.ExtractValue(blob); 50 | res.Y = stampY.ExtractValue(blob); 51 | res.Z = stampZ.ExtractValue(blob); 52 | return res; 53 | } 54 | 55 | 56 | class StampPolyLine3D: public GalleyVectorStr, public StampBaseStr 57 | { 58 | public: 59 | StampPolyLine3D(): GalleyVectorStr(std::make_shared()) {}; 60 | virtual std::string ExtractStr(std::shared_ptr blob) override; 61 | }; 62 | 63 | 64 | std::string StampPolyLine3D::ExtractStr(std::shared_ptr blob) 65 | { 66 | std::vector data = ExtractStrVector(blob); 67 | std::string res = ""; 68 | 69 | for(std::string s : data) 70 | { 71 | if (!res.empty()) 72 | { 73 | res+=", "; 74 | } 75 | res+= s; 76 | } 77 | res = "(" + res + ")"; 78 | return res; 79 | } 80 | 81 | int main() 82 | { 83 | char data[] = "abcdef" "abcdef" "ABCDEF" "012345"; 84 | auto blob = std::make_shared(data, strlen(data)); 85 | StampPolyLine3D stamp; 86 | 87 | std::string s = stamp.ExtractStr(blob); 88 | std::cout << s <<"\n"; 89 | } 90 | -------------------------------------------------------------------------------- /examples/example08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | typedef struct Point3D 10 | { 11 | short int X; 12 | short int Y; 13 | short int Z; 14 | } Point3D; 15 | 16 | class StampPoint3D: public StampBaseStr, public StampBaseV 17 | { 18 | protected: 19 | StampArithm stampX, stampY, stampZ; 20 | public: 21 | virtual int minSize() override; 22 | virtual int maxSize() override; 23 | virtual std::string ExtractStr(std::shared_ptr blob) override; 24 | virtual Point3D ExtractValue(std::shared_ptr blob) override; 25 | }; 26 | 27 | int StampPoint3D::minSize() 28 | { 29 | return stampX.minSize() + stampY.minSize() + stampZ.minSize(); 30 | } 31 | 32 | int StampPoint3D::maxSize() 33 | { 34 | return stampX.maxSize() + stampY.maxSize() + stampZ.maxSize(); 35 | } 36 | 37 | std::string StampPoint3D::ExtractStr(std::shared_ptr blob) 38 | { 39 | std::string X,Y,Z; 40 | X = stampX.ExtractStr(blob); 41 | Y = stampY.ExtractStr(blob); 42 | Z = stampZ.ExtractStr(blob); 43 | return "(" + X + ", " + Y + ", " + Z + ")"; 44 | } 45 | 46 | Point3D StampPoint3D::ExtractValue(std::shared_ptr blob) 47 | { 48 | Point3D res; 49 | res.X = stampX.ExtractValue(blob); 50 | res.Y = stampY.ExtractValue(blob); 51 | res.Z = stampZ.ExtractValue(blob); 52 | return res; 53 | } 54 | 55 | 56 | class StampPolyLine3D: public StampStrEnumerator 57 | { 58 | public: 59 | StampPolyLine3D(): StampStrEnumerator(std::make_shared(), ",", "(",")") {}; 60 | }; 61 | 62 | 63 | 64 | int main() 65 | { 66 | char data[] = "abcdef" "abcdef" "ABCDEF" "012345"; 67 | auto blob = std::make_shared(data, strlen(data)); 68 | 69 | StampPolyLine3D stamp; 70 | 71 | 72 | std::string s = stamp.ExtractStr(blob); 73 | std::cout << s <<"\n"; 74 | } 75 | -------------------------------------------------------------------------------- /examples/exampleZZ.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | 11 | class BinaryOp: public StampBaseStr, public GalleySetBase 12 | { 13 | protected: 14 | std::string op_name; 15 | StampBaseStr &stamp1; 16 | StampBaseStr &stamp2; 17 | public: 18 | virtual std::string ExtractStr(std::shared_ptr blob) override; 19 | BinaryOp(std::string arg_op_name, StampBaseStr& arg_stamp1, StampBaseStr& arg_stamp2) : 20 | GalleySetBase({arg_stamp1, arg_stamp2}), 21 | op_name(arg_op_name), 22 | stamp1(arg_stamp1), 23 | stamp2(arg_stamp2) {}; 24 | 25 | virtual int maxSize() override {return -1;}; 26 | 27 | }; 28 | 29 | std::string 30 | BinaryOp::ExtractStr(std::shared_ptr blob) 31 | { 32 | std::vector> blobs = this->extract_internal(blob); 33 | return (std::string)"(" + stamp1.ExtractStr(blobs[0]) + " "+ op_name + " " + stamp2.ExtractStr(blobs[1]) + ")"; 34 | } 35 | 36 | std::vector ops = {"+","-","*","/","^"}; 37 | 38 | int main() 39 | { 40 | // char data[] = "abcdef" "abcdef" "ABCDEF" "012345" "sdfaskdlfjalsfjdlasjfaksdjfgkwuergkwhfdaksjdfgaskuyrgfaelkrgfsaldjfgakyefgrkweugyfaksjskdfsd"; 41 | 42 | char data[] = 43 | "\x051\x04E\x05A\x018\x043\x00C\x039\x0DC\x069\x0AC\x009\x014\x05A\x0B2\x07F\x078\x021\x09F\x08B\x0B1\x07E\x060\x01F\x04A\x0D1\x071\x05C\x04F\x011\x0D0\x061\x0FB\x037\x077\x081\x00C\x059\x00A\x037\x02F\x061\x04A\x065\x06D" 44 | "\x003\x04A\x0BC\x099\x0F8\x00B\x0F7\x020\x0C9\x074\x065\x008\x0B4\x010\x008\x0B4\x08B\x070\x0E1\x0EF\x026\x04F\x0F9\x0AB\x01C\x06C\x035\x018\x086\x037\x0E7\x02F\x044\x057\x001\x020\x006\x0DD\x0C4\x059\x0D1\x0C5\x0A9\x005" 45 | "\x038\x078\x0E2\x053\x01D\x0F0\x06E\x0E6\x018\x0B6\x048\x0F1\x0DC\x061\x092\x0FB\x0D3\x010\x0B8\x042\x0CA\x0C1\x0E3\x075\x077\x099\x093\x0CC\x063\x0F0\x09E\x044\x03D\x070\x01A\x089\x035\x032\x04A\x0BD\x082\x0BF\x0EA\x002" 46 | "\x043\x071\x079\x0A0\x068\x0B3\x0D9\x029\x0E9\x045\x0A2\x027\x003\x02E\x0E2\x01F\x007\x0BD\x0CF\x00A\x03E\x00D\x044\x024\x0FA\x0DB\x03D\x033\x036\x011\x081\x070\x0B6\x04A\x083\x061\x05F\x0AE\x0F0\x0C5\x0A1\x010\x05B\x003" 47 | "\x061\x0C3\x0D2\x078\x0BD\x0F8\x0E1\x04B\x02F\x0D9\x093\x09F\x00E\x0D6\x03A\x070\x0F8\x052\x013\x0EE\x062\x0C0\x027\x0E5\x07B\x07B\x09E\x05D\x074\x068\x0C6\x0CD\x04E\x022\x03B\x04E\x0E7\x0E7\x0EE\x0EC\x015\x02C\x0FA\x050" 48 | "\x033\x042\x0E6\x0BF\x028\x002\x052\x096\x033\x057\x0D8\x082\x053\x06E\x0BD\x0C6\x0ED\x015\x036\x09E\x03B\x0BE\x0F3\x068\x0BD\x0EC\x0D3\x0E9\x023\x029\x081\x0CF\x0F8\x02D\x081\x049\x007\x0CC\x005\x004\x062\x040\x0E0\x0D0" 49 | "\x0CD\x062\x0D4\x09B\x007\x001\x037\x020\x059\x0AC\x0FC\x0A4\x095\x049\x05F\x04C\x0DA\x02B\x0E8\x0E9\x0BF\x029\x01F\x0D0\x06B\x06E\x0F5\x005\x075\x07B\x036\x0D2\x054\x078\x0D3\x059\x077\x09A\x0D5\x079\x0AC\x034\x030\x0FD" 50 | "\x006\x079\x022\x0F4\x0ED\x059\x080\x081\x08F\x0A6\x08F\x042\x08A\x0CC\x030\x019\x094\x0F3\x062\x00B\x08A\x0D4\x0F8\x0F3\x03B\x049\x0D1\x06D\x0C6\x067\x006\x0D3\x023\x035\x053\x0C1\x0F8\x068\x0EF\x0AD\x0C7\x053\x004\x02C" 51 | "\x092\x087\x075\x0B0\x0F0\x0F7\x0D9\x04C\x0C7\x0A2\x095\x02B\x038\x02E\x0F2\x005\x0BE\x0CD\x02E\x093\x08A\x088\x063\x07D\x0F1\x08A\x002\x0D0\x0B9\x05C\x008\x066\x002\x044\x0B0\x08F\x041\x009\x06F\x0E5\x08B\x068\x0EB\x05A"; 52 | 53 | auto blob = std::make_shared(data, strlen(data)); 54 | 55 | StampArithm stampс; 56 | 57 | auto dict = std::make_shared(); 58 | StampDict stamp_dict(dict); 59 | 60 | StampLottery4Recursion stamp_lot({stampс, stamp_dict}); 61 | 62 | for(std::string op_name : ops) 63 | { 64 | BinaryOp *stamp_bi = new BinaryOp(op_name, stamp_lot, stamp_lot); 65 | stamp_lot.Append(*stamp_bi); 66 | } 67 | 68 | for(int i=stamp_lot.minSize(); i<=strlen(data);i++) 69 | { 70 | auto blob2 = std::make_shared(data, i); 71 | std::cout << i << " " << stamp_lot.ExtractStr(blob2) <<"\n"; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /libtappp/.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | script: 3 | - make 4 | - make test 5 | compiler: 6 | - gcc 7 | - clang 8 | -------------------------------------------------------------------------------- /libtappp/Makefile: -------------------------------------------------------------------------------- 1 | CXX ?= g++ 2 | ACK := ack 3 | LIB := libtap++.so 4 | WARNINGS := -Wall -Wextra -Weffc++ 5 | DEBUG := -ggdb3 -DDEBUG 6 | CXXFLAGS := $(DEBUG) $(WARNINGS) -fPIC 7 | PREFIX := /usr/local 8 | LIBRARY_VAR := LD_LIBRARY_PATH 9 | TEST_GOALS := t/00-sanity.t 10 | 11 | all: $(LIB) 12 | 13 | $(LIB): src/tap++.cpp include/tap++/tap++.h 14 | $(CXX) -shared -o $@ -Wl,-soname,$(LIB) $(CXXFLAGS) -Iinclude/ src/*.cpp 15 | 16 | t/%.t: t/%.cpp $(LIB) 17 | $(CXX) $(CXXFLAGS) -Iinclude -o $@ $< -L. -ltap++ 18 | 19 | testbuild: $(TEST_GOALS) 20 | 21 | test: $(TEST_GOALS) 22 | @echo run_tests.pl $(TEST_GOALS) 23 | @$(LIBRARY_VAR)=. ./run_tests.pl $(TEST_GOALS) 24 | 25 | clean: 26 | -rm -r $(LIB) $(wildcard t/*.t) 2>/dev/null 27 | 28 | testclean: 29 | -rm t/*.t 2>/dev/null 30 | 31 | again: clean all 32 | 33 | install: $(LIB) 34 | cp --preserve=timestamps libtap++.so $(PREFIX)/lib/ 35 | cp -dR --preserve=timestamps,links include/tap++/ $(PREFIX)/include/ 36 | chmod a+x $(PREFIX)/include/tap++ 37 | chmod -R a+r $(PREFIX)/include/tap++ 38 | chmod a+rx $(PREFIX)/lib/libtap++.so 39 | 40 | uninstall: 41 | -rm $(PREFIX)/lib/libtap++.so 42 | -rm -r $(PREFIX)/include/tap++ 43 | 44 | .PHONY: todo install test testbuild clean testclean all uninstall 45 | 46 | todo: 47 | @for i in FIX''ME XX''X TO''DO; do echo -n "$$i: "; $(ACK) $$i | wc -l; done; 48 | 49 | apicount: libtap++.so 50 | @echo -n "Number of entries: " 51 | @nm libtap++.so -C --defined-only | egrep -i " [TW] TAP::" | wc -l 52 | -------------------------------------------------------------------------------- /libtappp/README.md: -------------------------------------------------------------------------------- 1 | # NAME 2 | 3 | libtap++ - C++ unit tests for the Test Anything Protocol 4 | 5 | # SYNOPSIS 6 | 7 | #include 8 | #include 9 | 10 | using namespace TAP; 11 | 12 | int foo(int ronkle = 1) { 13 | return ronkle; 14 | } 15 | 16 | std::string bar() { 17 | return "a string"; 18 | } 19 | 20 | int main() { 21 | plan(4); 22 | ok(true, "This test passes"); 23 | is(foo(), 1, "foo() should be 1"); 24 | is(bar(), "a string", "bar() should be \"a string\""); 25 | 26 | TODO="Foo is not completely implemented"; 27 | is(foo(2), 5, "foo(2) should be 5"); 28 | TODO=""; 29 | 30 | return exit_status(); 31 | } 32 | 33 | # DESCRIPTION 34 | 35 | `libtap++` is a TAP producer for C++ programs. 36 | 37 | # HISTORY 38 | 39 | libtap++ was originally developed as a part of 40 | [libperl++](https://github.com/Leont/libperl--) project by Leon Timmermans 41 | 42 | Then forked into separate [libtap++](https://github.com/cbab/libtappp) 43 | project by Christian Babeux 44 | 45 | Now libtap++ us supported by Nikolay Shaplov at 46 | [https://gitlab.com/dhyannataraj/libtappp](https://gitlab.com/dhyannataraj/libtappp) 47 | 48 | # FUNCTIONS 49 | 50 | All functions and variables are defined in the `TAP` namespace. 51 | 52 | ## I love it when a plan comes together 53 | 54 | Before anything else, you need a testing plan. This basically declares 55 | how many tests your script is going to run to protect against premature 56 | failure. 57 | 58 | - **plan()** 59 | 60 | void plan(int number_of_tests); 61 | void plan(skip_all, const std::string& reason=""); 62 | void plan(no_plan); 63 | 64 | The function `plan` is used to indicate the plan of your test run. Usually you 65 | will just give it the number of tests as argument. 66 | 67 | Alternatively, you can give it the `skip_all` or `no_plan` constants as 68 | arguments. The first means you will not run the tests at all, the second means 69 | you will run an unknown number of tests (the latter is not recommended). 70 | 71 | - **done\_testing()** 72 | 73 | void done_testing(); 74 | void done_testing(int number_of_tests); 75 | 76 | If you don't know how many tests you're going to run, you can issue the plan 77 | when you're done running tests. 78 | 79 | number\_of\_tests is the same as plan(), it's the number of tests you expected to 80 | run. You can omit this, in which case the number of tests you ran doesn't 81 | matter, just the fact that your tests ran to conclusion. 82 | 83 | This is safer than and replaces the "no\_plan" plan. 84 | 85 | ## Test names 86 | 87 | By convention, each test is assigned a number in order. This is 88 | largely done automatically for you. However, it's often very useful to 89 | assign a name to each test. Which would you rather see: 90 | 91 | ok 4 92 | not ok 5 93 | ok 6 94 | 95 | or 96 | 97 | ok 4 - basic multi-variable 98 | not ok 5 - simple exponential 99 | ok 6 - force == mass * acceleration 100 | 101 | The later gives you some idea of what failed. It also makes it easier 102 | to find the test in your script, simply search for "simple 103 | exponential". 104 | 105 | All test functions take a name argument. It's optional, but highly 106 | suggested that you use it. 107 | 108 | ## I'm ok, you're not ok. 109 | 110 | The basic purpose of this module is to print out either "ok #" or "not 111 | ok #" depending on if a given test succeeded or failed. Everything 112 | else is just gravy. 113 | 114 | All of the following print "ok" or "not ok" depending on if the test 115 | succeeded or failed. They all also return true or false, 116 | respectively. 117 | 118 | - **ok()** 119 | 120 | bool ok(bool condition, const std::string& test_name = ""); 121 | 122 | `ok` is the basic test expression in TAP. It simply evaluates any expression, 123 | for example, _got == expected_, taking a true value to mean that the test 124 | passed and a false value to mean that the test failed. 125 | 126 | `test_name` is a very short description of the test that will be printed out. 127 | It makes it very easy to find a test in your script when it fails and gives 128 | others an idea of your intentions. `test_name` is optional, but we very 129 | strongly encourage its use. 130 | 131 | - **is()** 132 | - **isnt()** 133 | 134 | template bool is(const T& got, const U& expected, std::string& test_name = ""); 135 | template bool isnt(const T& got, const U& expected, std::string& test_name = ""); 136 | 137 | Similar to ok(), is() and isnt() compare their two arguments 138 | with `==` and `!=` respectively and use the result of that to 139 | determine if the test succeeded or failed. So these: 140 | 141 | # Is the ultimate answer 42? 142 | is( ultimate_answer(), 42, "Meaning of Life" ); 143 | 144 | # foo isn't empty 145 | isnt( foo, "", "Got some foo" ); 146 | 147 | are similar to these: 148 | 149 | ok( ultimate_answer() == 42, "Meaning of Life" ); 150 | ok( foo != "", "Got some foo" ); 151 | 152 | (Mnemonic: "This is that." "This isn't that.") 153 | 154 | So why use these? They produce better diagnostics on failure. ok() cannot know 155 | what you are testing for (beyond the name), but is() and isnt() know what the 156 | test was and why it failed. For example this test: 157 | 158 | std::string foo("waffle"), bar("yarblokos"); 159 | is( foo, bar, 'Is foo the same as bar?' ); 160 | 161 | Will produce something like this: 162 | 163 | not ok 17 - Is foo the same as bar? 164 | # Failed test 'Is foo the same as bar?' 165 | # got: 'waffle' 166 | # expected: 'yarblokos' 167 | 168 | - **pass()** 169 | - **fail()** 170 | 171 | bool pass(const std::string& test_name = ""); 172 | bool fail(const std::string& test_name = ""); 173 | 174 | Sometimes you just want to say that the tests have passed. Usually 175 | the case is you've got some complicated condition that is difficult to 176 | wedge into an ok(). In this case, you can simply use pass() (to 177 | declare the test ok) or fail (for not ok). They are synonyms for 178 | ok(true, test\_name) and ok(false, test\_name). 179 | 180 | Use these very, very, very sparingly. 181 | 182 | ## Conditional testing 183 | 184 | - **skip()** 185 | 186 | void skip(int number, const std::string& reason = ""); 187 | 188 | `skip` tells the TAP harness that you're skipping a _number_ of tests for the 189 | given _reason_. Note that you have to do the skipping yourself. 190 | 191 | - **TODO** 192 | 193 | { 194 | todo_guard why; 195 | TODO="why" 196 | my_tests_here ... 197 | } 198 | 199 | `TODO` is a global string variable that tells TAP harness the reason 200 | the current test is expected to fail. You set TODO before a block of 201 | tests that you expect to fail and then unset it afterwards. When TODO 202 | is the empty string, then the harness considers that there is no 203 | reason for the test to fail. However, when TODO is non-empty, any 204 | failing test is not counted against the test suite and any succeeding 205 | test is reported as an unexpected success. 206 | 207 | The nice part about todo tests, as opposed to simply commenting out a 208 | block of tests, is it's like having a programmatic todo list. You know 209 | how much work is left to be done, you're aware of what bugs there are, 210 | and you'll know immediately when they're fixed. 211 | 212 | Note that TODO manipulates a global variable. Thus, you should be 213 | careful to set it to "" before going to another section of the 214 | program. An easy mistake to make is to have a failing section of code 215 | that throws an exception, taking you out of the current scope without 216 | resetting TODO. To make it easier to deal with this in a thread-safe 217 | manner, the todo\_guard class is provided. Objects of this class will 218 | reset TODO when they fall out of scope. 219 | 220 | ## Diagnostics 221 | 222 | If you pick the right test function, you'll usually get a good idea of 223 | what went wrong when it failed. But sometimes it doesn't work out 224 | that way. So here we have ways for you to write your own diagnostic 225 | messages which are safer than just `print STDERR`. 226 | 227 | - **diag** 228 | 229 | diag(diagnostic_message...); 230 | 231 | Prints a diagnostic message which is guaranteed not to interfere with 232 | test output. The arguments are simply concatenated together. 233 | 234 | Returns false, so as to preserve failure. 235 | 236 | Handy for this sort of thing: 237 | 238 | ok( has_user("foo"), "There's a foo user" ) or 239 | diag("Since there's no foo, check that /etc/bar is set up right"); 240 | 241 | which would produce: 242 | 243 | not ok 42 - There's a foo user 244 | # Failed test 'There's a foo user' 245 | # Since there's no foo, check that /etc/bar is set up right. 246 | 247 | You might remember `ok() or diag()` with the mnemonic `open() or 248 | die()`. 249 | 250 | **NOTE** The exact formatting of the diagnostic output is still 251 | changing, but it is guaranteed that whatever you throw at it it won't 252 | interfere with the test. 253 | 254 | - **note** 255 | 256 | note(diagnostic_message...); 257 | 258 | Like diag(), except the message will not be seen when the test is run 259 | in a harness. It will only be visible in the verbose TAP stream. 260 | 261 | Handy for putting in notes which might be useful for debugging, but 262 | don't indicate a problem. 263 | 264 | note("Tempfile is ", tempfile); 265 | 266 | `diag` simply catenates its arguments to the error output, while `note` 267 | prints diagnostics to the TAP stream. 268 | 269 | - **set\_output()** 270 | - **set\_error()** 271 | 272 | void set_output(std::ofstream& new_output); 273 | void set_error(std::ofstream& new_error); 274 | 275 | These set the filehandle of the TAP stream and the error stream. They default 276 | to `std::cout` and `std::cerr`, respectively. These can only be set before any 277 | output is written to them. 278 | 279 | ## Ending a test run 280 | 281 | - **exit\_status()** 282 | 283 | If all your tests passed, Test::Builder will exit with zero (which is 284 | normal). If anything failed it will exit with how many failed. If 285 | you run less (or more) tests than you planned, the missing (or extras) 286 | will be considered failures. If the test died, even after having 287 | successfully completed all its tests, it will still be considered a failure 288 | and will exit with 255. 289 | 290 | So the exit codes are... 291 | 292 | 0 all tests successful 293 | 255 test died or all passed but wrong # of tests run 294 | any other number how many failed (including missing or extras) 295 | 296 | If you fail more than 254 tests, it will be reported as 254. 297 | 298 | - **bail\_out()** 299 | 300 | int exit_status(); 301 | void bail_out(const std::string& reason); 302 | 303 | **bail\_out** terminates the current test program with exit code 255, indicating 304 | to the test harness that all subsequent testing should halt. Typically this 305 | is used to indicate that testing cannot continue at all. 306 | 307 | # SEE ALSO 308 | 309 | [http://www.testanything.org](http://www.testanything.org) 310 | 311 | [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 312 | harness, respectively. This library is modeled after Test::More. 313 | 314 | # AUTHORS 315 | 316 | Leon Timmermans wrote `libtap++`. He stole much of this documentation from 317 | Test::More. Mike Pomraning also contributed this documentation. 318 | 319 | # COPYRIGHT 320 | 321 | Copyright (c) 2008, 2009, 2010 Leon Timmermans. 322 | 323 | See the LICENSE file for details. 324 | -------------------------------------------------------------------------------- /libtappp/README.pod: -------------------------------------------------------------------------------- 1 | =pod 2 | 3 | =head1 NAME 4 | 5 | libtap++ - C++ unit tests for the Test Anything Protocol 6 | 7 | =head1 SYNOPSIS 8 | 9 | #include 10 | #include 11 | 12 | using namespace TAP; 13 | 14 | int foo(int ronkle = 1) { 15 | return ronkle; 16 | } 17 | 18 | std::string bar() { 19 | return "a string"; 20 | } 21 | 22 | int main() { 23 | plan(4); 24 | ok(true, "This test passes"); 25 | is(foo(), 1, "foo() should be 1"); 26 | is(bar(), "a string", "bar() should be \"a string\""); 27 | 28 | TODO="Foo is not completely implemented"; 29 | is(foo(2), 5, "foo(2) should be 5"); 30 | TODO=""; 31 | 32 | return exit_status(); 33 | } 34 | 35 | =head1 DESCRIPTION 36 | 37 | C is a TAP producer for C++ programs. 38 | 39 | =head1 HISTORY 40 | 41 | libtap++ was originally developed as a part of 42 | L project by Leon Timmermans 43 | 44 | Then forked into separate L 45 | project by Christian Babeux 46 | 47 | Now libtap++ us supported by Nikolay Shaplov at 48 | L 49 | 50 | =head1 FUNCTIONS 51 | 52 | All functions and variables are defined in the C namespace. 53 | 54 | =head2 I love it when a plan comes together 55 | 56 | Before anything else, you need a testing plan. This basically declares 57 | how many tests your script is going to run to protect against premature 58 | failure. 59 | 60 | =over 4 61 | 62 | =item B 63 | 64 | void plan(int number_of_tests); 65 | void plan(skip_all, const std::string& reason=""); 66 | void plan(no_plan); 67 | 68 | The function C is used to indicate the plan of your test run. Usually you 69 | will just give it the number of tests as argument. 70 | 71 | Alternatively, you can give it the C or C constants as 72 | arguments. The first means you will not run the tests at all, the second means 73 | you will run an unknown number of tests (the latter is not recommended). 74 | 75 | =item B 76 | 77 | void done_testing(); 78 | void done_testing(int number_of_tests); 79 | 80 | If you don't know how many tests you're going to run, you can issue the plan 81 | when you're done running tests. 82 | 83 | number_of_tests is the same as plan(), it's the number of tests you expected to 84 | run. You can omit this, in which case the number of tests you ran doesn't 85 | matter, just the fact that your tests ran to conclusion. 86 | 87 | This is safer than and replaces the "no_plan" plan. 88 | 89 | =back 90 | 91 | =head2 Test names 92 | 93 | By convention, each test is assigned a number in order. This is 94 | largely done automatically for you. However, it's often very useful to 95 | assign a name to each test. Which would you rather see: 96 | 97 | ok 4 98 | not ok 5 99 | ok 6 100 | 101 | or 102 | 103 | ok 4 - basic multi-variable 104 | not ok 5 - simple exponential 105 | ok 6 - force == mass * acceleration 106 | 107 | The later gives you some idea of what failed. It also makes it easier 108 | to find the test in your script, simply search for "simple 109 | exponential". 110 | 111 | All test functions take a name argument. It's optional, but highly 112 | suggested that you use it. 113 | 114 | =head2 I'm ok, you're not ok. 115 | 116 | The basic purpose of this module is to print out either "ok #" or "not 117 | ok #" depending on if a given test succeeded or failed. Everything 118 | else is just gravy. 119 | 120 | All of the following print "ok" or "not ok" depending on if the test 121 | succeeded or failed. They all also return true or false, 122 | respectively. 123 | 124 | =over 4 125 | 126 | =item B 127 | 128 | bool ok(bool condition, const std::string& test_name = ""); 129 | 130 | C is the basic test expression in TAP. It simply evaluates any expression, 131 | for example, I, taking a true value to mean that the test 132 | passed and a false value to mean that the test failed. 133 | 134 | C is a very short description of the test that will be printed out. 135 | It makes it very easy to find a test in your script when it fails and gives 136 | others an idea of your intentions. C is optional, but we very 137 | strongly encourage its use. 138 | 139 | =item B 140 | 141 | =item B 142 | 143 | template bool is(const T& got, const U& expected, std::string& test_name = ""); 144 | template bool isnt(const T& got, const U& expected, std::string& test_name = ""); 145 | 146 | Similar to ok(), is() and isnt() compare their two arguments 147 | with C<==> and C respectively and use the result of that to 148 | determine if the test succeeded or failed. So these: 149 | 150 | # Is the ultimate answer 42? 151 | is( ultimate_answer(), 42, "Meaning of Life" ); 152 | 153 | # foo isn't empty 154 | isnt( foo, "", "Got some foo" ); 155 | 156 | are similar to these: 157 | 158 | ok( ultimate_answer() == 42, "Meaning of Life" ); 159 | ok( foo != "", "Got some foo" ); 160 | 161 | (Mnemonic: "This is that." "This isn't that.") 162 | 163 | So why use these? They produce better diagnostics on failure. ok() cannot know 164 | what you are testing for (beyond the name), but is() and isnt() know what the 165 | test was and why it failed. For example this test: 166 | 167 | std::string foo("waffle"), bar("yarblokos"); 168 | is( foo, bar, 'Is foo the same as bar?' ); 169 | 170 | Will produce something like this: 171 | 172 | not ok 17 - Is foo the same as bar? 173 | # Failed test 'Is foo the same as bar?' 174 | # got: 'waffle' 175 | # expected: 'yarblokos' 176 | 177 | =item B 178 | 179 | =item B 180 | 181 | bool pass(const std::string& test_name = ""); 182 | bool fail(const std::string& test_name = ""); 183 | 184 | Sometimes you just want to say that the tests have passed. Usually 185 | the case is you've got some complicated condition that is difficult to 186 | wedge into an ok(). In this case, you can simply use pass() (to 187 | declare the test ok) or fail (for not ok). They are synonyms for 188 | ok(true, test_name) and ok(false, test_name). 189 | 190 | Use these very, very, very sparingly. 191 | 192 | =back 193 | 194 | =head2 Conditional testing 195 | 196 | =over 4 197 | 198 | =item B 199 | 200 | void skip(int number, const std::string& reason = ""); 201 | 202 | C tells the TAP harness that you're skipping a I of tests for the 203 | given I. Note that you have to do the skipping yourself. 204 | 205 | =item B 206 | 207 | { 208 | todo_guard why; 209 | TODO="why" 210 | my_tests_here ... 211 | } 212 | 213 | C is a global string variable that tells TAP harness the reason 214 | the current test is expected to fail. You set TODO before a block of 215 | tests that you expect to fail and then unset it afterwards. When TODO 216 | is the empty string, then the harness considers that there is no 217 | reason for the test to fail. However, when TODO is non-empty, any 218 | failing test is not counted against the test suite and any succeeding 219 | test is reported as an unexpected success. 220 | 221 | The nice part about todo tests, as opposed to simply commenting out a 222 | block of tests, is it's like having a programmatic todo list. You know 223 | how much work is left to be done, you're aware of what bugs there are, 224 | and you'll know immediately when they're fixed. 225 | 226 | Note that TODO manipulates a global variable. Thus, you should be 227 | careful to set it to "" before going to another section of the 228 | program. An easy mistake to make is to have a failing section of code 229 | that throws an exception, taking you out of the current scope without 230 | resetting TODO. To make it easier to deal with this in a thread-safe 231 | manner, the todo_guard class is provided. Objects of this class will 232 | reset TODO when they fall out of scope. 233 | 234 | =back 235 | 236 | =head2 Diagnostics 237 | 238 | If you pick the right test function, you'll usually get a good idea of 239 | what went wrong when it failed. But sometimes it doesn't work out 240 | that way. So here we have ways for you to write your own diagnostic 241 | messages which are safer than just C. 242 | 243 | =over 4 244 | 245 | =item B 246 | 247 | diag(diagnostic_message...); 248 | 249 | Prints a diagnostic message which is guaranteed not to interfere with 250 | test output. The arguments are simply concatenated together. 251 | 252 | Returns false, so as to preserve failure. 253 | 254 | Handy for this sort of thing: 255 | 256 | ok( has_user("foo"), "There's a foo user" ) or 257 | diag("Since there's no foo, check that /etc/bar is set up right"); 258 | 259 | which would produce: 260 | 261 | not ok 42 - There's a foo user 262 | # Failed test 'There's a foo user' 263 | # Since there's no foo, check that /etc/bar is set up right. 264 | 265 | You might remember C with the mnemonic C. 267 | 268 | B The exact formatting of the diagnostic output is still 269 | changing, but it is guaranteed that whatever you throw at it it won't 270 | interfere with the test. 271 | 272 | =item B 273 | 274 | note(diagnostic_message...); 275 | 276 | Like diag(), except the message will not be seen when the test is run 277 | in a harness. It will only be visible in the verbose TAP stream. 278 | 279 | Handy for putting in notes which might be useful for debugging, but 280 | don't indicate a problem. 281 | 282 | note("Tempfile is ", tempfile); 283 | 284 | C simply catenates its arguments to the error output, while C 285 | prints diagnostics to the TAP stream. 286 | 287 | =item B 288 | 289 | =item B 290 | 291 | void set_output(std::ofstream& new_output); 292 | void set_error(std::ofstream& new_error); 293 | 294 | These set the filehandle of the TAP stream and the error stream. They default 295 | to C and C, respectively. These can only be set before any 296 | output is written to them. 297 | 298 | =back 299 | 300 | =head2 Ending a test run 301 | 302 | =over 4 303 | 304 | =item B 305 | 306 | If all your tests passed, Test::Builder will exit with zero (which is 307 | normal). If anything failed it will exit with how many failed. If 308 | you run less (or more) tests than you planned, the missing (or extras) 309 | will be considered failures. If the test died, even after having 310 | successfully completed all its tests, it will still be considered a failure 311 | and will exit with 255. 312 | 313 | So the exit codes are... 314 | 315 | 0 all tests successful 316 | 255 test died or all passed but wrong # of tests run 317 | any other number how many failed (including missing or extras) 318 | 319 | If you fail more than 254 tests, it will be reported as 254. 320 | 321 | =item B 322 | 323 | int exit_status(); 324 | void bail_out(const std::string& reason); 325 | 326 | B terminates the current test program with exit code 255, indicating 327 | to the test harness that all subsequent testing should halt. Typically this 328 | is used to indicate that testing cannot continue at all. 329 | 330 | =back 331 | 332 | =head1 SEE ALSO 333 | 334 | L 335 | 336 | L and L are the traditional perl client library and TAP 337 | harness, respectively. This library is modeled after Test::More. 338 | 339 | =head1 AUTHORS 340 | 341 | Leon Timmermans wrote C. He stole much of this documentation from 342 | Test::More. Mike Pomraning also contributed this documentation. 343 | 344 | =head1 COPYRIGHT 345 | 346 | Copyright (c) 2008, 2009, 2010 Leon Timmermans. 347 | 348 | See the LICENSE file for details. 349 | 350 | =cut 351 | -------------------------------------------------------------------------------- /libtappp/include/tap++/tap++.h: -------------------------------------------------------------------------------- 1 | #ifndef LIB_TAPPP_TAPPP_H 2 | #define LIB_TAPPP_TAPPP_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef _MSC_VER 11 | #pragma warning( disable : 4290 ) // MSVC: https://msdn.microsoft.com/en-us/library/sa28fef8.aspx 12 | #endif 13 | 14 | #if __cplusplus >= 201103L 15 | #define NOEXCEPT noexcept(true) 16 | #else 17 | #define NOEXCEPT throw() 18 | #endif 19 | 20 | 21 | namespace TAP { 22 | namespace details { 23 | struct skip_all_type {}; 24 | struct no_plan_type {}; 25 | extern std::ostream* output; 26 | extern std::ostream* error; 27 | 28 | /* Return the variant of "Failed test" or "Failed */ 29 | /* (TODO) test" required by whether the current test is a todo test */ 30 | char const * failed_test_msg() NOEXCEPT; 31 | } 32 | class fatal_exception : public std::exception { 33 | std::string message; 34 | public: 35 | fatal_exception(const std::string& _message) : message(_message) { 36 | } 37 | const char* what() const throw() { 38 | return message.c_str(); 39 | } 40 | ~fatal_exception() NOEXCEPT { 41 | } 42 | }; 43 | extern const details::skip_all_type skip_all; 44 | extern const details::no_plan_type no_plan; 45 | void plan(unsigned); 46 | void plan(const details::skip_all_type&, const std::string& = ""); 47 | void plan(const details::no_plan_type&) NOEXCEPT; 48 | void done_testing(); 49 | void done_testing(unsigned); 50 | 51 | unsigned planned() NOEXCEPT; 52 | unsigned encountered() NOEXCEPT; 53 | 54 | bool ok(bool, const std::string& = "") NOEXCEPT; 55 | bool not_ok(bool, const std::string& = "") NOEXCEPT; 56 | 57 | bool pass(const std::string& = "") NOEXCEPT; 58 | bool fail(const std::string& = "") NOEXCEPT; 59 | 60 | void skip(unsigned, const std::string& = "") NOEXCEPT; 61 | void bail_out(const std::string& reason) NOEXCEPT; 62 | 63 | int exit_status() NOEXCEPT; 64 | bool summary() NOEXCEPT; 65 | 66 | void set_output(std::ostream&); 67 | void set_error(std::ostream&); 68 | 69 | template void diag(const T& first) NOEXCEPT { 70 | *details::error << "# " << first << std::endl; 71 | } 72 | template void diag(const T1& first, const T2& second) NOEXCEPT { 73 | *details::error << "# " << first << second << std::endl; 74 | } 75 | template void diag(const T1& first, const T2& second, const T3& third) NOEXCEPT { 76 | *details::error << "# " << first << second << third << std::endl; 77 | } 78 | template void diag(const T1& first, const T2& second, const T3& third, const T4& fourth) NOEXCEPT { 79 | *details::error << "# " << first << second << third << fourth << std::endl; 80 | } 81 | template void diag(const T1& first, const T2& second, const T3& third, const T4& fourth, const T5& fifth) NOEXCEPT { 82 | *details::error << "# " << first << second << third << fourth << fifth << std::endl; 83 | } 84 | 85 | template void note(const T& first) NOEXCEPT { 86 | *details::output << "# " << first << std::endl; 87 | } 88 | template void note(const T1& first, const T2& second) NOEXCEPT { 89 | *details::output << "# " << first << second << std::endl; 90 | } 91 | template void note(const T1& first, const T2& second, const T3& third) NOEXCEPT { 92 | *details::output << "# " << first << second << third << std::endl; 93 | } 94 | template void note(const T1& first, const T2& second, const T3& third, const T4& fourth) NOEXCEPT { 95 | *details::output << "# " << first << second << third << fourth << std::endl; 96 | } 97 | template void note(const T1& first, const T2& second, const T3& third, const T4& fourth, const T5& fifth) NOEXCEPT { 98 | *details::output << "# " << first << second << third << fourth << fifth << std::endl; 99 | } 100 | 101 | template 102 | bool is(const T& left, const U& right, const std::string& message, BinaryPredicate p) { 103 | using namespace TAP::details; 104 | try { 105 | bool ret = ok(p(left, right), message); 106 | if (!ret) { 107 | diag(failed_test_msg()," '", message, "'"); 108 | diag(" Got: ", left); 109 | diag(" Expected: ", right); 110 | } 111 | return ret; 112 | } 113 | catch(const std::exception& e) { 114 | fail(message); 115 | diag(failed_test_msg()," '", message, "'"); 116 | diag("Caught exception '", e.what(), "'"); 117 | diag(" Got: ", left); 118 | diag(" Expected: ", right); 119 | return false; 120 | } 121 | catch(...) { 122 | fail(message); 123 | diag(failed_test_msg()," '", message, "'"); 124 | diag("Caught unknown exception"); 125 | diag(" Got: ", left); 126 | diag(" Expected: ", right); 127 | return false; 128 | } 129 | } 130 | 131 | template 132 | bool is(const T& left, const U& right, const std::string& message = "") { 133 | return is(left, right, message, std::equal_to()); 134 | } 135 | 136 | template 137 | bool isnt(const T& left, const U& right, const std::string& message, BinaryPredicate p) { 138 | using namespace TAP::details; 139 | try { 140 | return ok(!p(left, right), message); 141 | } 142 | catch(const std::exception& e) { 143 | fail(message); 144 | diag("In test ", message); 145 | diag("Caught exception: ", e.what()); 146 | return false; 147 | } 148 | catch(...) { 149 | fail(message); 150 | diag("In test ", message); 151 | diag("Caught unknown exception"); 152 | return false; 153 | } 154 | } 155 | 156 | template 157 | bool isnt(const T& left, const U& right, const std::string& message = "") { 158 | return isnt(left, right, message, std::equal_to()); 159 | } 160 | 161 | extern double EPSILON; 162 | 163 | /*** 164 | * Compare two floating point numbers for (nearly) equality. 165 | * Follows the floating point guide at 166 | * http://floating-point-gui.de/errors/comparison/ 167 | * 168 | * RESULT is dependend on EPSILON, which describes the relative error 169 | */ 170 | template 171 | struct nearly_equal 172 | { 173 | bool operator()(const T& left, const T& right) const 174 | { 175 | T diff = fabs(left - right); 176 | return // Shortcut for equality and infinites 177 | ( left == right ) || 178 | // Very small numbers or very small diff 179 | // (std::numeric_limits::min() gives the smallest normalized number) 180 | ( (left == 0 || right == 0 || diff < std::numeric_limits::min()) && 181 | diff < EPSILON * std::numeric_limits::min() ) || 182 | // relative error 183 | ( 2. * diff / fmin(fabs(left) + fabs(right), std::numeric_limits::max()) < EPSILON ); 184 | } 185 | }; 186 | 187 | template<> inline bool is(const float& left, const float& right, const std::string& message) { 188 | return is(left, right, message, nearly_equal()); 189 | } 190 | 191 | template<> inline bool is(const float& left, const double& right, const std::string& message) { 192 | return is(left, right, message, nearly_equal()); 193 | } 194 | 195 | template<> inline bool is(const double& left, const float& right, const std::string& message) { 196 | return is(left, right, message, nearly_equal()); 197 | } 198 | 199 | template<> inline bool is(const double& left, const double& right, const std::string& message) { 200 | return is(left, right, message, nearly_equal()); 201 | } 202 | 203 | template<> inline bool isnt(const float& left, const float& right, const std::string& message) { 204 | return isnt(left, right, message, nearly_equal()); 205 | } 206 | 207 | template<> inline bool isnt(const float& left, const double& right, const std::string& message) { 208 | return isnt(left, right, message, nearly_equal()); 209 | } 210 | 211 | template<> inline bool isnt(const double& left, const float& right, const std::string& message) { 212 | return isnt(left, right, message, nearly_equal()); 213 | } 214 | 215 | template<> inline bool isnt(const double& left, const double& right, const std::string& message) { 216 | return isnt(left, right, message, nearly_equal()); 217 | } 218 | 219 | inline bool is(const float& left, const float& right){ 220 | return is(left, right, ""); 221 | } 222 | 223 | inline bool is(const float& left, const double& right){ 224 | return is(left, right, ""); 225 | } 226 | 227 | inline bool is(const double& left, const float& right){ 228 | return is(left, right, ""); 229 | } 230 | 231 | inline bool is(const double& left, const double& right){ 232 | return is(left, right, ""); 233 | } 234 | 235 | inline bool isnt(const float& left, const float& right){ 236 | return isnt(left, right, ""); 237 | } 238 | 239 | inline bool isnt(const float& left, const double& right){ 240 | return isnt(left, right, ""); 241 | } 242 | 243 | inline bool isnt(const double& left, const float& right){ 244 | return isnt(left, right, ""); 245 | } 246 | 247 | inline bool isnt(const double& left, const double& right){ 248 | return isnt(left, right, ""); 249 | } 250 | 251 | extern std::string TODO; 252 | 253 | class todo_guard { 254 | const std::string value; 255 | public: 256 | todo_guard() NOEXCEPT; 257 | ~todo_guard() NOEXCEPT; 258 | }; 259 | } 260 | 261 | #ifdef WANT_TEST_EXTRAS 262 | 263 | namespace TAP { 264 | namespace details { 265 | struct Skip_exception { 266 | const std::string reason; 267 | Skip_exception(const std::string& _reason) NOEXCEPT : reason(_reason) { 268 | } 269 | }; 270 | struct Todo_exception { 271 | const std::string reason; 272 | Todo_exception(const std::string& _reason) NOEXCEPT : reason(_reason) { 273 | } 274 | }; 275 | 276 | void start_block(unsigned) NOEXCEPT; 277 | unsigned stop_block(); 278 | 279 | } 280 | 281 | void skip(const std::string& reason); 282 | void skip_todo(const std::string& reason); 283 | } 284 | 285 | #define TRY(action, name) do {\ 286 | try {\ 287 | action;\ 288 | TAP::pass(name);\ 289 | }\ 290 | catch (const std::exception& e) {\ 291 | TAP::fail(name);\ 292 | note("Caught exception: ", e.what());\ 293 | }\ 294 | catch (...) {\ 295 | TAP::fail(name);\ 296 | }\ 297 | } while (0) 298 | 299 | #define FAIL(action, name) do {\ 300 | try {\ 301 | action;\ 302 | TAP::fail(name);\ 303 | }\ 304 | catch (...) {\ 305 | TAP::pass(name);\ 306 | }\ 307 | } while (0) 308 | 309 | #define TEST_START(num) {\ 310 | const char* _current_message = NULL;\ 311 | TAP::plan(num);\ 312 | try { 313 | 314 | #define TEST_END \ 315 | if (TAP::encountered() < TAP::planned()) {\ 316 | TAP::note("Looks like you planned ", TAP::planned(), " tests but only ran ", TAP::encountered());\ 317 | }\ 318 | else if(TAP::encountered() > TAP::planned()) {\ 319 | TAP::note("Looks like you planned ", TAP::planned(), " tests but ran ", TAP::encountered() - TAP::planned(), " extra");\ 320 | }\ 321 | }\ 322 | catch(TAP::details::Skip_exception& skipper) {\ 323 | TAP::skip(TAP::planned() - TAP::encountered(), skipper.reason);\ 324 | }\ 325 | catch(TAP::details::Todo_exception& todoer) {\ 326 | /*TODO*/\ 327 | }\ 328 | catch(const TAP::fatal_exception& e) {\ 329 | if(_current_message) TAP::fail(_current_message);\ 330 | note("A fatal error occured:,", e.what()," aborting");\ 331 | }\ 332 | catch(const std::exception& e) {\ 333 | if(_current_message) TAP::fail(_current_message);\ 334 | note("Got unknown error: ", e.what());\ 335 | }\ 336 | catch (...) {\ 337 | if(_current_message) TAP::fail(_current_message);\ 338 | }\ 339 | return TAP::exit_status();\ 340 | } 341 | 342 | #define BLOCK_START(planned) \ 343 | try {\ 344 | todo_guard foo##planned;\ 345 | TAP::details::start_block(planned); 346 | 347 | 348 | #define BLOCK_END \ 349 | if (TAP::encountered() != TAP::details::stop_block()) {\ 350 | note("There seems to be a wrong number of tests!");\ 351 | }\ 352 | }\ 353 | catch(TAP::details::Skip_exception& skipper) {\ 354 | TAP::skip(TAP::details::stop_block() - TAP::encountered(), skipper.reason);\ 355 | }\ 356 | catch(TAP::details::Todo_exception& todoer) {\ 357 | note("Can't handle todo properly yet");\ 358 | /*TODO*/\ 359 | }\ 360 | catch(const std::exception& e) {\ 361 | TAP::fail(_current_message);\ 362 | note("Got error: ", e.what());\ 363 | }\ 364 | catch (...) {\ 365 | TAP::fail(_current_message);\ 366 | note("Died with some mysterious error");\ 367 | } 368 | 369 | /* This small macro is a main reason for this ugly exercise. I can't introduce a new scope because 370 | * code subsequent to the declaration should be visible to the rest of the code. At the same time, it 371 | * must be exception safe. They are quite severe constraints :-(. 372 | */ 373 | #define TRY_DECL(action, new_message) \ 374 | _current_message = new_message;\ 375 | action;\ 376 | TAP::pass(_current_message);\ 377 | _current_message = NULL 378 | 379 | #endif /* WANT_TEST_EXTRAS */ 380 | 381 | 382 | #endif /* LIB_TAPPP_TAPPP_H */ 383 | -------------------------------------------------------------------------------- /libtappp/run_tests.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use POSIX qw/strftime/; 6 | use TAP::Harness; 7 | 8 | printf "Report %s\n", strftime("%y%m%d-%H:%M", localtime); 9 | my $harness = TAP::Harness->new( { 10 | verbosity => $ENV{VERBOSE}, 11 | exec => sub { 12 | my ($harness, $file) = @_; 13 | return [ $file ]; 14 | }, 15 | merge => 1, 16 | color => 1, 17 | }); 18 | 19 | $harness->runtests(@ARGV)->all_passed or exit 1; 20 | -------------------------------------------------------------------------------- /libtappp/src/tap++.cpp: -------------------------------------------------------------------------------- 1 | #define WANT_TEST_EXTRAS 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace TAP { 9 | double EPSILON = 1.e-4; 10 | 11 | std::string TODO = ""; 12 | 13 | const details::skip_all_type skip_all = details::skip_all_type(); 14 | const details::no_plan_type no_plan = details::no_plan_type(); 15 | 16 | namespace { 17 | unsigned expected = 0; 18 | unsigned counter = 0; 19 | unsigned not_oks = 0; 20 | 21 | std::string todo_test() NOEXCEPT { 22 | if (TODO == "") { 23 | return TODO; 24 | } 25 | else { 26 | return " # TODO " + TODO; 27 | } 28 | } 29 | 30 | bool is_todo_test() NOEXCEPT { return TODO != ""; } 31 | 32 | bool is_planned = false; 33 | bool no_planned = false; 34 | bool has_output_plan = false; 35 | 36 | void output_plan(unsigned tests, const std::string& extra = "") { 37 | if (has_output_plan) { 38 | throw fatal_exception("Can't plan twice"); 39 | } 40 | *details::output << "1.." << tests << extra << std::endl; 41 | has_output_plan = true; 42 | } 43 | inline const std::string to_string(unsigned num) NOEXCEPT { 44 | std::stringstream out; 45 | out << num; 46 | return out.str(); 47 | } 48 | 49 | inline void _done_testing(unsigned tests) { 50 | static bool is_done = false; 51 | if (is_done) { 52 | fail("done_testing() was already called"); 53 | return; 54 | } 55 | is_done = true; 56 | 57 | if (expected && tests != expected) { 58 | fail(std::string("planned to run ") + to_string(expected) + " tests but done_testing() expects " + to_string(tests)); 59 | } 60 | else { 61 | expected = tests; 62 | } 63 | is_planned = true; 64 | if (!has_output_plan) { 65 | output_plan(tests); 66 | } 67 | } 68 | 69 | } 70 | 71 | void plan(unsigned tests) { 72 | if (is_planned) { 73 | bail_out("Can't plan again!"); 74 | } 75 | is_planned = true; 76 | output_plan(tests); 77 | expected = tests; 78 | } 79 | void plan(const details::skip_all_type&, const std::string& reason) { 80 | output_plan(0, " #skip " + reason); 81 | std::exit(0); 82 | } 83 | void plan(const details::no_plan_type&) NOEXCEPT { 84 | is_planned = true; 85 | no_planned = true; 86 | } 87 | 88 | void done_testing() { 89 | _done_testing(encountered()); 90 | } 91 | 92 | void done_testing(unsigned tests) { 93 | no_planned = false; 94 | _done_testing(tests); 95 | } 96 | 97 | unsigned planned() NOEXCEPT { 98 | return expected; 99 | } 100 | unsigned encountered() NOEXCEPT { 101 | return counter; 102 | } 103 | 104 | int exit_status() NOEXCEPT { 105 | // bool passing; 106 | if (!is_planned && encountered()) { 107 | diag("Tests were run but no plan was declared and done_testing() was not seen."); 108 | } 109 | if (no_planned) { 110 | output_plan(encountered()); 111 | return std::min(254u, not_oks); 112 | } 113 | else if (expected == counter) { 114 | return std::min(254u, not_oks); 115 | } 116 | else { 117 | return 255; 118 | } 119 | } 120 | bool summary() NOEXCEPT { 121 | return (not_oks != 0); 122 | } 123 | 124 | void bail_out(const std::string& reason) NOEXCEPT { 125 | *details::output << "Bail out! " << reason << std::endl; 126 | std::exit(255); // Does not unwind stack! 127 | } 128 | 129 | bool ok(bool is_ok, const std::string& message) NOEXCEPT { 130 | const char* hot_or_not = is_ok ? "" : "not "; 131 | *details::output << hot_or_not << "ok " << ++counter<< " - " << message << todo_test() << std::endl; 132 | if (!is_ok && !is_todo_test()) { 133 | ++not_oks; 134 | } 135 | return is_ok; 136 | } 137 | bool not_ok(bool is_not_ok, const std::string& message) NOEXCEPT { 138 | return !ok(!is_not_ok, message); 139 | } 140 | 141 | bool pass(const std::string& message) NOEXCEPT { 142 | return ok(true, message); 143 | } 144 | bool fail(const std::string& message) NOEXCEPT { 145 | return ok(false, message); 146 | } 147 | 148 | void skip(unsigned num, const std::string& reason) NOEXCEPT { 149 | for(unsigned i = 0; i < num; ++i) { 150 | pass(" # skip " + reason); 151 | } 152 | } 153 | 154 | void set_output(std::ostream& new_output) { 155 | if (is_planned) { 156 | throw fatal_exception("Can't set output after plan()"); 157 | } 158 | details::output = &new_output; 159 | } 160 | void set_error(std::ostream& new_error) { 161 | if (is_planned) { 162 | throw fatal_exception("Can't set error after plan()"); 163 | } 164 | details::error = &new_error; 165 | } 166 | todo_guard::todo_guard() NOEXCEPT : value(TODO) { 167 | } 168 | todo_guard::~todo_guard() NOEXCEPT { 169 | TODO = value; 170 | } 171 | namespace details { 172 | std::ostream* output = &std::cout; 173 | std::ostream* error = &std::cout; 174 | static std::stack block_expected; 175 | void start_block(unsigned expected) NOEXCEPT { 176 | block_expected.push(encountered() + expected); 177 | } 178 | unsigned stop_block() { 179 | unsigned ret = block_expected.top(); 180 | block_expected.pop(); 181 | return ret; 182 | } 183 | 184 | char const * failed_test_msg() NOEXCEPT { 185 | return is_todo_test()?"Failed (TODO) test":"Failed test"; 186 | } 187 | 188 | } 189 | 190 | void skip(const std::string& reason) { 191 | throw details::Skip_exception(reason); 192 | } 193 | void skip_todo(const std::string& reason) { 194 | throw details::Todo_exception(reason); 195 | } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /libtappp/t/00-sanity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define WANT_TEST_EXTRAS 5 | #include 6 | 7 | using namespace TAP; 8 | 9 | class exception : public std::exception { 10 | std::string message; 11 | public: 12 | exception(const std::string& _message) : message(_message) { 13 | } 14 | virtual const char* what() const throw() { 15 | return message.c_str(); 16 | } 17 | ~exception() throw() { 18 | } 19 | }; 20 | 21 | int main() { 22 | TEST_START(13); 23 | 24 | ok(true, "True is ok"); 25 | not_ok(false, "False is not ok"); 26 | is(1, 1, "1 == 1"); 27 | isnt(1, 2, "1 == 2"); 28 | is(1.0, 1.0, "1.0 == 1.0"); 29 | not_ok(float(0.1) == 0.1, "float(0.1) != 0.1"); 30 | is(float(67329.234), float(67329.242), "Adjacent floats"); 31 | isnt(1.0, 2.0, "1.0 != 2.0"); 32 | 33 | TRY(std::rand(), "rand shouldn't throw exceptions"); 34 | FAIL(throw exception("Runtime exception"), "Should throw a Runtime exception"); 35 | 36 | BLOCK_START(1); 37 | skip("Should skip"); 38 | is(0, 1, "0 == 1"); 39 | BLOCK_END; 40 | 41 | TRY_DECL(int foo = std::rand(), "int foo = std::rand()"); 42 | ok(++foo, "++foo"); 43 | 44 | TEST_END; 45 | } 46 | -------------------------------------------------------------------------------- /t/00-sanity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define WANT_TEST_EXTRAS 5 | #include 6 | 7 | using namespace TAP; 8 | 9 | class exception : public std::exception { 10 | std::string message; 11 | public: 12 | exception(const std::string& _message) : message(_message) { 13 | } 14 | virtual const char* what() const throw() { 15 | return message.c_str(); 16 | } 17 | ~exception() throw() { 18 | } 19 | }; 20 | 21 | int main() { 22 | TEST_START(13); 23 | 24 | ok(true, "True is ok"); 25 | not_ok(false, "False is not ok"); 26 | is(1, 1, "1 == 1"); 27 | isnt(1, 2, "1 == 2"); 28 | is(1.0, 1.0, "1.0 == 1.0"); 29 | not_ok(float(0.1) == 0.1, "float(0.1) != 0.1"); 30 | is(float(67329.234), float(67329.242), "Adjacent floats"); 31 | isnt(1.0, 2.0, "1.0 != 2.0"); 32 | 33 | TRY(std::rand(), "rand shouldn't throw exceptions"); 34 | FAIL(throw exception("Runtime exception"), "Should throw a Runtime exception"); 35 | 36 | BLOCK_START(1); 37 | skip("Should skip"); 38 | is(0, 1, "0 == 1"); 39 | BLOCK_END; 40 | 41 | TRY_DECL(int foo = std::rand(), "int foo = std::rand()"); 42 | ok(++foo, "++foo"); 43 | 44 | TEST_END; 45 | } 46 | -------------------------------------------------------------------------------- /t/001-blob-generic.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #define WANT_TEST_EXTRAS 25 | #include 26 | 27 | #include "blobstamper/blobstamper.h" 28 | #include "blobstamper/helpers.h" 29 | 30 | 31 | using namespace TAP; 32 | 33 | char my_data[]="1234567890ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyzАБВГДитд.___"; 34 | 35 | char short_sample[]="123456"; 36 | 37 | int 38 | main() 39 | { 40 | char *ptr; 41 | size_t size; 42 | 43 | TEST_START(7); 44 | 45 | { /* 1..2 */ 46 | /* Check that DataDup gives us the same data we've just added to blob */ 47 | Blob blob(my_data, strlen(my_data)); 48 | blob.DataDup(ptr,size); 49 | ok(! memcmp(my_data, ptr, size), "Blob gets and returns blob data ok"); 50 | ok(size == strlen(my_data), "Blob gets and returns blob data with expected size"); 51 | free(ptr); 52 | } 53 | { /* 3..6 */ 54 | /* Check that Shift bytes behave as expected*/ 55 | char expected1[]="456"; 56 | char expected2[]="123"; 57 | 58 | std::shared_ptr blob1 = std::make_shared(short_sample,strlen(short_sample)); 59 | std::shared_ptr blob2 = blob1->Chop(3); 60 | 61 | blob1->DataDup(ptr,size); 62 | ok(size == strlen(expected1), "Blob shifted data size ok"); 63 | ok(! memcmp(expected1, ptr, size), "Blob shifted data ok"); 64 | free(ptr); 65 | 66 | blob2->DataDup(ptr,size); 67 | ok(size == strlen(expected2), "Blob remained data size ok"); 68 | ok(! memcmp(expected2, ptr, size), "Blob remained data ok"); 69 | free(ptr); 70 | } 71 | { /* 7 */ 72 | /* Check that shifting too many bytes return empty result */ 73 | std::shared_ptr blob = std::make_shared(my_data, strlen(my_data)); 74 | try 75 | { 76 | std::shared_ptr blob_res = blob->Chop(99999); 77 | ok(false, "Shift too many bytes"); 78 | } 79 | catch (OutOfData) 80 | { 81 | ok(true, "Shift too many bytes"); 82 | } 83 | catch (...) //Any othe exeption 84 | { 85 | ok(false, "Shift too many bytes"); 86 | } 87 | } 88 | 89 | 90 | 91 | TEST_END; 92 | } 93 | -------------------------------------------------------------------------------- /t/050-sized_prt_and_vsato_ptr.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | #define WANT_TEST_EXTRAS 23 | #include 24 | 25 | #include"blobstamper/helpers.h" 26 | 27 | using namespace TAP; 28 | 29 | 30 | typedef struct 31 | { 32 | float f; 33 | long l; 34 | char c; 35 | } FixedLengthObject; 36 | 37 | typedef struct 38 | { 39 | float f; 40 | long l; 41 | char c; 42 | short int arr[]; 43 | } VariableLengthObject; 44 | 45 | 46 | 47 | int main() { 48 | TEST_START(9); 49 | 50 | // #tests for sized_ptr 51 | { /* 1..3 */ 52 | long *l; 53 | size_t size = sizeof(long) * 5; 54 | l = (long*) malloc(size); 55 | for(int i=0; i<5; i++) 56 | l[i]=i*100; 57 | sized_ptr sp(l, size); 58 | 59 | long * l2 = sp; 60 | is(l2[4], 400, "Can use memory from sized poiner"); 61 | ok(l2 == l, "It is actually same pointer"); 62 | is(sp.size(),size, "Size is stored as expected"); 63 | // free(l); /*Do not need to free it. sized_ptr will do it for you*/ 64 | } 65 | { /* 4..10 */ 66 | VLATO_ptr vp(offsetof(VariableLengthObject,arr), 5); 67 | is(vp.length(), 5, "Number of elements is ok"); 68 | is(vp.size(), offsetof(VariableLengthObject,arr) + sizeof(short int) *5, "Size of object is ok"); 69 | VariableLengthObject *p1 = vp; 70 | p1->arr[4]=100; 71 | 72 | sized_ptr sp = vp; // from now on vp does not exit 73 | VariableLengthObject *p2 = vp; 74 | ok(!p2, "now vp should not point anywere"); 75 | is(sp.size(), offsetof(VariableLengthObject,arr) + sizeof(short int) *5, "Size of sized object is ok"); 76 | 77 | VariableLengthObject *p3 = sp; 78 | ok(p1 == p3, "Still same object"); 79 | is(p3->arr[4], 100, "stored data is in it's place"); 80 | } 81 | TEST_END; 82 | } 83 | -------------------------------------------------------------------------------- /t/060-oracle.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | 22 | #define WANT_TEST_EXTRAS 23 | #include 24 | 25 | #include "blobstamper/oracle.h" 26 | 27 | using namespace TAP; 28 | 29 | int 30 | main() 31 | { 32 | TEST_START(6); 33 | { 34 | is(OracleProportion(0,0,255), 0); 35 | is(OracleProportion(255,0,255), 0); 36 | is(OracleProportion(256,0,255), 1); 37 | is(OracleProportion(65535,0,255), 255); 38 | is(OracleProportion(65535-255,0,255), 255); 39 | is(OracleProportion(65535-256,0,255), 254); 40 | 41 | } 42 | TEST_END; 43 | } 44 | -------------------------------------------------------------------------------- /t/100-stamp-base.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define WANT_TEST_EXTRAS 27 | #include 28 | 29 | #include "blobstamper/blobstamper.h" 30 | #include "blobstamper/helpers.h" 31 | 32 | #include "test-chars-stamps.h" 33 | 34 | using namespace TAP; 35 | 36 | 37 | /* Tests for very basic stamp operations */ 38 | 39 | char my_data[]="1234567890ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyzАБВГДитд.___"; 40 | 41 | char short_sample[]="1234567"; 42 | 43 | int 44 | main() 45 | { 46 | char *ptr; 47 | size_t size; 48 | 49 | TEST_START(10); 50 | 51 | /* Test that ShiftSingleStampStr shifts ok with StampTwoChars stamp */ 52 | { /* 1..3 */ 53 | std::string expected1 = "12"; 54 | char expected2[] = "34567"; 55 | 56 | 57 | std::shared_ptr blob = std::make_shared(short_sample, strlen(short_sample)); 58 | StampTwoChars stamp; 59 | std::string str = stamp.ExtractStr(blob); 60 | is(str, expected1, "ShiftSingleStampStr: shifts ok"); 61 | 62 | blob->DataDup(ptr,size); 63 | ok(size == strlen(expected2), "ShiftSingleStampStr: Remaining blob data size ok"); 64 | ok(! memcmp(expected2, ptr, size), "ShiftSingleStampStr: Remaining blob data ok"); 65 | free(ptr); 66 | } 67 | 68 | /* Check that data is shifted till blob data is empty*/ 69 | { /* 4 */ 70 | char sample_two_bytes[]="12"; 71 | std::string expected1 = "12"; 72 | std::shared_ptr blob = std::make_shared(sample_two_bytes, strlen(sample_two_bytes)); 73 | StampTwoChars stamp; 74 | std::string str = stamp.ExtractStr(blob); 75 | is(str, expected1, "ShiftSingleStampStr: shifts first two bytes ok"); 76 | } 77 | /* Checks for variated size stamps*/ 78 | 79 | { /* 5,6 */ 80 | char sample[]="1234567890"; 81 | std::shared_ptr blob = std::make_shared(sample, strlen(sample)); 82 | StampSeveralChars stamp; /* accepts from 2 to 8 bytes*/ 83 | 84 | /* If used alone, is shifts as much bytes as it can. When blob has a lot, it shifts maxSize bytes */ 85 | std::string str = stamp.ExtractStr(blob); 86 | 87 | is(str, "12345678", "variated size stamp shifts as much data as it can"); 88 | 89 | str = stamp.ExtractStr(blob); 90 | is(str, "90", "but will be satisfied with less, unless it is not less than minSize()"); 91 | } 92 | 93 | { /* 7,8 */ 94 | char sample[]="123456789"; 95 | std::shared_ptr blob = std::make_shared(sample, strlen(sample)); 96 | StampSeveralChars stamp; /* accepts from 2 to 8 bytes*/ 97 | 98 | /* If used alone, is shifts as much bytes as it can. When blob has a lot, it shifts maxSize bytes */ 99 | std::string str = stamp.ExtractStr(blob); 100 | 101 | is(str, "12345678", "variated size stamp shifts as much data as it can (take two)"); 102 | 103 | try { 104 | std::string str = stamp.ExtractStr(blob); 105 | ok(false, "Variated stamp, not enough data"); 106 | } 107 | catch (OutOfData) 108 | { 109 | ok(true, "Variated stamp, not enough data"); 110 | } 111 | catch (...) //Any other exeption 112 | { 113 | ok(false, "Variated stamp, not enough data"); 114 | } 115 | } 116 | 117 | { /* 9 */ 118 | char sample[]="1"; 119 | std::shared_ptr blob = std::make_shared(sample, strlen(sample)); 120 | StampTwoChars stamp; 121 | try { 122 | std::string str = stamp.ExtractStr(blob); 123 | ok(false, "Fixed stamp, not enough data"); 124 | } 125 | catch (OutOfData) 126 | { 127 | ok(true, "Fixed stamp, not enough data"); 128 | } 129 | catch (...) //Any other exeption 130 | { 131 | ok(false, "Fixed stamp, not enough data"); 132 | } 133 | } 134 | 135 | { /* 10 */ 136 | char sample[]="1"; 137 | std::shared_ptr blob = std::make_shared(sample, strlen(sample)); 138 | StampTwoCharsList stamp; 139 | try { 140 | std::string str = stamp.ExtractStr(blob); 141 | ok(false, "Unbounded stamp, not enough data"); 142 | } 143 | catch (OutOfData) 144 | { 145 | ok(true, "Unbounded stamp, not enough data"); 146 | } 147 | catch (...) //Any other exeption 148 | { 149 | ok(false, "Unbounded stamp, not enough data"); 150 | } 151 | } 152 | TEST_END; 153 | } 154 | -------------------------------------------------------------------------------- /t/110-stamp-arithm.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #define WANT_TEST_EXTRAS 26 | #include 27 | 28 | #include "blobstamper/blobstamper.h" 29 | #include "blobstamper/helpers.h" 30 | 31 | 32 | using namespace TAP; 33 | 34 | 35 | /* Tests for atomic type stamps */ 36 | 37 | char sample_data_char[] = "Some string"; 38 | short int sample_data_int16[] = {1, -2, -3, 4, 555, 66, 777, 8}; 39 | int sample_data_int32[] = {10, -20, - 30, 40, 500, 6, 77, 888}; 40 | long long sample_data_int64[] = {100, -200, -300, 400, 5, 6, 7000, 808}; 41 | double sample_data_double[] = {1.4142, 2, 3.1415, 4.2e01, 5, 6, 7}; 42 | 43 | int 44 | main() 45 | { 46 | size_t sample_data_int16_size = sizeof(sample_data_int16); 47 | size_t sample_data_int32_size = sizeof(sample_data_int32); 48 | size_t sample_data_int64_size = sizeof(sample_data_int64); 49 | size_t sample_data_double_size = sizeof(double) * 7; 50 | 51 | TEST_START(29); 52 | 53 | /* Check that Bin and Str Char stamps works well */ 54 | { /* 1..4 */ 55 | std::shared_ptr blob = std::make_shared(sample_data_char, strlen(sample_data_char)); 56 | StampArithm stamp; 57 | 58 | std::vector v = stamp.ExtractBin(blob); 59 | 60 | char * pc = (char *) &v[0]; 61 | is(*pc, 'S' , "Bin Char stamp works well"); 62 | 63 | std::string s = stamp.ExtractStr(blob); 64 | 65 | is(s, "111" , "Str UInt8 stamp works well"); // 'o'==111 66 | 67 | char c = stamp.ExtractValue(blob); 68 | is(c, 'm' , "extract char as value works well"); 69 | 70 | sized_ptr sp =stamp.ExtractPValue(blob); 71 | char * p = sp; 72 | is(*p, 'e', "Extract poiner to value works well"); 73 | } 74 | 75 | /* Check that Bin and Srt Int16 stamps works well */ 76 | { /* 5..11 */ 77 | std::shared_ptr blob = std::make_shared((char *)sample_data_int16, sample_data_int16_size); 78 | StampArithm stamp; 79 | std::vector v = stamp.ExtractBin(blob); 80 | short int * pi = (short int *) &v[0]; 81 | is(*pi, 1 , "Bin Int16 stamp works well"); 82 | 83 | StampArithm stamp_unsigned; 84 | std::string s = stamp_unsigned.ExtractStr(blob); 85 | is(s, "65534" , "Str UInt16 stamp works well"); // (unsigned short int)-2 == 65534 86 | 87 | StampArithm stamp_signed; 88 | s = stamp_signed.ExtractStr(blob); 89 | is(s, "-3" , "Str SInt16 stamp works well"); 90 | 91 | unsigned short int ui = stamp_unsigned.ExtractValue(blob); 92 | is(ui, 4, "Extract unsigned int16 as value"); 93 | 94 | signed short int si = stamp_signed.ExtractValue(blob); 95 | is(si, 555, "Extract signed int16 as value"); 96 | 97 | sized_ptr usp =stamp_unsigned.ExtractPValue(blob); 98 | unsigned short int * up = usp; 99 | is(*up, 66, "Extract poiner to value for unsigned int16 works well"); 100 | 101 | sized_ptr ssp =stamp_signed.ExtractPValue(blob); 102 | signed short int * sp = ssp; 103 | is(*sp, 777, "Extract poiner to value for signed int16 works well"); 104 | } 105 | 106 | /* Check that Bin and Srt Int32 stamps works well */ 107 | { /* 12..18 */ 108 | std::shared_ptr blob = std::make_shared((char *)sample_data_int32, sample_data_int32_size); 109 | StampArithm stamp; 110 | 111 | std::vector v = stamp.ExtractBin(blob); 112 | 113 | int * i = (int *) &v[0]; 114 | is(*i, 10 , "Bin Int32 stamp works well"); 115 | 116 | StampArithm stamp_unsigned; 117 | std::string s = stamp_unsigned.ExtractStr(blob); 118 | is(s, "4294967276" , "Str UInt32 stamp works well"); // (unsigned short int)-20 == 4294967276 119 | 120 | StampArithm stamp_signed; 121 | s = stamp_signed.ExtractStr(blob); 122 | is(s, "-30" , "Str SInt32 stamp works well"); 123 | 124 | unsigned int ui = stamp_unsigned.ExtractValue(blob); 125 | is(ui, 40, "Extract unsigned int32 as value"); 126 | 127 | signed int si = stamp_signed.ExtractValue(blob); 128 | is(si, 500, "Extract signed int32 as value"); 129 | 130 | sized_ptr usp =stamp_unsigned.ExtractPValue(blob); 131 | unsigned int * up = usp; 132 | is(*up, 6, "Extract poiner to value for unsigned int32 works well"); 133 | 134 | sized_ptr ssp =stamp_signed.ExtractPValue(blob); 135 | signed int * sp = ssp; 136 | is(*sp, 77, "Extract poiner to value for signed int32 works well"); 137 | } 138 | 139 | 140 | /* Check that Bin and Srt Int64 stamps works well */ 141 | { /* 19..25 */ 142 | std::shared_ptr blob = std::make_shared((char *)sample_data_int64, sample_data_int64_size); 143 | StampArithm stamp; 144 | 145 | std::vector v = stamp.ExtractBin(blob); 146 | 147 | long long * i = (long long *) &v[0]; 148 | is(*i, 100 , "Bin Int64 stamp works well"); 149 | 150 | StampArithm stamp_unsigned; 151 | std::string s = stamp_unsigned.ExtractStr(blob); 152 | is(s, "18446744073709551416" , "Str UInt64 stamp works well"); // (unsigned short int)-200 == 18446744073709551416 153 | 154 | StampArithm stamp_signed; 155 | s = stamp_signed.ExtractStr(blob);; 156 | is(s, "-300" , "Str SInt64 stamp works well"); 157 | 158 | unsigned long long ui = stamp_unsigned.ExtractValue(blob); 159 | is(ui, 400, "Extract unsigned int32 as value"); 160 | 161 | signed long long si = stamp_signed.ExtractValue(blob); 162 | is(si, 5, "Extract signed int32 as value"); 163 | 164 | sized_ptr usp =stamp_unsigned.ExtractPValue(blob); 165 | unsigned long long * up = usp; 166 | is(*up, 6, "Extract poiner to value for unsigned int64 works well"); 167 | 168 | sized_ptr ssp =stamp_signed.ExtractPValue(blob); 169 | signed long long * sp = ssp; 170 | is(*sp, 7000, "Extract poiner to value for signed int64 works well"); 171 | 172 | } 173 | 174 | /* Test Double stamp */ 175 | { /* 26..29 */ 176 | std::shared_ptr blob = std::make_shared((char *)sample_data_double, sample_data_double_size); 177 | StampArithm stamp; 178 | std::vector v = stamp.ExtractBin(blob); 179 | double *pd = (double *) &v[0]; 180 | is(*pd, 1.4142, "Bin Double stamp works well"); 181 | 182 | std::string res = stamp.ExtractStr(blob); 183 | is(res, "2", "Str Double stamp works well"); 184 | 185 | double d = stamp.ExtractValue(blob); 186 | is(d, 3.1415, "Extract double as value"); 187 | 188 | sized_ptr sp =stamp.ExtractPValue(blob); 189 | double * p = sp; 190 | is(*p, 42, "Extract poiner to value for double works well"); 191 | 192 | } 193 | TEST_END; 194 | } 195 | -------------------------------------------------------------------------------- /t/120-stamp_dict.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #define WANT_TEST_EXTRAS 25 | #include 26 | 27 | #include "blobstamper/dict.h" 28 | #include "blobstamper/stamp_dict.h" 29 | 30 | class DictTest : public DictBase 31 | { 32 | public: 33 | DictTest(); 34 | }; 35 | 36 | DictTest::DictTest() 37 | { 38 | data = {"one","two","three","four"}; 39 | } 40 | 41 | using namespace TAP; 42 | 43 | /* Test that dict works as expected*/ 44 | unsigned char sample[]={0,63,64,255}; 45 | 46 | int 47 | main() 48 | { 49 | TEST_START(4); 50 | { /* 1..4 */ 51 | auto dict = std::make_shared(); 52 | StampDict stamp(dict); 53 | std::shared_ptr blob = std::make_shared((char *) sample, 4); 54 | std::string s; 55 | 56 | s = stamp.ExtractStr(blob); 57 | is(s, "one", "0 stamps as first element of dict"); 58 | 59 | s = stamp.ExtractStr(blob); 60 | is(s, "one", "63 still stamps as first element of dict, when dict has only four elements"); 61 | 62 | s = stamp.ExtractStr(blob); 63 | is(s, "two", "64 stamps as second element of dict"); 64 | 65 | s = stamp.ExtractStr(blob); 66 | is(s, "four", "255 stamps as last (fourth) element of dict"); 67 | 68 | } 69 | TEST_END; 70 | } 71 | -------------------------------------------------------------------------------- /t/130-stamp_enumerator.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #define WANT_TEST_EXTRAS 25 | #include 26 | 27 | #include "blobstamper/stamp_arithm.h" 28 | #include "blobstamper/stamp_enumerator.h" 29 | 30 | 31 | using namespace TAP; 32 | 33 | unsigned char sample[]={1,63,64,255}; 34 | 35 | int 36 | main() 37 | { 38 | TEST_START(1); 39 | { /* 1..1 */ 40 | std::shared_ptr blob = std::make_shared((char *) sample, sizeof(sample)); 41 | std::shared_ptr> base_stamp = std::make_shared>(); 42 | StampStrEnumerator stamp(base_stamp, "; ", "<", ">"); 43 | 44 | std::string s = stamp.ExtractStr(blob); 45 | 46 | is(s, "<1; 63; 64; 255>" , "The only test"); 47 | 48 | } 49 | TEST_END; 50 | } 51 | -------------------------------------------------------------------------------- /t/140-stamp_lottery.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #define WANT_TEST_EXTRAS 25 | #include 26 | 27 | #include "blobstamper/blob.h" 28 | #include "blobstamper/stamp_arithm.h" 29 | #include "blobstamper/stamp_lottery.h" 30 | 31 | 32 | using namespace TAP; 33 | 34 | unsigned char sample[]={1,63,64,255,1}; 35 | unsigned char sample2[]={1,63,64,255,1,63,64,255,1}; 36 | 37 | int 38 | main() 39 | { 40 | TEST_START(10); 41 | 42 | /* Tests for common Stamp Lottery*/ 43 | { /* 1..5 */ 44 | std::shared_ptr blob = std::make_shared((char *) sample, sizeof(sample)); 45 | StampArithm stamp_s; 46 | StampArithm stamp_c; 47 | StampArithm stamp_i; 48 | StampLottery stamp({stamp_s}); 49 | 50 | is(stamp.maxSize(), 2+1, "Test Set 1, max size is as expected"); 51 | is(stamp.minSize(), 2+1, "Test Set 1, min size is as expected"); 52 | 53 | stamp.Append(stamp_c); 54 | stamp.Append(stamp_i); 55 | 56 | is(stamp.maxSize(), 4+1, "Test Set 1.1, max size is as expected"); 57 | is(stamp.minSize(), 1+1, "Test Set 1.1, min size is as expected"); 58 | 59 | std::string s = stamp.ExtractStr(blob); 60 | 61 | is(s, "16447", "Test Set 1, return value is as expected"); 62 | 63 | } 64 | 65 | { /* 6 */ 66 | sample[0] = 255; /* Should choose last stamp*/ 67 | std::shared_ptr blob = std::make_shared((char *) sample, sizeof(sample)); 68 | StampArithm stamp_s; 69 | StampArithm stamp_c; 70 | StampArithm stamp_i; 71 | StampLottery stamp({stamp_s,stamp_c,stamp_i}); 72 | 73 | std::string s = stamp.ExtractStr(blob); 74 | 75 | is(s, "33505343", "Test Set 2, return value is as expected"); 76 | } 77 | 78 | { /* 7 */ 79 | sample[0] = 128; /* Should choose stamp in the middle */ 80 | std::shared_ptr blob = std::make_shared((char *) sample, sizeof(sample)); 81 | StampArithm stamp_s; 82 | StampArithm stamp_c; 83 | StampArithm stamp_i; 84 | StampLottery stamp({stamp_s,stamp_c,stamp_i}); 85 | 86 | std::string s = stamp.ExtractStr(blob); 87 | 88 | is(s, "63", "Test Set 3, return value is as expected"); 89 | } 90 | 91 | { /* 8 */ 92 | sample[0] = 1; /* Should choose first available stamp*/ 93 | std::shared_ptr blob = std::make_shared((char *) sample, 2); /* Sic! */ 94 | StampArithm stamp_s; 95 | StampArithm stamp_c; 96 | StampArithm stamp_l; 97 | StampLottery stamp({stamp_s,stamp_l,stamp_c}); 98 | 99 | std::string s = stamp.ExtractStr(blob); 100 | /* Only char stamp will be chosen as only it has enough data*/ 101 | is(s, "63", "Test Set 4, return value is as expected"); 102 | } 103 | 104 | /* Tests for common Stamp Lottery that is used for recursion*/ 105 | 106 | 107 | { /* 9 */ 108 | sample2[0] = 1; /* Should choose first available stamp*/ 109 | std::shared_ptr blob = std::make_shared((char *) sample2, sizeof(sample2)); 110 | StampArithm stamp_s; 111 | StampArithm stamp_c; 112 | StampArithm stamp_l; 113 | StampLottery4Recursion stamp({stamp_s,stamp_c,stamp_l}); 114 | 115 | std::string s = stamp.ExtractStr(blob); 116 | /* Only unsigned long stamp will be chosen as other stamps does not consume enough data*/ 117 | is(s, "143904352459767871", "Test Set 5, return value is as expected"); 118 | } 119 | 120 | { /* 10 */ 121 | sample2[0] = 255; /* Should choose last available stamp*/ 122 | std::shared_ptr blob = std::make_shared((char *) sample2, sizeof(sample2) -1 ); /*One byte short for unsigned long*/ 123 | StampArithm stamp_s; 124 | StampArithm stamp_c; 125 | StampArithm stamp_l; 126 | StampLottery4Recursion stamp({stamp_s,stamp_c,stamp_l}); 127 | 128 | std::string s = stamp.ExtractStr(blob); 129 | /* l-stamp is to long. s & c stamps are too short. When no stamps left, it will ignore "too short" limit, and will chose last available stamp: c */ 130 | is(s, "63", "Test Set 6, return value is as expected"); 131 | } 132 | 133 | 134 | 135 | TEST_END; 136 | } 137 | -------------------------------------------------------------------------------- /t/150-stamp_text.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #define WANT_TEST_EXTRAS 25 | #include 26 | 27 | #include "blobstamper/stamp_text.h" 28 | 29 | using namespace TAP; 30 | 31 | int 32 | main() 33 | { 34 | TEST_START(3); 35 | { /* 1..1 */ 36 | char data[] = "папа\0мама\0бабушка\0дедушка\0братик\0сестричка"; 37 | std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); 38 | StampTextPulp stamp; 39 | std::string s = stamp.ExtractStr(blob); 40 | is(s, "папа мама бабушка дедушка братик сестричка", "StampTextSimple"); 41 | 42 | } 43 | { /* 2..2 */ 44 | char data[] = "dad\0mam\0granddad\0grandmam\0brother\0sister"; 45 | std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); 46 | StampTextPulpWords stamp; 47 | std::string s = stamp.ExtractStr(blob); 48 | is(s, "d dad gra n dmam broth er siste", "GalleyTextSimple"); 49 | 50 | } 51 | { /* 3..3 */ 52 | char data[] = "abcdef" "abcdef" "ABCDEF" "012345"; 53 | std::shared_ptr blob = std::make_shared(data, (sizeof data)-1); 54 | StampTextDictWords stamp; 55 | std::string s = stamp.ExtractStr(blob); 56 | 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"); 57 | 58 | } 59 | TEST_END; 60 | } 61 | -------------------------------------------------------------------------------- /t/200-dict.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #define WANT_TEST_EXTRAS 25 | #include 26 | 27 | #include "blobstamper/dict.h" 28 | 29 | class DictTest : public DictBase 30 | { 31 | public: 32 | DictTest(); 33 | }; 34 | 35 | DictTest::DictTest() 36 | { 37 | data = {"one","two","three"}; 38 | } 39 | 40 | using namespace TAP; 41 | 42 | /* Test that dict works as expected*/ 43 | 44 | int 45 | main() 46 | { 47 | TEST_START(2); 48 | 49 | { /* 1..2 */ 50 | DictTest dict; 51 | is(dict.size(), 3,"Dict size"); 52 | is(dict.get(1), "two","Dict content"); 53 | } 54 | 55 | TEST_END; 56 | } 57 | -------------------------------------------------------------------------------- /t/320-galley-recursion-experiments.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #define WANT_TEST_EXTRAS 27 | #include 28 | 29 | #include "blobstamper/blobstamper.h" 30 | 31 | #include "test-chars-stamps.h" 32 | 33 | using namespace TAP; 34 | 35 | char short_sample[]="1234567"; 36 | char longer_sample[]="z1234567*89abcde&fghijklmnopqrstuvwxyzAB%CDEFGHIJKLMNOPQRSTUVWXYZ!"; 37 | unsigned char bin_sample[]= {49, 22, 152, 226, 89, 119, 247, 115, 43, 42, 243, 71, 234, 231, 91, 35, 78, 108, 115, 39, 181, 248, 211, 52, 47, 94, 60, 237, 18, 39, 148, 62, 205, 214, 156, 184, 18, 201, 84, 183, 74, 134, 94, 72, 14, 116, 145, 109, 1, 230, 17, 95, 154, 100, 60, 15, 12, 102, 20, 115, 35, 183, 47, 176, 78, 176, 189, 113, 131, 93, 206, 62, 158, 166, 131, 95, 232, 217, 32, 171, 87, 31, 172, 160, 66, 160, 222, 134, 253, 1, 7, 191, 91, 125, 81, 148, 41, 46, 38, 171, 83, 215, 79, 34, 23, 215, 183, 118, 236, 191, 59, 160, 135, 58, 32, 199, 170, 183, 213, 53, 162, 138, 178, 118, 23, 202, 133, 8, 192, 183, 195, 199, 250, 29, 230, 34, 159, 10, 145, 74, 121, 85, 168, 204, 192, 25, 232, 88, 85, 76, 61, 168, 247, 128, 141, 176, 112, 113, 100, 201, 82, 183, 219, 236, 226, 171, 85, 97, 160, 1, 50, 250, 161, 51, 61, 220, 167, 227, 195, 17, 164, 211, 189, 130, 52, 167, 169, 42, 17, 29, 95, 15, 178, 165, 110, 87, 149, 214, 55, 12, 236, 138, 2, 245, 158, 84, 140, 24, 225, 169, 115, 16, 130, 253, 237, 182, 95, 109, 4, 28, 249, 4, 254, 166, 62, 107, 228, 113, 130, 127, 70, 79, 140, 41, 84, 218, 134, 146, 88, 65, 24, 174, 252, 253, 226, 214, 22, 92, 248, 14, 29, 60, 180, 94, 30, 186, 0}; 38 | 39 | 40 | 41 | //class SimpeRecursionNode; 42 | //class TestRNode1; 43 | //class TestRNode2; 44 | //class TestRNode3; 45 | 46 | 47 | template using my_refvector = std::vector>; /* This defines my_refvector type a shortcut to std::vector> */ 48 | 49 | class Variants 50 | { 51 | protected: 52 | int variant_count = 1; 53 | int variant_selected = -1; 54 | bool enabled = true; 55 | 56 | public: 57 | void SetVariantCount(int i) {variant_count = i;}; 58 | int GetVariantCount(){if(enabled) return variant_count; return 0;}; 59 | void SetVariantSelected(int i) {variant_selected = i;}; 60 | int GetVariantSelected(){return variant_selected;}; 61 | void Enable(){enabled = true;}; 62 | void Disable(){enabled = false;}; 63 | }; 64 | 65 | Variants& 66 | VariantPicker(my_refvector ref_vec, unsigned char seed) 67 | { 68 | unsigned char max = 255; 69 | int total = 0; 70 | for(Variants& v : ref_vec) 71 | { 72 | total += v.GetVariantCount(); 73 | } 74 | double step = (double)max / total; 75 | int i = 0; 76 | double sum = 0; 77 | 78 | 79 | Variants * last_variant; 80 | 81 | for(Variants& v : ref_vec) 82 | { 83 | if (v.GetVariantCount() == 0) 84 | continue; 85 | last_variant = &v; 86 | for(i=0; i 0.1) 100 | { 101 | fprintf(stderr,"Something is really wrong\n"); 102 | exit(1); 103 | } 104 | /* FIXME here we should solve case when there in no variants. Now it will segfault here */ 105 | last_variant->SetVariantSelected(last_variant->GetVariantCount()-1); 106 | 107 | return ref_vec.back(); 108 | } 109 | 110 | std::vector 111 | fit_sizes(std::vector seeds, unsigned int fit_in) 112 | { 113 | long seed_sum = 0; 114 | for(int seed : seeds) 115 | { 116 | seed_sum += seed; 117 | } 118 | double proportion = (double) fit_in / (double) seed_sum; 119 | 120 | double remainder = 0; 121 | 122 | std::vector res; 123 | 124 | int res_sum = 0; 125 | for(int seed : seeds) 126 | { 127 | double d_size = (double) seed * proportion + remainder; 128 | unsigned int size = round(d_size); 129 | remainder = d_size - size; 130 | res.push_back(size); 131 | res_sum += size; 132 | } 133 | assert(res_sum == fit_in); 134 | return res; 135 | } 136 | 137 | 138 | 139 | 140 | template class WeightedRef 141 | { 142 | public: 143 | std::reference_wrapper ref; 144 | char weight; 145 | WeightedRef(T& arg_ref): ref{arg_ref}, weight{1} {} 146 | WeightedRef(T& arg_ref, char weight_arg): ref{arg_ref}, weight{weight_arg} {} 147 | }; 148 | 149 | 150 | template class WeightedRefPicker 151 | { 152 | std::vector> vec; 153 | public: 154 | WeightedRefPicker(std::initializer_list> arg): vec{arg} {} 155 | std::reference_wrapper pick(unsigned char c); 156 | }; 157 | 158 | 159 | template std::reference_wrapper 160 | WeightedRefPicker::pick(unsigned char c) 161 | { 162 | unsigned char max = 255; 163 | int total = 0; 164 | for(WeightedRef & wr : vec) 165 | { 166 | total += wr.weight; 167 | } 168 | double step = (double)max / total; 169 | int i = 0; 170 | double sum = 0; 171 | 172 | 173 | for(WeightedRef & wr : vec) 174 | { 175 | sum += step * wr.weight; 176 | if (c <= sum) 177 | return wr.ref; 178 | } 179 | 180 | // there mught be problem with precision that will not allow us to catch last item 181 | // but delta should be small. In other cases terminating 182 | if (abs(c-sum) >0.1) 183 | { 184 | fprintf(stderr,"Something is really wrong\n"); 185 | exit(1); 186 | } 187 | return vec.back().ref; 188 | } 189 | 190 | 191 | 192 | 193 | class GalleySimpleRecusion; 194 | 195 | 196 | class SimpeRecursionNode: public StampBase, public Variants 197 | { 198 | 199 | public: 200 | GalleySimpleRecusion * recursor; 201 | virtual std::string do_recursion(std::shared_ptr blob) = 0; 202 | 203 | virtual std::string tmpID() = 0; 204 | }; 205 | class TestRNode1: public SimpeRecursionNode 206 | { 207 | std::vector operations = {"+","-","*","/","^"} ; 208 | public: 209 | virtual std::string do_recursion(std::shared_ptr blob) override; 210 | int minSize() override {return 1; }; // FIXME correct it 211 | int maxSize() override {return -1;}; /* Sereies always takes as much data as it can take */ 212 | 213 | TestRNode1() {SetVariantCount(operations.size());}; 214 | 215 | std::string tmpID() override {return "A";}; 216 | }; 217 | 218 | class TestRNode2: public SimpeRecursionNode 219 | { 220 | public: 221 | virtual std::string do_recursion(std::shared_ptr blob) override; 222 | int minSize() override {return 1; }; // FIXME correct it 223 | int maxSize() override {return -1;}; /* Sereies always takes as much data as it can take */ 224 | 225 | std::string tmpID() override {return "B";} 226 | }; 227 | class TestRNode3: public SimpeRecursionNode 228 | { 229 | public: 230 | virtual std::string do_recursion(std::shared_ptr blob) override; 231 | int minSize() override {return 1; }; // FIXME correct it 232 | int maxSize() override {return -1;}; /* Sereies always takes as much data as it can take */ 233 | 234 | std::string tmpID() override {return "C";} 235 | }; 236 | 237 | class GalleySimpleRecusion : public GalleyBase 238 | { 239 | TestRNode1 node1; 240 | TestRNode2 node2; 241 | TestRNode3 node3; 242 | 243 | std::vector> stamps = {node1/*, node2, node3*/}; 244 | 245 | public: 246 | int minSize() override {return 1; }; // FIXME correct it 247 | int maxSize() override {return -1;}; /* Sereies always takes as much data as it can take */ 248 | 249 | 250 | virtual std::string do_recursion(std::shared_ptr blob); 251 | 252 | }; 253 | 254 | 255 | 256 | 257 | std::string 258 | TestRNode1::do_recursion(std::shared_ptr blob) 259 | { 260 | int variant_n = GetVariantSelected(); /* Copy it as early as possible as it can be overwritten while recursion */ 261 | 262 | StampArithm stamp_char; 263 | 264 | StampArithm stamp_sint; 265 | 266 | unsigned short int spl_val; 267 | 268 | if (blob->Size() < (stamp_sint.minSize() + 4* stamp_char.minSize()) ) 269 | { 270 | try{ 271 | std::string val = stamp_char.ExtractStr(blob); 272 | return val; 273 | } 274 | catch (OutOfData) 275 | { 276 | printf("___________________________ %i\n", blob->Size()); 277 | return "Q"; 278 | } 279 | 280 | } 281 | 282 | try{ 283 | spl_val = stamp_sint.ExtractValue(blob); 284 | } 285 | catch (OutOfData) 286 | { 287 | return "Z"; 288 | } 289 | 290 | std::vector split_data_in = {spl_val, (unsigned short int) std::numeric_limits::max() - spl_val }; 291 | std::vector split_data = fit_sizes(split_data_in, blob->Size() - 4* stamp_char.minSize()); 292 | 293 | printf("llll - %i %i \n", split_data[0], split_data[1]); 294 | 295 | std::shared_ptr blob_left = blob->Chop(split_data[0]+ 2*stamp_char.minSize() ); 296 | 297 | printf("~~~ %i\n",variant_n); 298 | 299 | return "(" + recursor->do_recursion(blob_left) + " " + operations[variant_n] +" "+ recursor->do_recursion(blob)+")"; 300 | } 301 | 302 | std::string 303 | TestRNode2::do_recursion(std::shared_ptr blob) 304 | { 305 | try{ 306 | std::shared_ptr tmp = blob->Chop(1); 307 | } 308 | catch (OutOfData) 309 | { 310 | return "0"; 311 | } 312 | 313 | return "2 + " + recursor->do_recursion(blob); 314 | } 315 | 316 | 317 | std::string 318 | TestRNode3::do_recursion(std::shared_ptr blob) 319 | { 320 | try{ 321 | std::shared_ptr tmp = blob->Chop(1); 322 | } 323 | catch (OutOfData) 324 | { 325 | return "0"; 326 | } 327 | 328 | return "3 + " + recursor->do_recursion(blob); 329 | } 330 | 331 | std::string 332 | GalleySimpleRecusion::do_recursion(std::shared_ptr blob) 333 | { 334 | 335 | 336 | StampArithm stamp_char; 337 | unsigned char c; 338 | try{ 339 | c = stamp_char.ExtractValue(blob); 340 | } 341 | catch (OutOfData) 342 | { 343 | return "0"; 344 | } 345 | 346 | 347 | std::vector> stamps_v = {node1/*, node2, node3*/}; 348 | 349 | 350 | /* printf("=================================\n"); 351 | 352 | 353 | for(int i = 0; i<256;i+=1) 354 | { 355 | 356 | SimpeRecursionNode& res_node = (SimpeRecursionNode&) VariantPicker(stamps_v, i); 357 | printf("--- %s - %i \n",res_node.tmpID().c_str(), res_node.GetVariantSelected()); 358 | } 359 | 360 | */ 361 | 362 | 363 | // c = c % 3; 364 | 365 | // SimpeRecursionNode &node = stamps[c]; 366 | // TestRNode3 node; 367 | 368 | 369 | 370 | SimpeRecursionNode& node = (SimpeRecursionNode&) VariantPicker(stamps_v, c); 371 | 372 | printf("--- %s - %i - %i \n",node.tmpID().c_str(), c, node.GetVariantSelected()); 373 | 374 | 375 | node.recursor = this; 376 | return node.do_recursion(blob); 377 | } 378 | 379 | 380 | 381 | 382 | 383 | int 384 | main() 385 | { 386 | 387 | std::vector v = {1,20,30,10,1}; 388 | 389 | std::vector res = fit_sizes(v, 6); 390 | for( unsigned int i : res) 391 | { 392 | printf("*** %i\n",i); 393 | } 394 | 395 | 396 | /* 397 | char c1='a'; 398 | char c2='b'; 399 | char c3='c'; 400 | char c4='d'; 401 | 402 | WeightedRefPicker wrp {{c1,1},{c2,2},{c3,3},{c4,4}}; 403 | 404 | for(int i = 0; i<=255;i+=1) 405 | { 406 | char &rc = wrp.pick(i); 407 | fprintf(stderr,"^^ %i %c\n",i,rc); 408 | 409 | } */ 410 | 411 | TEST_START(1); 412 | { 413 | // Blob blob(short_sample, strlen(short_sample)); 414 | std::shared_ptr blob = std::make_shared((char *)bin_sample, strlen((char *)bin_sample)); 415 | GalleySimpleRecusion galley; 416 | 417 | fprintf(stderr,"--1\n"); 418 | 419 | std::string str = galley.do_recursion(blob); 420 | 421 | fprintf(stderr,"--99\n"); 422 | 423 | fprintf(stderr,"-- %s --\n",str.c_str()); 424 | 425 | ok(1); 426 | } 427 | TEST_END; 428 | } 429 | -------------------------------------------------------------------------------- /t/321-galley-recursion-experiments_2.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | #define WANT_TEST_EXTRAS 25 | #include 26 | 27 | #include "blobstamper/stamp_json.h" 28 | #include "blobstamper/oracle.h" 29 | 30 | using namespace TAP; 31 | 32 | char short_sample[]="1234567"; 33 | char longer_sample[]="z1234567*89abcde&fghijklmnopqrstuvwxyzAB%CDEFGHIJKLMNOPQRSTUVWXYZ!"; 34 | unsigned char bin_sample[]= {49, 22, 152, 226, 89, 119, 247, 115, 43, 42, 243, 71, 234, 231, 91, 35, 78, 108, 115, 39, 181, 248, 211, 52, 47, 94, 60, 237, 18, 39, 148, 62, 205, 214, 156, 184, 18, 201, 84, 183, 74, 134, 94, 72, 14, 116, 145, 109, 1, 230, 17, 95, 154, 100, 60, 15, 12, 102, 20, 115, 35, 183, 47, 176, 78, 176, 189, 113, 131, 93, 206, 62, 158, 166, 131, 95, 232, 217, 32, 171, 87, 31, 172, 160, 66, 160, 222, 134, 253, 1, 7, 191, 91, 125, 81, 148, 41, 46, 38, 171, 83, 215, 79, 34, 23, 215, 183, 118, 236, 191, 59, 160, 135, 58, 32, 199, 170, 183, 213, 53, 162, 138, 178, 118, 23, 202, 133, 8, 192, 183, 195, 199, 250, 29, 230, 34, 159, 10, 145, 74, 121, 85, 168, 204, 192, 25, 232, 88, 85, 76, 61, 168, 247, 128, 141, 176, 112, 113, 100, 201, 82, 183, 219, 236, 226, 171, 85, 97, 160, 1, 50, 250, 161, 51, 61, 220, 167, 227, 195, 17, 164, 211, 189, 130, 52, 167, 169, 42, 17, 29, 95, 15, 178, 165, 110, 87, 149, 214, 55, 12, 236, 138, 2, 245, 158, 84, 140, 24, 225, 169, 115, 16, 130, 253, 237, 182, 95, 109, 4, 28, 249, 4, 254, 166, 62, 107, 228, 113, 130, 127, 70, 79, 140, 41, 84, 218, 134, 146, 88, 65, 24, 174, 252, 253, 226, 214, 22, 92, 248, 14, 29, 60, 180, 94, 30, 186, 0}; 35 | 36 | 37 | int 38 | main() 39 | { 40 | 41 | // If you uncomment this it will crash for reason I do not understand 42 | 43 | /* auto blob1 = std::make_shared((char *)bin_sample, strlen((char *)bin_sample)); 44 | auto stamp_j1 = std::make_shared(); 45 | std::string s1 = stamp_j1->ExtractStr(blob1); 46 | printf("%s\n", s1.c_str()); 47 | */ 48 | 49 | TEST_START(5); 50 | { 51 | auto blob = std::make_shared((char *)bin_sample, strlen((char *)bin_sample)); 52 | auto stamp_j = std::make_shared(); 53 | 54 | std::string s = stamp_j->ExtractStr(blob); 55 | 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\"]"; 56 | is(s, expected, "json stamp works well"); 57 | } 58 | /* Smallest sample giving sane output */ 59 | { 60 | auto blob = std::make_shared((char *)bin_sample, 10); /* ORACLE_SIZE = 2 + int = 8 */ 61 | auto stamp_j = std::make_shared(); 62 | 63 | std::string s = stamp_j->ExtractStr(blob); 64 | std::string expected = "3038649880288027288"; 65 | is(s, expected, "json stamp on shortest data works well"); 66 | } 67 | /* Check throw OutOfMemory when data length is less then ORACLE_SIZE */ 68 | { 69 | auto blob = std::make_shared((char *)bin_sample, ORACLE_SIZE - 1); 70 | auto stamp_j = std::make_shared(); 71 | 72 | int cought = 0; 73 | try{ 74 | std::string s = stamp_j->ExtractStr(blob); 75 | } 76 | catch (OutOfData) 77 | { 78 | cought = 1; 79 | } 80 | ok(cought, "Throws OutOfData if have data size less then ORACLE_SIZE"); 81 | } 82 | /* Check throw OutOfMemory when data length is equal to ORACLE_SIZE */ 83 | { 84 | auto blob = std::make_shared((char *)bin_sample, ORACLE_SIZE); 85 | auto stamp_j = std::make_shared(); 86 | 87 | int cought = 0; 88 | try{ 89 | std::string s = stamp_j->ExtractStr(blob); 90 | } 91 | catch (OutOfData) 92 | { 93 | cought = 1; 94 | } 95 | ok(cought, "Throws OutOfData if have data size equal to ORACLE_SIZE"); 96 | } 97 | /* Check throw OutOfMemory when data length is bit bigger than ORACLE_SIZE */ 98 | /* But not big enough to give any output */ 99 | { 100 | auto blob = std::make_shared((char *)bin_sample, ORACLE_SIZE + 1); 101 | auto stamp_j = std::make_shared(); 102 | 103 | int cought = 0; 104 | try{ 105 | std::string s = stamp_j->ExtractStr(blob); 106 | } 107 | catch (OutOfData) 108 | { 109 | cought = 1; 110 | } 111 | ok(cought, "Throws OutOfData if have data size is a bit bigger then ORACLE_SIZE"); 112 | } 113 | TEST_END; 114 | } 115 | -------------------------------------------------------------------------------- /t/Makefile: -------------------------------------------------------------------------------- 1 | CXX ?= g++ 2 | ACK := ack 3 | LIBTAPPP := ../libtappp/libtap++.so 4 | WARNINGS := -Wall -Wextra -Weffc++ 5 | DEBUG := -ggdb3 -DDEBUG 6 | #CXXFLAGS := $(DEBUG) $(WARNINGS) -fPIC 7 | PREFIX := /usr/local 8 | LIBRARY_VAR := LD_LIBRARY_PATH 9 | 10 | 11 | BLOBSTAMPER_SRC := $(wildcard ../blobstamper/*.cpp) 12 | BLOBSTAMPER_OBJ := $(addsuffix .o, $(basename $(BLOBSTAMPER_SRC))) 13 | 14 | TEST_SRC := $(wildcard ./*.cpp) 15 | TEST_BIN := $(addsuffix .t, $(basename $(TEST_SRC))) 16 | 17 | 18 | all: build-libtappp $(TEST_BIN) 19 | 20 | build-libtappp: 21 | $(MAKE) -C ../libtappp 22 | 23 | %.t: %.cpp $(BLOBSTAMPER_OBJ) 24 | $(CXX) $(CXXFLAGS) -I../libtappp/include -g -I.. -o $@ $< $(BLOBSTAMPER_OBJ) -L../libtappp -ltap++ 25 | 26 | test: all 27 | @echo run_tests.pl $(TEST_BIN) 28 | @$(LIBRARY_VAR)=../libtappp ../libtappp/run_tests.pl $(TEST_BIN) 29 | 30 | clean: 31 | -rm *.t 2>/dev/null 32 | 33 | .PHONY: test clean all build-libtappp build-libblobstamper 34 | 35 | -------------------------------------------------------------------------------- /t/README.md: -------------------------------------------------------------------------------- 1 | Запуск отдельного теста: 2 | 3 | ``` 4 | LD_LIBRARY_PATH=../libtappp ./001-blob-generic.t 5 | ``` 6 | -------------------------------------------------------------------------------- /t/test-chars-stamps.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2021-2023 Nikolay Shaplov (Postgres Professional) 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | /* This stamps chops first two bytes and treat them as string */ 20 | /* Never do this in real live, as blob is binary and may have \0 in the middle of it*/ 21 | 22 | class StampTwoChars: public StampBaseStr 23 | { 24 | public: 25 | std::string ExtractStr(std::shared_ptr blob) override; 26 | virtual int minSize() override {return 2;} /* This stamp shifts two characters only */ 27 | virtual int maxSize() override {return 2;} /* This stamp shifts two characters only */ 28 | 29 | }; 30 | 31 | std::string 32 | StampTwoChars::ExtractStr(std::shared_ptr blob) 33 | { 34 | /* Chopping suitable data chunk from blob */ 35 | std::vector data = blob->Chop(minSize(), maxSize())->AsByteVector(); 36 | 37 | size_t buf_size = data.size() + 1; 38 | char * buf = (char *) malloc(buf_size); 39 | memcpy(buf, &data[0], data.size()); 40 | buf[buf_size-1] = '\0'; 41 | 42 | /* Save shited data as string */ 43 | /* NEVER do this in prod, as in real live blob is binary and may have 0 in the middle of it */ 44 | std::string res = buf; 45 | free(buf); 46 | 47 | return res; 48 | } 49 | 50 | /*****************************************************************************/ 51 | class StampSeveralChars: public StampBaseStr 52 | { 53 | public: 54 | virtual int minSize() override {return 2;} /* Minimal size of consumed data */ 55 | virtual int maxSize() override {return 8;} /* Maximal size of consumed data */ 56 | std::string ExtractStr(std::shared_ptr blob) override; 57 | }; 58 | 59 | std::string 60 | StampSeveralChars::ExtractStr(std::shared_ptr blob) 61 | { 62 | std::vector data = blob->Chop(minSize(), maxSize())->AsByteVector(); 63 | /* Save optained data as string */ 64 | /* NEVER do this in prod, as in real live blob is binary and may have 0 in the middle of it */ 65 | char * buf; 66 | buf = (char *) malloc(data.size() + 1); 67 | memcpy((void *) buf, (void *) &data[0], data.size()); 68 | buf[data.size()] = '\0'; 69 | 70 | std::string res = buf; 71 | free(buf); 72 | 73 | return res; 74 | } 75 | 76 | /*****************************************************************************/ 77 | class StampTwoCharsList: public StampBaseStr 78 | { 79 | protected: 80 | std::shared_ptr el_stamp; 81 | GalleyVectorStr galley; 82 | public: 83 | std::string ExtractStr(std::shared_ptr blob) override; 84 | StampTwoCharsList(): el_stamp {std::make_shared()}, galley {el_stamp} {}; 85 | 86 | virtual int minSize() override {return el_stamp->minSize();}; 87 | virtual int maxSize() override {return -1;}; 88 | }; 89 | 90 | std::string 91 | StampTwoCharsList::ExtractStr(std::shared_ptr blob) 92 | { 93 | std::string res = ""; 94 | std::vector list = galley.ExtractStrVector(blob); 95 | 96 | for (std::string point : list) 97 | { 98 | if (!res.empty()) res = res + ", "; 99 | res = res + point; 100 | } 101 | 102 | res = "(" + res + ")"; 103 | return res; 104 | } 105 | 106 | 107 | -------------------------------------------------------------------------------- /test_with_sanitizers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export CC=clang-11 4 | export CXX=clang++-11 5 | export CFLAGS="-g -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=undefined" 6 | export CXXFLAGS="-g -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=undefined" 7 | export LDFLAGS="-g -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=undefined" 8 | 9 | make clean 10 | make 11 | make examples 12 | make -C console_demo 13 | make test 14 | --------------------------------------------------------------------------------