├── .azure-pipelines.yml ├── .github └── workflows │ └── actions.yml ├── LICENSE ├── README.md ├── test ├── include │ ├── gtest │ │ ├── gtest-death-test.h │ │ ├── gtest-matchers.h │ │ ├── gtest-message.h │ │ ├── gtest-param-test.h │ │ ├── gtest-printers.h │ │ ├── gtest-spi.h │ │ ├── gtest-test-part.h │ │ ├── gtest-typed-test.h │ │ ├── gtest.h │ │ ├── gtest_pred_impl.h │ │ ├── gtest_prod.h │ │ └── internal │ │ │ ├── custom │ │ │ ├── README.md │ │ │ ├── gtest-port.h │ │ │ ├── gtest-printers.h │ │ │ └── gtest.h │ │ │ ├── gtest-death-test-internal.h │ │ │ ├── gtest-filepath.h │ │ │ ├── gtest-internal.h │ │ │ ├── gtest-param-util.h │ │ │ ├── gtest-port-arch.h │ │ │ ├── gtest-port.h │ │ │ ├── gtest-string.h │ │ │ └── gtest-type-util.h │ └── test.h ├── src │ ├── gtest │ │ └── src │ │ │ ├── gtest-death-test.cc │ │ │ ├── gtest-filepath.cc │ │ │ ├── gtest-internal-inl.h │ │ │ ├── gtest-matchers.cc │ │ │ ├── gtest-port.cc │ │ │ ├── gtest-printers.cc │ │ │ ├── gtest-test-part.cc │ │ │ ├── gtest-typed-test.cc │ │ │ ├── gtest.cc │ │ │ └── gtest_main.cc │ ├── test_alloc_limit.cpp │ ├── test_append.cpp │ ├── test_array.cpp │ ├── test_bitset.cpp │ ├── test_byte_serializable.cpp │ ├── test_constexpr.cpp │ ├── test_data_sources.cpp │ ├── test_default_size_type.cpp │ ├── test_detect_members_serialize.cpp │ ├── test_endian.cpp │ ├── test_function.cpp │ ├── test_graph.cpp │ ├── test_hash.cpp │ ├── test_list.cpp │ ├── test_map.cpp │ ├── test_members_serialize.cpp │ ├── test_optional.cpp │ ├── test_optional_ptr.cpp │ ├── test_pb_protocol.cpp │ ├── test_reflect.cpp │ ├── test_rpc.cpp │ ├── test_rpc_opaque.cpp │ ├── test_sanity.cpp │ ├── test_set.cpp │ ├── test_shared_ptr.cpp │ ├── test_span.cpp │ ├── test_span_extent.cpp │ ├── test_stdarray.cpp │ ├── test_unique_ptr.cpp │ ├── test_unordered_map.cpp │ ├── test_unordered_set.cpp │ ├── test_variant.cpp │ ├── test_varint.cpp │ ├── test_vector.cpp │ └── test_zero_copy_byte_types.cpp ├── zpp.mk └── zpp_project.mk └── zpp_bits.h /.azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - main 3 | 4 | strategy: 5 | matrix: 6 | ubuntu-22.04-clang: 7 | VM_IMAGE: 'ubuntu-22.04' 8 | OPERATING_SYSTEM: 'linux' 9 | COMPILER: 'clang' 10 | CLANG_VERSION: '13' 11 | ASAN_OPTIONS: 'alloc_dealloc_mismatch=0' 12 | TEST_AUTODETECT: 1 13 | macOS-15: 14 | VM_IMAGE: 'macOS-15' 15 | OPERATING_SYSTEM: 'mac-os' 16 | COMPILER: 'clang' 17 | CLANG_VERSION: '17' 18 | ASAN_OPTIONS: 'alloc_dealloc_mismatch=0' 19 | TEST_AUTODETECT: 1 20 | 21 | pool: 22 | vmImage: $(VM_IMAGE) 23 | 24 | steps: 25 | - script: | 26 | curl -fLo llvm.sh https://apt.llvm.org/llvm.sh 27 | chmod +x ./llvm.sh 28 | sudo ./llvm.sh $(CLANG_VERSION) all 29 | sudo apt install -y libc++-$(CLANG_VERSION)-dev libc++abi-$(CLANG_VERSION)-dev libunwind-$(CLANG_VERSION)-dev 30 | sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-$(CLANG_VERSION) $(CLANG_VERSION)00 31 | displayName: 'install (linux)' 32 | condition: and(eq(variables['OPERATING_SYSTEM'], 'linux'), eq(variables['COMPILER'], 'clang')) 33 | 34 | - script: | 35 | sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test 36 | sudo apt install gcc-$(GCC_VERSION) g++-$(GCC_VERSION) 37 | displayName: 'install (linux)' 38 | condition: and(eq(variables['OPERATING_SYSTEM'], 'linux'), eq(variables['COMPILER'], 'gcc')) 39 | 40 | - script: | 41 | brew install --force-bottle llvm@$(CLANG_VERSION) make 42 | displayName: 'install (mac)' 43 | condition: eq(variables['OPERATING_SYSTEM'], 'mac-os') 44 | 45 | - script: | 46 | git clone https://github.com/eyalz800/zpp_throwing ../zpp_throwing 47 | displayName: 'dependencies' 48 | condition: eq(variables['COMPILER'], 'clang') 49 | 50 | - script: | 51 | make -C test -f zpp.mk -j ZPP_BITS_AUTODETECT_MEMBERS_MODE=$(TEST_AUTODETECT) 52 | displayName: 'compile-debug (linux)' 53 | condition: and(eq(variables['OPERATING_SYSTEM'], 'linux'), eq(variables['COMPILER'], 'clang')) 54 | 55 | - script: | 56 | make -C test -f zpp.mk -j mode=release ZPP_BITS_AUTODETECT_MEMBERS_MODE=$(TEST_AUTODETECT) 57 | displayName: 'compile-release (linux)' 58 | condition: and(eq(variables['OPERATING_SYSTEM'], 'linux'), eq(variables['COMPILER'], 'clang')) 59 | 60 | - script: | 61 | sed -i 's/-stdlib=libc++//g' ./test/zpp_project.mk 62 | make -C test -f zpp.mk -j ZPP_CC=gcc-11 ZPP_CXX=g++-11 63 | displayName: 'compile-debug (linux)' 64 | condition: and(eq(variables['OPERATING_SYSTEM'], 'linux'), eq(variables['COMPILER'], 'gcc')) 65 | 66 | - script: | 67 | sed -i 's/-stdlib=libc++//g' ./test/zpp_project.mk 68 | make -C test -f zpp.mk -j mode=release ZPP_CC=gcc-11 ZPP_CXX=g++-11 69 | displayName: 'compile-release (linux)' 70 | condition: and(eq(variables['OPERATING_SYSTEM'], 'linux'), eq(variables['COMPILER'], 'gcc')) 71 | 72 | - script: | 73 | export PATH=/usr/local/opt/llvm@$(CLANG_VERSION)/bin:/usr/local/opt/llvm/bin:$PATH 74 | gmake -C test -f zpp.mk -j 75 | displayName: 'compile-debug (mac)' 76 | condition: eq(variables['OPERATING_SYSTEM'], 'mac-os') 77 | 78 | - script: | 79 | export PATH=/usr/local/opt/llvm@$(CLANG_VERSION)/bin:/usr/local/opt/llvm/bin:$PATH 80 | gmake -C test -f zpp.mk -j mode=release 81 | displayName: 'compile-release (mac)' 82 | condition: eq(variables['OPERATING_SYSTEM'], 'mac-os') 83 | 84 | - script: | 85 | ./test/out/debug/default/output 86 | displayName: 'test-debug' 87 | 88 | - script: | 89 | ./test/out/release/default/output 90 | displayName: 'test-release' 91 | -------------------------------------------------------------------------------- /.github/workflows/actions.yml: -------------------------------------------------------------------------------- 1 | name: actions 2 | 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | schedule: 9 | - cron: '0 8 * * *' 10 | 11 | jobs: 12 | build: 13 | runs-on: ${{ matrix.config.vm_image }} 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | config: 18 | - name: GCC 11 Ubuntu 19 | compiler: gcc 20 | compiler_version: 11 21 | make: make 22 | mode: release 23 | os: ubuntu 24 | vm_image: ubuntu-22.04 25 | test_autodetect_members: 0 26 | with_zpp_throwing: 0 27 | - name: GCC 12 Ubuntu 28 | compiler: gcc 29 | compiler_version: 12 30 | make: make 31 | mode: release 32 | os: ubuntu 33 | vm_image: ubuntu-22.04 34 | test_autodetect_members: 0 35 | with_zpp_throwing: 0 36 | - name: Clang 13 Ubuntu 37 | compiler: clang 38 | compiler_version: 13 39 | make: make 40 | mode: release 41 | os: ubuntu 42 | vm_image: ubuntu-22.04 43 | test_autodetect_members: 1 44 | with_zpp_throwing: 1 45 | - name: Clang 21 Ubuntu 46 | compiler: clang 47 | compiler_version: 21 48 | make: make 49 | mode: release 50 | os: ubuntu 51 | vm_image: ubuntu-24.04 52 | test_autodetect_members: 0 53 | with_zpp_throwing: 1 54 | - name: Clang 17 MacOS 55 | compiler: clang 56 | compiler_version: 17 57 | make: gmake 58 | mode: release 59 | os: macos 60 | vm_image: macos-15 61 | test_autodetect_members: 0 62 | with_zpp_throwing: 1 63 | - name: Clang 18 MacOS 64 | compiler: clang 65 | compiler_version: 18 66 | make: gmake 67 | mode: release 68 | os: macos 69 | vm_image: macos-15 70 | test_autodetect_members: 1 71 | with_zpp_throwing: 1 72 | env: 73 | DEBIAN_FRONTEND: noninteractive 74 | ASAN_OPTIONS: 'alloc_dealloc_mismatch=0' 75 | 76 | steps: 77 | - uses: actions/checkout@v2 78 | with: 79 | submodules: true 80 | - name: 'install (ubuntu, clang)' 81 | if: matrix.config.os == 'ubuntu' && matrix.config.compiler == 'clang' 82 | run: | 83 | curl -fLo llvm.sh https://apt.llvm.org/llvm.sh 84 | chmod +x ./llvm.sh 85 | sudo ./llvm.sh ${{ matrix.config.compiler_version }} all 86 | sudo apt install -y libc++-${{ matrix.config.compiler_version }}-dev libc++abi-${{ matrix.config.compiler_version }}-dev libunwind-${{ matrix.config.compiler_version }}-dev 87 | sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${{ matrix.config.compiler_version }} ${{ matrix.config.compiler_version }}00 88 | - name: 'install (ubuntu, gcc)' 89 | if: matrix.config.os == 'ubuntu' && matrix.config.compiler == 'gcc' 90 | run: | 91 | sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test 92 | sudo apt install gcc-${{ matrix.config.compiler_version }} g++-${{ matrix.config.compiler_version }} 93 | - name: 'install (macos)' 94 | if: matrix.config.os == 'macos' 95 | run: | 96 | brew install llvm@${{ matrix.config.compiler_version }} make 97 | echo "PATH=/usr/local/opt/llvm@${{ matrix.config.compiler_version }}/bin:/usr/local/opt/llvm/bin:$PATH" >> $GITHUB_ENV 98 | - name: 'install (zpp_throwing)' 99 | if: matrix.config.with_zpp_throwing == '1' 100 | run: | 101 | git clone https://github.com/eyalz800/zpp_throwing ../zpp_throwing 102 | - name: 'configure (gcc, libstdc++)' 103 | if: matrix.config.compiler == 'gcc' 104 | run: | 105 | sed -i 's/-stdlib=libc++//g' ./test/zpp_project.mk 106 | sed -i 's/ZPP_CC .*/ZPP_CC := g++-${{ matrix.config.compiler_version }}/g' ./test/zpp_project.mk 107 | sed -i 's/ZPP_CXX .*/ZPP_CXX := g++-${{ matrix.config.compiler_version }}/g' ./test/zpp_project.mk 108 | - name: 'compile' 109 | run: | 110 | ${{ matrix.config.make }} -C test -f zpp.mk -j mode=${{ matrix.config.mode }} ZPP_BITS_AUTODETECT_MEMBERS_MODE=${{ matrix.config.test_autodetect_members }} 111 | - name: 'test' 112 | run: | 113 | ./test/out/${{ matrix.config.mode }}/default/output 114 | 115 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Eyal Z 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/include/gtest/gtest-message.h: -------------------------------------------------------------------------------- 1 | // Copyright 2005, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // 31 | // The Google C++ Testing and Mocking Framework (Google Test) 32 | // 33 | // This header file defines the Message class. 34 | // 35 | // IMPORTANT NOTE: Due to limitation of the C++ language, we have to 36 | // leave some internal implementation details in this header file. 37 | // They are clearly marked by comments like this: 38 | // 39 | // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 40 | // 41 | // Such code is NOT meant to be used by a user directly, and is subject 42 | // to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user 43 | // program! 44 | 45 | #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 46 | #define GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 47 | 48 | #include 49 | #include 50 | #include 51 | 52 | #include "gtest/internal/gtest-port.h" 53 | 54 | GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ 55 | /* class A needs to have dll-interface to be used by clients of class B */) 56 | 57 | // Ensures that there is at least one operator<< in the global namespace. 58 | // See Message& operator<<(...) below for why. 59 | void operator<<(const testing::internal::Secret&, int); 60 | 61 | namespace testing { 62 | 63 | // The Message class works like an ostream repeater. 64 | // 65 | // Typical usage: 66 | // 67 | // 1. You stream a bunch of values to a Message object. 68 | // It will remember the text in a stringstream. 69 | // 2. Then you stream the Message object to an ostream. 70 | // This causes the text in the Message to be streamed 71 | // to the ostream. 72 | // 73 | // For example; 74 | // 75 | // testing::Message foo; 76 | // foo << 1 << " != " << 2; 77 | // std::cout << foo; 78 | // 79 | // will print "1 != 2". 80 | // 81 | // Message is not intended to be inherited from. In particular, its 82 | // destructor is not virtual. 83 | // 84 | // Note that stringstream behaves differently in gcc and in MSVC. You 85 | // can stream a NULL char pointer to it in the former, but not in the 86 | // latter (it causes an access violation if you do). The Message 87 | // class hides this difference by treating a NULL char pointer as 88 | // "(null)". 89 | class GTEST_API_ Message { 90 | private: 91 | // The type of basic IO manipulators (endl, ends, and flush) for 92 | // narrow streams. 93 | typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); 94 | 95 | public: 96 | // Constructs an empty Message. 97 | Message(); 98 | 99 | // Copy constructor. 100 | Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT 101 | *ss_ << msg.GetString(); 102 | } 103 | 104 | // Constructs a Message from a C-string. 105 | explicit Message(const char* str) : ss_(new ::std::stringstream) { 106 | *ss_ << str; 107 | } 108 | 109 | // Streams a non-pointer value to this object. 110 | template 111 | inline Message& operator <<(const T& val) { 112 | // Some libraries overload << for STL containers. These 113 | // overloads are defined in the global namespace instead of ::std. 114 | // 115 | // C++'s symbol lookup rule (i.e. Koenig lookup) says that these 116 | // overloads are visible in either the std namespace or the global 117 | // namespace, but not other namespaces, including the testing 118 | // namespace which Google Test's Message class is in. 119 | // 120 | // To allow STL containers (and other types that has a << operator 121 | // defined in the global namespace) to be used in Google Test 122 | // assertions, testing::Message must access the custom << operator 123 | // from the global namespace. With this using declaration, 124 | // overloads of << defined in the global namespace and those 125 | // visible via Koenig lookup are both exposed in this function. 126 | using ::operator <<; 127 | *ss_ << val; 128 | return *this; 129 | } 130 | 131 | // Streams a pointer value to this object. 132 | // 133 | // This function is an overload of the previous one. When you 134 | // stream a pointer to a Message, this definition will be used as it 135 | // is more specialized. (The C++ Standard, section 136 | // [temp.func.order].) If you stream a non-pointer, then the 137 | // previous definition will be used. 138 | // 139 | // The reason for this overload is that streaming a NULL pointer to 140 | // ostream is undefined behavior. Depending on the compiler, you 141 | // may get "0", "(nil)", "(null)", or an access violation. To 142 | // ensure consistent result across compilers, we always treat NULL 143 | // as "(null)". 144 | template 145 | inline Message& operator <<(T* const& pointer) { // NOLINT 146 | if (pointer == nullptr) { 147 | *ss_ << "(null)"; 148 | } else { 149 | *ss_ << pointer; 150 | } 151 | return *this; 152 | } 153 | 154 | // Since the basic IO manipulators are overloaded for both narrow 155 | // and wide streams, we have to provide this specialized definition 156 | // of operator <<, even though its body is the same as the 157 | // templatized version above. Without this definition, streaming 158 | // endl or other basic IO manipulators to Message will confuse the 159 | // compiler. 160 | Message& operator <<(BasicNarrowIoManip val) { 161 | *ss_ << val; 162 | return *this; 163 | } 164 | 165 | // Instead of 1/0, we want to see true/false for bool values. 166 | Message& operator <<(bool b) { 167 | return *this << (b ? "true" : "false"); 168 | } 169 | 170 | // These two overloads allow streaming a wide C string to a Message 171 | // using the UTF-8 encoding. 172 | Message& operator <<(const wchar_t* wide_c_str); 173 | Message& operator <<(wchar_t* wide_c_str); 174 | 175 | #if GTEST_HAS_STD_WSTRING 176 | // Converts the given wide string to a narrow string using the UTF-8 177 | // encoding, and streams the result to this Message object. 178 | Message& operator <<(const ::std::wstring& wstr); 179 | #endif // GTEST_HAS_STD_WSTRING 180 | 181 | // Gets the text streamed to this object so far as an std::string. 182 | // Each '\0' character in the buffer is replaced with "\\0". 183 | // 184 | // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 185 | std::string GetString() const; 186 | 187 | private: 188 | // We'll hold the text streamed to this object here. 189 | const std::unique_ptr< ::std::stringstream> ss_; 190 | 191 | // We declare (but don't implement) this to prevent the compiler 192 | // from implementing the assignment operator. 193 | void operator=(const Message&); 194 | }; 195 | 196 | // Streams a Message to an ostream. 197 | inline std::ostream& operator <<(std::ostream& os, const Message& sb) { 198 | return os << sb.GetString(); 199 | } 200 | 201 | namespace internal { 202 | 203 | // Converts a streamable value to an std::string. A NULL pointer is 204 | // converted to "(null)". When the input value is a ::string, 205 | // ::std::string, ::wstring, or ::std::wstring object, each NUL 206 | // character in it is replaced with "\\0". 207 | template 208 | std::string StreamableToString(const T& streamable) { 209 | return (Message() << streamable).GetString(); 210 | } 211 | 212 | } // namespace internal 213 | } // namespace testing 214 | 215 | GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 216 | 217 | #endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 218 | -------------------------------------------------------------------------------- /test/include/gtest/gtest-spi.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // 31 | // Utilities for testing Google Test itself and code that uses Google Test 32 | // (e.g. frameworks built on top of Google Test). 33 | 34 | #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_ 35 | #define GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_ 36 | 37 | #include "gtest/gtest.h" 38 | 39 | GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ 40 | /* class A needs to have dll-interface to be used by clients of class B */) 41 | 42 | namespace testing { 43 | 44 | // This helper class can be used to mock out Google Test failure reporting 45 | // so that we can test Google Test or code that builds on Google Test. 46 | // 47 | // An object of this class appends a TestPartResult object to the 48 | // TestPartResultArray object given in the constructor whenever a Google Test 49 | // failure is reported. It can either intercept only failures that are 50 | // generated in the same thread that created this object or it can intercept 51 | // all generated failures. The scope of this mock object can be controlled with 52 | // the second argument to the two arguments constructor. 53 | class GTEST_API_ ScopedFakeTestPartResultReporter 54 | : public TestPartResultReporterInterface { 55 | public: 56 | // The two possible mocking modes of this object. 57 | enum InterceptMode { 58 | INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. 59 | INTERCEPT_ALL_THREADS // Intercepts all failures. 60 | }; 61 | 62 | // The c'tor sets this object as the test part result reporter used 63 | // by Google Test. The 'result' parameter specifies where to report the 64 | // results. This reporter will only catch failures generated in the current 65 | // thread. DEPRECATED 66 | explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); 67 | 68 | // Same as above, but you can choose the interception scope of this object. 69 | ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, 70 | TestPartResultArray* result); 71 | 72 | // The d'tor restores the previous test part result reporter. 73 | ~ScopedFakeTestPartResultReporter() override; 74 | 75 | // Appends the TestPartResult object to the TestPartResultArray 76 | // received in the constructor. 77 | // 78 | // This method is from the TestPartResultReporterInterface 79 | // interface. 80 | void ReportTestPartResult(const TestPartResult& result) override; 81 | 82 | private: 83 | void Init(); 84 | 85 | const InterceptMode intercept_mode_; 86 | TestPartResultReporterInterface* old_reporter_; 87 | TestPartResultArray* const result_; 88 | 89 | GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); 90 | }; 91 | 92 | namespace internal { 93 | 94 | // A helper class for implementing EXPECT_FATAL_FAILURE() and 95 | // EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given 96 | // TestPartResultArray contains exactly one failure that has the given 97 | // type and contains the given substring. If that's not the case, a 98 | // non-fatal failure will be generated. 99 | class GTEST_API_ SingleFailureChecker { 100 | public: 101 | // The constructor remembers the arguments. 102 | SingleFailureChecker(const TestPartResultArray* results, 103 | TestPartResult::Type type, const std::string& substr); 104 | ~SingleFailureChecker(); 105 | private: 106 | const TestPartResultArray* const results_; 107 | const TestPartResult::Type type_; 108 | const std::string substr_; 109 | 110 | GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); 111 | }; 112 | 113 | } // namespace internal 114 | 115 | } // namespace testing 116 | 117 | GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 118 | 119 | // A set of macros for testing Google Test assertions or code that's expected 120 | // to generate Google Test fatal failures. It verifies that the given 121 | // statement will cause exactly one fatal Google Test failure with 'substr' 122 | // being part of the failure message. 123 | // 124 | // There are two different versions of this macro. EXPECT_FATAL_FAILURE only 125 | // affects and considers failures generated in the current thread and 126 | // EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. 127 | // 128 | // The verification of the assertion is done correctly even when the statement 129 | // throws an exception or aborts the current function. 130 | // 131 | // Known restrictions: 132 | // - 'statement' cannot reference local non-static variables or 133 | // non-static members of the current object. 134 | // - 'statement' cannot return a value. 135 | // - You cannot stream a failure message to this macro. 136 | // 137 | // Note that even though the implementations of the following two 138 | // macros are much alike, we cannot refactor them to use a common 139 | // helper macro, due to some peculiarity in how the preprocessor 140 | // works. The AcceptsMacroThatExpandsToUnprotectedComma test in 141 | // gtest_unittest.cc will fail to compile if we do that. 142 | #define EXPECT_FATAL_FAILURE(statement, substr) \ 143 | do { \ 144 | class GTestExpectFatalFailureHelper {\ 145 | public:\ 146 | static void Execute() { statement; }\ 147 | };\ 148 | ::testing::TestPartResultArray gtest_failures;\ 149 | ::testing::internal::SingleFailureChecker gtest_checker(\ 150 | >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ 151 | {\ 152 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 153 | ::testing::ScopedFakeTestPartResultReporter:: \ 154 | INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ 155 | GTestExpectFatalFailureHelper::Execute();\ 156 | }\ 157 | } while (::testing::internal::AlwaysFalse()) 158 | 159 | #define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ 160 | do { \ 161 | class GTestExpectFatalFailureHelper {\ 162 | public:\ 163 | static void Execute() { statement; }\ 164 | };\ 165 | ::testing::TestPartResultArray gtest_failures;\ 166 | ::testing::internal::SingleFailureChecker gtest_checker(\ 167 | >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ 168 | {\ 169 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 170 | ::testing::ScopedFakeTestPartResultReporter:: \ 171 | INTERCEPT_ALL_THREADS, >est_failures);\ 172 | GTestExpectFatalFailureHelper::Execute();\ 173 | }\ 174 | } while (::testing::internal::AlwaysFalse()) 175 | 176 | // A macro for testing Google Test assertions or code that's expected to 177 | // generate Google Test non-fatal failures. It asserts that the given 178 | // statement will cause exactly one non-fatal Google Test failure with 'substr' 179 | // being part of the failure message. 180 | // 181 | // There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only 182 | // affects and considers failures generated in the current thread and 183 | // EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. 184 | // 185 | // 'statement' is allowed to reference local variables and members of 186 | // the current object. 187 | // 188 | // The verification of the assertion is done correctly even when the statement 189 | // throws an exception or aborts the current function. 190 | // 191 | // Known restrictions: 192 | // - You cannot stream a failure message to this macro. 193 | // 194 | // Note that even though the implementations of the following two 195 | // macros are much alike, we cannot refactor them to use a common 196 | // helper macro, due to some peculiarity in how the preprocessor 197 | // works. If we do that, the code won't compile when the user gives 198 | // EXPECT_NONFATAL_FAILURE() a statement that contains a macro that 199 | // expands to code containing an unprotected comma. The 200 | // AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc 201 | // catches that. 202 | // 203 | // For the same reason, we have to write 204 | // if (::testing::internal::AlwaysTrue()) { statement; } 205 | // instead of 206 | // GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) 207 | // to avoid an MSVC warning on unreachable code. 208 | #define EXPECT_NONFATAL_FAILURE(statement, substr) \ 209 | do {\ 210 | ::testing::TestPartResultArray gtest_failures;\ 211 | ::testing::internal::SingleFailureChecker gtest_checker(\ 212 | >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ 213 | (substr));\ 214 | {\ 215 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 216 | ::testing::ScopedFakeTestPartResultReporter:: \ 217 | INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ 218 | if (::testing::internal::AlwaysTrue()) { statement; }\ 219 | }\ 220 | } while (::testing::internal::AlwaysFalse()) 221 | 222 | #define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ 223 | do {\ 224 | ::testing::TestPartResultArray gtest_failures;\ 225 | ::testing::internal::SingleFailureChecker gtest_checker(\ 226 | >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ 227 | (substr));\ 228 | {\ 229 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 230 | ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ 231 | >est_failures);\ 232 | if (::testing::internal::AlwaysTrue()) { statement; }\ 233 | }\ 234 | } while (::testing::internal::AlwaysFalse()) 235 | 236 | #endif // GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_ 237 | -------------------------------------------------------------------------------- /test/include/gtest/gtest-test-part.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 31 | #define GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 32 | 33 | #include 34 | #include 35 | #include "gtest/internal/gtest-internal.h" 36 | #include "gtest/internal/gtest-string.h" 37 | 38 | GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ 39 | /* class A needs to have dll-interface to be used by clients of class B */) 40 | 41 | namespace testing { 42 | 43 | // A copyable object representing the result of a test part (i.e. an 44 | // assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). 45 | // 46 | // Don't inherit from TestPartResult as its destructor is not virtual. 47 | class GTEST_API_ TestPartResult { 48 | public: 49 | // The possible outcomes of a test part (i.e. an assertion or an 50 | // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). 51 | enum Type { 52 | kSuccess, // Succeeded. 53 | kNonFatalFailure, // Failed but the test can continue. 54 | kFatalFailure, // Failed and the test should be terminated. 55 | kSkip // Skipped. 56 | }; 57 | 58 | // C'tor. TestPartResult does NOT have a default constructor. 59 | // Always use this constructor (with parameters) to create a 60 | // TestPartResult object. 61 | TestPartResult(Type a_type, const char* a_file_name, int a_line_number, 62 | const char* a_message) 63 | : type_(a_type), 64 | file_name_(a_file_name == nullptr ? "" : a_file_name), 65 | line_number_(a_line_number), 66 | summary_(ExtractSummary(a_message)), 67 | message_(a_message) {} 68 | 69 | // Gets the outcome of the test part. 70 | Type type() const { return type_; } 71 | 72 | // Gets the name of the source file where the test part took place, or 73 | // NULL if it's unknown. 74 | const char* file_name() const { 75 | return file_name_.empty() ? nullptr : file_name_.c_str(); 76 | } 77 | 78 | // Gets the line in the source file where the test part took place, 79 | // or -1 if it's unknown. 80 | int line_number() const { return line_number_; } 81 | 82 | // Gets the summary of the failure message. 83 | const char* summary() const { return summary_.c_str(); } 84 | 85 | // Gets the message associated with the test part. 86 | const char* message() const { return message_.c_str(); } 87 | 88 | // Returns true if and only if the test part was skipped. 89 | bool skipped() const { return type_ == kSkip; } 90 | 91 | // Returns true if and only if the test part passed. 92 | bool passed() const { return type_ == kSuccess; } 93 | 94 | // Returns true if and only if the test part non-fatally failed. 95 | bool nonfatally_failed() const { return type_ == kNonFatalFailure; } 96 | 97 | // Returns true if and only if the test part fatally failed. 98 | bool fatally_failed() const { return type_ == kFatalFailure; } 99 | 100 | // Returns true if and only if the test part failed. 101 | bool failed() const { return fatally_failed() || nonfatally_failed(); } 102 | 103 | private: 104 | Type type_; 105 | 106 | // Gets the summary of the failure message by omitting the stack 107 | // trace in it. 108 | static std::string ExtractSummary(const char* message); 109 | 110 | // The name of the source file where the test part took place, or 111 | // "" if the source file is unknown. 112 | std::string file_name_; 113 | // The line in the source file where the test part took place, or -1 114 | // if the line number is unknown. 115 | int line_number_; 116 | std::string summary_; // The test failure summary. 117 | std::string message_; // The test failure message. 118 | }; 119 | 120 | // Prints a TestPartResult object. 121 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result); 122 | 123 | // An array of TestPartResult objects. 124 | // 125 | // Don't inherit from TestPartResultArray as its destructor is not 126 | // virtual. 127 | class GTEST_API_ TestPartResultArray { 128 | public: 129 | TestPartResultArray() {} 130 | 131 | // Appends the given TestPartResult to the array. 132 | void Append(const TestPartResult& result); 133 | 134 | // Returns the TestPartResult at the given index (0-based). 135 | const TestPartResult& GetTestPartResult(int index) const; 136 | 137 | // Returns the number of TestPartResult objects in the array. 138 | int size() const; 139 | 140 | private: 141 | std::vector array_; 142 | 143 | GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); 144 | }; 145 | 146 | // This interface knows how to report a test part result. 147 | class GTEST_API_ TestPartResultReporterInterface { 148 | public: 149 | virtual ~TestPartResultReporterInterface() {} 150 | 151 | virtual void ReportTestPartResult(const TestPartResult& result) = 0; 152 | }; 153 | 154 | namespace internal { 155 | 156 | // This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a 157 | // statement generates new fatal failures. To do so it registers itself as the 158 | // current test part result reporter. Besides checking if fatal failures were 159 | // reported, it only delegates the reporting to the former result reporter. 160 | // The original result reporter is restored in the destructor. 161 | // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 162 | class GTEST_API_ HasNewFatalFailureHelper 163 | : public TestPartResultReporterInterface { 164 | public: 165 | HasNewFatalFailureHelper(); 166 | ~HasNewFatalFailureHelper() override; 167 | void ReportTestPartResult(const TestPartResult& result) override; 168 | bool has_new_fatal_failure() const { return has_new_fatal_failure_; } 169 | private: 170 | bool has_new_fatal_failure_; 171 | TestPartResultReporterInterface* original_reporter_; 172 | 173 | GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); 174 | }; 175 | 176 | } // namespace internal 177 | 178 | } // namespace testing 179 | 180 | GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 181 | 182 | #endif // GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 183 | -------------------------------------------------------------------------------- /test/include/gtest/gtest_prod.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // 31 | // Google C++ Testing and Mocking Framework definitions useful in production code. 32 | 33 | #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ 34 | #define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ 35 | 36 | // When you need to test the private or protected members of a class, 37 | // use the FRIEND_TEST macro to declare your tests as friends of the 38 | // class. For example: 39 | // 40 | // class MyClass { 41 | // private: 42 | // void PrivateMethod(); 43 | // FRIEND_TEST(MyClassTest, PrivateMethodWorks); 44 | // }; 45 | // 46 | // class MyClassTest : public testing::Test { 47 | // // ... 48 | // }; 49 | // 50 | // TEST_F(MyClassTest, PrivateMethodWorks) { 51 | // // Can call MyClass::PrivateMethod() here. 52 | // } 53 | // 54 | // Note: The test class must be in the same namespace as the class being tested. 55 | // For example, putting MyClassTest in an anonymous namespace will not work. 56 | 57 | #define FRIEND_TEST(test_case_name, test_name)\ 58 | friend class test_case_name##_##test_name##_Test 59 | 60 | #endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ 61 | -------------------------------------------------------------------------------- /test/include/gtest/internal/custom/README.md: -------------------------------------------------------------------------------- 1 | # Customization Points 2 | 3 | The custom directory is an injection point for custom user configurations. 4 | 5 | ## Header `gtest.h` 6 | 7 | ### The following macros can be defined: 8 | 9 | * `GTEST_OS_STACK_TRACE_GETTER_` - The name of an implementation of 10 | `OsStackTraceGetterInterface`. 11 | * `GTEST_CUSTOM_TEMPDIR_FUNCTION_` - An override for `testing::TempDir()`. See 12 | `testing::TempDir` for semantics and signature. 13 | 14 | ## Header `gtest-port.h` 15 | 16 | The following macros can be defined: 17 | 18 | ### Flag related macros: 19 | 20 | * `GTEST_FLAG(flag_name)` 21 | * `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its 22 | own flagfile flag parsing. 23 | * `GTEST_DECLARE_bool_(name)` 24 | * `GTEST_DECLARE_int32_(name)` 25 | * `GTEST_DECLARE_string_(name)` 26 | * `GTEST_DEFINE_bool_(name, default_val, doc)` 27 | * `GTEST_DEFINE_int32_(name, default_val, doc)` 28 | * `GTEST_DEFINE_string_(name, default_val, doc)` 29 | * `GTEST_FLAG_GET(flag_name)` 30 | * `GTEST_FLAG_SET(flag_name, value)` 31 | 32 | ### Logging: 33 | 34 | * `GTEST_LOG_(severity)` 35 | * `GTEST_CHECK_(condition)` 36 | * Functions `LogToStderr()` and `FlushInfoLog()` have to be provided too. 37 | 38 | ### Threading: 39 | 40 | * `GTEST_HAS_NOTIFICATION_` - Enabled if Notification is already provided. 41 | * `GTEST_HAS_MUTEX_AND_THREAD_LOCAL_` - Enabled if `Mutex` and `ThreadLocal` 42 | are already provided. Must also provide `GTEST_DECLARE_STATIC_MUTEX_(mutex)` 43 | and `GTEST_DEFINE_STATIC_MUTEX_(mutex)` 44 | * `GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)` 45 | * `GTEST_LOCK_EXCLUDED_(locks)` 46 | 47 | ### Underlying library support features 48 | 49 | * `GTEST_HAS_CXXABI_H_` 50 | 51 | ### Exporting API symbols: 52 | 53 | * `GTEST_API_` - Specifier for exported symbols. 54 | 55 | ## Header `gtest-printers.h` 56 | 57 | * See documentation at `gtest/gtest-printers.h` for details on how to define a 58 | custom printer. 59 | -------------------------------------------------------------------------------- /test/include/gtest/internal/custom/gtest-port.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Injection point for custom user configurations. See README for details 31 | // 32 | // ** Custom implementation starts here ** 33 | 34 | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 35 | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 36 | 37 | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 38 | -------------------------------------------------------------------------------- /test/include/gtest/internal/custom/gtest-printers.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // This file provides an injection point for custom printers in a local 31 | // installation of gTest. 32 | // It will be included from gtest-printers.h and the overrides in this file 33 | // will be visible to everyone. 34 | // 35 | // Injection point for custom user configurations. See README for details 36 | // 37 | // ** Custom implementation starts here ** 38 | 39 | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 40 | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 41 | 42 | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 43 | -------------------------------------------------------------------------------- /test/include/gtest/internal/custom/gtest.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Injection point for custom user configurations. See README for details 31 | // 32 | // ** Custom implementation starts here ** 33 | 34 | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 35 | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 36 | 37 | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 38 | -------------------------------------------------------------------------------- /test/include/gtest/internal/gtest-death-test-internal.h: -------------------------------------------------------------------------------- 1 | // Copyright 2005, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // The Google C++ Testing and Mocking Framework (Google Test) 31 | // 32 | // This header file defines internal utilities needed for implementing 33 | // death tests. They are subject to change without notice. 34 | 35 | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ 36 | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ 37 | 38 | #include "gtest/gtest-matchers.h" 39 | #include "gtest/internal/gtest-internal.h" 40 | 41 | #include 42 | #include 43 | 44 | GTEST_DECLARE_string_(internal_run_death_test); 45 | 46 | namespace testing { 47 | namespace internal { 48 | 49 | // Names of the flags (needed for parsing Google Test flags). 50 | const char kDeathTestStyleFlag[] = "death_test_style"; 51 | const char kDeathTestUseFork[] = "death_test_use_fork"; 52 | const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; 53 | 54 | #if GTEST_HAS_DEATH_TEST 55 | 56 | GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ 57 | /* class A needs to have dll-interface to be used by clients of class B */) 58 | 59 | // DeathTest is a class that hides much of the complexity of the 60 | // GTEST_DEATH_TEST_ macro. It is abstract; its static Create method 61 | // returns a concrete class that depends on the prevailing death test 62 | // style, as defined by the --gtest_death_test_style and/or 63 | // --gtest_internal_run_death_test flags. 64 | 65 | // In describing the results of death tests, these terms are used with 66 | // the corresponding definitions: 67 | // 68 | // exit status: The integer exit information in the format specified 69 | // by wait(2) 70 | // exit code: The integer code passed to exit(3), _exit(2), or 71 | // returned from main() 72 | class GTEST_API_ DeathTest { 73 | public: 74 | // Create returns false if there was an error determining the 75 | // appropriate action to take for the current death test; for example, 76 | // if the gtest_death_test_style flag is set to an invalid value. 77 | // The LastMessage method will return a more detailed message in that 78 | // case. Otherwise, the DeathTest pointer pointed to by the "test" 79 | // argument is set. If the death test should be skipped, the pointer 80 | // is set to NULL; otherwise, it is set to the address of a new concrete 81 | // DeathTest object that controls the execution of the current test. 82 | static bool Create(const char* statement, Matcher matcher, 83 | const char* file, int line, DeathTest** test); 84 | DeathTest(); 85 | virtual ~DeathTest() { } 86 | 87 | // A helper class that aborts a death test when it's deleted. 88 | class ReturnSentinel { 89 | public: 90 | explicit ReturnSentinel(DeathTest* test) : test_(test) { } 91 | ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } 92 | private: 93 | DeathTest* const test_; 94 | GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); 95 | } GTEST_ATTRIBUTE_UNUSED_; 96 | 97 | // An enumeration of possible roles that may be taken when a death 98 | // test is encountered. EXECUTE means that the death test logic should 99 | // be executed immediately. OVERSEE means that the program should prepare 100 | // the appropriate environment for a child process to execute the death 101 | // test, then wait for it to complete. 102 | enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; 103 | 104 | // An enumeration of the three reasons that a test might be aborted. 105 | enum AbortReason { 106 | TEST_ENCOUNTERED_RETURN_STATEMENT, 107 | TEST_THREW_EXCEPTION, 108 | TEST_DID_NOT_DIE 109 | }; 110 | 111 | // Assumes one of the above roles. 112 | virtual TestRole AssumeRole() = 0; 113 | 114 | // Waits for the death test to finish and returns its status. 115 | virtual int Wait() = 0; 116 | 117 | // Returns true if the death test passed; that is, the test process 118 | // exited during the test, its exit status matches a user-supplied 119 | // predicate, and its stderr output matches a user-supplied regular 120 | // expression. 121 | // The user-supplied predicate may be a macro expression rather 122 | // than a function pointer or functor, or else Wait and Passed could 123 | // be combined. 124 | virtual bool Passed(bool exit_status_ok) = 0; 125 | 126 | // Signals that the death test did not die as expected. 127 | virtual void Abort(AbortReason reason) = 0; 128 | 129 | // Returns a human-readable outcome message regarding the outcome of 130 | // the last death test. 131 | static const char* LastMessage(); 132 | 133 | static void set_last_death_test_message(const std::string& message); 134 | 135 | private: 136 | // A string containing a description of the outcome of the last death test. 137 | static std::string last_death_test_message_; 138 | 139 | GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); 140 | }; 141 | 142 | GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 143 | 144 | // Factory interface for death tests. May be mocked out for testing. 145 | class DeathTestFactory { 146 | public: 147 | virtual ~DeathTestFactory() { } 148 | virtual bool Create(const char* statement, 149 | Matcher matcher, const char* file, 150 | int line, DeathTest** test) = 0; 151 | }; 152 | 153 | // A concrete DeathTestFactory implementation for normal use. 154 | class DefaultDeathTestFactory : public DeathTestFactory { 155 | public: 156 | bool Create(const char* statement, Matcher matcher, 157 | const char* file, int line, DeathTest** test) override; 158 | }; 159 | 160 | // Returns true if exit_status describes a process that was terminated 161 | // by a signal, or exited normally with a nonzero exit code. 162 | GTEST_API_ bool ExitedUnsuccessfully(int exit_status); 163 | 164 | // A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads 165 | // and interpreted as a regex (rather than an Eq matcher) for legacy 166 | // compatibility. 167 | inline Matcher MakeDeathTestMatcher( 168 | ::testing::internal::RE regex) { 169 | return ContainsRegex(regex.pattern()); 170 | } 171 | inline Matcher MakeDeathTestMatcher(const char* regex) { 172 | return ContainsRegex(regex); 173 | } 174 | inline Matcher MakeDeathTestMatcher( 175 | const ::std::string& regex) { 176 | return ContainsRegex(regex); 177 | } 178 | 179 | // If a Matcher is passed to EXPECT_DEATH (etc.), it's 180 | // used directly. 181 | inline Matcher MakeDeathTestMatcher( 182 | Matcher matcher) { 183 | return matcher; 184 | } 185 | 186 | // Traps C++ exceptions escaping statement and reports them as test 187 | // failures. Note that trapping SEH exceptions is not implemented here. 188 | # if GTEST_HAS_EXCEPTIONS 189 | # define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ 190 | try { \ 191 | GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ 192 | } catch (const ::std::exception& gtest_exception) { \ 193 | fprintf(\ 194 | stderr, \ 195 | "\n%s: Caught std::exception-derived exception escaping the " \ 196 | "death test statement. Exception message: %s\n", \ 197 | ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ 198 | gtest_exception.what()); \ 199 | fflush(stderr); \ 200 | death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ 201 | } catch (...) { \ 202 | death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ 203 | } 204 | 205 | # else 206 | # define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ 207 | GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) 208 | 209 | # endif 210 | 211 | // This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, 212 | // ASSERT_EXIT*, and EXPECT_EXIT*. 213 | #define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail) \ 214 | GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 215 | if (::testing::internal::AlwaysTrue()) { \ 216 | ::testing::internal::DeathTest* gtest_dt; \ 217 | if (!::testing::internal::DeathTest::Create( \ 218 | #statement, \ 219 | ::testing::internal::MakeDeathTestMatcher(regex_or_matcher), \ 220 | __FILE__, __LINE__, >est_dt)) { \ 221 | goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ 222 | } \ 223 | if (gtest_dt != nullptr) { \ 224 | std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \ 225 | switch (gtest_dt->AssumeRole()) { \ 226 | case ::testing::internal::DeathTest::OVERSEE_TEST: \ 227 | if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ 228 | goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ 229 | } \ 230 | break; \ 231 | case ::testing::internal::DeathTest::EXECUTE_TEST: { \ 232 | ::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \ 233 | gtest_dt); \ 234 | GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ 235 | gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ 236 | break; \ 237 | } \ 238 | } \ 239 | } \ 240 | } else \ 241 | GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__) \ 242 | : fail(::testing::internal::DeathTest::LastMessage()) 243 | // The symbol "fail" here expands to something into which a message 244 | // can be streamed. 245 | 246 | // This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in 247 | // NDEBUG mode. In this case we need the statements to be executed and the macro 248 | // must accept a streamed message even though the message is never printed. 249 | // The regex object is not evaluated, but it is used to prevent "unused" 250 | // warnings and to avoid an expression that doesn't compile in debug mode. 251 | #define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \ 252 | GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 253 | if (::testing::internal::AlwaysTrue()) { \ 254 | GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ 255 | } else if (!::testing::internal::AlwaysTrue()) { \ 256 | ::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \ 257 | } else \ 258 | ::testing::Message() 259 | 260 | // A class representing the parsed contents of the 261 | // --gtest_internal_run_death_test flag, as it existed when 262 | // RUN_ALL_TESTS was called. 263 | class InternalRunDeathTestFlag { 264 | public: 265 | InternalRunDeathTestFlag(const std::string& a_file, 266 | int a_line, 267 | int an_index, 268 | int a_write_fd) 269 | : file_(a_file), line_(a_line), index_(an_index), 270 | write_fd_(a_write_fd) {} 271 | 272 | ~InternalRunDeathTestFlag() { 273 | if (write_fd_ >= 0) 274 | posix::Close(write_fd_); 275 | } 276 | 277 | const std::string& file() const { return file_; } 278 | int line() const { return line_; } 279 | int index() const { return index_; } 280 | int write_fd() const { return write_fd_; } 281 | 282 | private: 283 | std::string file_; 284 | int line_; 285 | int index_; 286 | int write_fd_; 287 | 288 | GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); 289 | }; 290 | 291 | // Returns a newly created InternalRunDeathTestFlag object with fields 292 | // initialized from the GTEST_FLAG(internal_run_death_test) flag if 293 | // the flag is specified; otherwise returns NULL. 294 | InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); 295 | 296 | #endif // GTEST_HAS_DEATH_TEST 297 | 298 | } // namespace internal 299 | } // namespace testing 300 | 301 | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ 302 | -------------------------------------------------------------------------------- /test/include/gtest/internal/gtest-filepath.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Google Test filepath utilities 31 | // 32 | // This header file declares classes and functions used internally by 33 | // Google Test. They are subject to change without notice. 34 | // 35 | // This file is #included in gtest/internal/gtest-internal.h. 36 | // Do not include this header file separately! 37 | 38 | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 39 | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 40 | 41 | #include "gtest/internal/gtest-string.h" 42 | 43 | GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ 44 | /* class A needs to have dll-interface to be used by clients of class B */) 45 | 46 | namespace testing { 47 | namespace internal { 48 | 49 | // FilePath - a class for file and directory pathname manipulation which 50 | // handles platform-specific conventions (like the pathname separator). 51 | // Used for helper functions for naming files in a directory for xml output. 52 | // Except for Set methods, all methods are const or static, which provides an 53 | // "immutable value object" -- useful for peace of mind. 54 | // A FilePath with a value ending in a path separator ("like/this/") represents 55 | // a directory, otherwise it is assumed to represent a file. In either case, 56 | // it may or may not represent an actual file or directory in the file system. 57 | // Names are NOT checked for syntax correctness -- no checking for illegal 58 | // characters, malformed paths, etc. 59 | 60 | class GTEST_API_ FilePath { 61 | public: 62 | FilePath() : pathname_("") { } 63 | FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } 64 | 65 | explicit FilePath(const std::string& pathname) : pathname_(pathname) { 66 | Normalize(); 67 | } 68 | 69 | FilePath& operator=(const FilePath& rhs) { 70 | Set(rhs); 71 | return *this; 72 | } 73 | 74 | void Set(const FilePath& rhs) { 75 | pathname_ = rhs.pathname_; 76 | } 77 | 78 | const std::string& string() const { return pathname_; } 79 | const char* c_str() const { return pathname_.c_str(); } 80 | 81 | // Returns the current working directory, or "" if unsuccessful. 82 | static FilePath GetCurrentDir(); 83 | 84 | // Given directory = "dir", base_name = "test", number = 0, 85 | // extension = "xml", returns "dir/test.xml". If number is greater 86 | // than zero (e.g., 12), returns "dir/test_12.xml". 87 | // On Windows platform, uses \ as the separator rather than /. 88 | static FilePath MakeFileName(const FilePath& directory, 89 | const FilePath& base_name, 90 | int number, 91 | const char* extension); 92 | 93 | // Given directory = "dir", relative_path = "test.xml", 94 | // returns "dir/test.xml". 95 | // On Windows, uses \ as the separator rather than /. 96 | static FilePath ConcatPaths(const FilePath& directory, 97 | const FilePath& relative_path); 98 | 99 | // Returns a pathname for a file that does not currently exist. The pathname 100 | // will be directory/base_name.extension or 101 | // directory/base_name_.extension if directory/base_name.extension 102 | // already exists. The number will be incremented until a pathname is found 103 | // that does not already exist. 104 | // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. 105 | // There could be a race condition if two or more processes are calling this 106 | // function at the same time -- they could both pick the same filename. 107 | static FilePath GenerateUniqueFileName(const FilePath& directory, 108 | const FilePath& base_name, 109 | const char* extension); 110 | 111 | // Returns true if and only if the path is "". 112 | bool IsEmpty() const { return pathname_.empty(); } 113 | 114 | // If input name has a trailing separator character, removes it and returns 115 | // the name, otherwise return the name string unmodified. 116 | // On Windows platform, uses \ as the separator, other platforms use /. 117 | FilePath RemoveTrailingPathSeparator() const; 118 | 119 | // Returns a copy of the FilePath with the directory part removed. 120 | // Example: FilePath("path/to/file").RemoveDirectoryName() returns 121 | // FilePath("file"). If there is no directory part ("just_a_file"), it returns 122 | // the FilePath unmodified. If there is no file part ("just_a_dir/") it 123 | // returns an empty FilePath (""). 124 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 125 | FilePath RemoveDirectoryName() const; 126 | 127 | // RemoveFileName returns the directory path with the filename removed. 128 | // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". 129 | // If the FilePath is "a_file" or "/a_file", RemoveFileName returns 130 | // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does 131 | // not have a file, like "just/a/dir/", it returns the FilePath unmodified. 132 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 133 | FilePath RemoveFileName() const; 134 | 135 | // Returns a copy of the FilePath with the case-insensitive extension removed. 136 | // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns 137 | // FilePath("dir/file"). If a case-insensitive extension is not 138 | // found, returns a copy of the original FilePath. 139 | FilePath RemoveExtension(const char* extension) const; 140 | 141 | // Creates directories so that path exists. Returns true if successful or if 142 | // the directories already exist; returns false if unable to create 143 | // directories for any reason. Will also return false if the FilePath does 144 | // not represent a directory (that is, it doesn't end with a path separator). 145 | bool CreateDirectoriesRecursively() const; 146 | 147 | // Create the directory so that path exists. Returns true if successful or 148 | // if the directory already exists; returns false if unable to create the 149 | // directory for any reason, including if the parent directory does not 150 | // exist. Not named "CreateDirectory" because that's a macro on Windows. 151 | bool CreateFolder() const; 152 | 153 | // Returns true if FilePath describes something in the file-system, 154 | // either a file, directory, or whatever, and that something exists. 155 | bool FileOrDirectoryExists() const; 156 | 157 | // Returns true if pathname describes a directory in the file-system 158 | // that exists. 159 | bool DirectoryExists() const; 160 | 161 | // Returns true if FilePath ends with a path separator, which indicates that 162 | // it is intended to represent a directory. Returns false otherwise. 163 | // This does NOT check that a directory (or file) actually exists. 164 | bool IsDirectory() const; 165 | 166 | // Returns true if pathname describes a root directory. (Windows has one 167 | // root directory per disk drive.) 168 | bool IsRootDirectory() const; 169 | 170 | // Returns true if pathname describes an absolute path. 171 | bool IsAbsolutePath() const; 172 | 173 | private: 174 | // Replaces multiple consecutive separators with a single separator. 175 | // For example, "bar///foo" becomes "bar/foo". Does not eliminate other 176 | // redundancies that might be in a pathname involving "." or "..". 177 | // 178 | // A pathname with multiple consecutive separators may occur either through 179 | // user error or as a result of some scripts or APIs that generate a pathname 180 | // with a trailing separator. On other platforms the same API or script 181 | // may NOT generate a pathname with a trailing "/". Then elsewhere that 182 | // pathname may have another "/" and pathname components added to it, 183 | // without checking for the separator already being there. 184 | // The script language and operating system may allow paths like "foo//bar" 185 | // but some of the functions in FilePath will not handle that correctly. In 186 | // particular, RemoveTrailingPathSeparator() only removes one separator, and 187 | // it is called in CreateDirectoriesRecursively() assuming that it will change 188 | // a pathname from directory syntax (trailing separator) to filename syntax. 189 | // 190 | // On Windows this method also replaces the alternate path separator '/' with 191 | // the primary path separator '\\', so that for example "bar\\/\\foo" becomes 192 | // "bar\\foo". 193 | 194 | void Normalize(); 195 | 196 | // Returns a pointer to the last occurrence of a valid path separator in 197 | // the FilePath. On Windows, for example, both '/' and '\' are valid path 198 | // separators. Returns NULL if no path separator was found. 199 | const char* FindLastPathSeparator() const; 200 | 201 | std::string pathname_; 202 | }; // class FilePath 203 | 204 | } // namespace internal 205 | } // namespace testing 206 | 207 | GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 208 | 209 | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 210 | -------------------------------------------------------------------------------- /test/include/gtest/internal/gtest-port-arch.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // The Google C++ Testing and Mocking Framework (Google Test) 31 | // 32 | // This header file defines the GTEST_OS_* macro. 33 | // It is separate from gtest-port.h so that custom/gtest-port.h can include it. 34 | 35 | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 36 | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 37 | 38 | // Determines the platform on which Google Test is compiled. 39 | #ifdef __CYGWIN__ 40 | # define GTEST_OS_CYGWIN 1 41 | # elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__) 42 | # define GTEST_OS_WINDOWS_MINGW 1 43 | # define GTEST_OS_WINDOWS 1 44 | #elif defined _WIN32 45 | # define GTEST_OS_WINDOWS 1 46 | # ifdef _WIN32_WCE 47 | # define GTEST_OS_WINDOWS_MOBILE 1 48 | # elif defined(WINAPI_FAMILY) 49 | # include 50 | # if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 51 | # define GTEST_OS_WINDOWS_DESKTOP 1 52 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) 53 | # define GTEST_OS_WINDOWS_PHONE 1 54 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 55 | # define GTEST_OS_WINDOWS_RT 1 56 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE) 57 | # define GTEST_OS_WINDOWS_PHONE 1 58 | # define GTEST_OS_WINDOWS_TV_TITLE 1 59 | # else 60 | // WINAPI_FAMILY defined but no known partition matched. 61 | // Default to desktop. 62 | # define GTEST_OS_WINDOWS_DESKTOP 1 63 | # endif 64 | # else 65 | # define GTEST_OS_WINDOWS_DESKTOP 1 66 | # endif // _WIN32_WCE 67 | #elif defined __OS2__ 68 | # define GTEST_OS_OS2 1 69 | #elif defined __APPLE__ 70 | # define GTEST_OS_MAC 1 71 | # include 72 | # if TARGET_OS_IPHONE 73 | # define GTEST_OS_IOS 1 74 | # endif 75 | #elif defined __DragonFly__ 76 | # define GTEST_OS_DRAGONFLY 1 77 | #elif defined __FreeBSD__ 78 | # define GTEST_OS_FREEBSD 1 79 | #elif defined __Fuchsia__ 80 | # define GTEST_OS_FUCHSIA 1 81 | #elif defined(__GNU__) 82 | # define GTEST_OS_GNU_HURD 1 83 | #elif defined(__GLIBC__) && defined(__FreeBSD_kernel__) 84 | # define GTEST_OS_GNU_KFREEBSD 1 85 | #elif defined __linux__ 86 | # define GTEST_OS_LINUX 1 87 | # if defined __ANDROID__ 88 | # define GTEST_OS_LINUX_ANDROID 1 89 | # endif 90 | #elif defined __MVS__ 91 | # define GTEST_OS_ZOS 1 92 | #elif defined(__sun) && defined(__SVR4) 93 | # define GTEST_OS_SOLARIS 1 94 | #elif defined(_AIX) 95 | # define GTEST_OS_AIX 1 96 | #elif defined(__hpux) 97 | # define GTEST_OS_HPUX 1 98 | #elif defined __native_client__ 99 | # define GTEST_OS_NACL 1 100 | #elif defined __NetBSD__ 101 | # define GTEST_OS_NETBSD 1 102 | #elif defined __OpenBSD__ 103 | # define GTEST_OS_OPENBSD 1 104 | #elif defined __QNX__ 105 | # define GTEST_OS_QNX 1 106 | #elif defined(__HAIKU__) 107 | #define GTEST_OS_HAIKU 1 108 | #elif defined ESP8266 109 | #define GTEST_OS_ESP8266 1 110 | #elif defined ESP32 111 | #define GTEST_OS_ESP32 1 112 | #elif defined(__XTENSA__) 113 | #define GTEST_OS_XTENSA 1 114 | #endif // __CYGWIN__ 115 | 116 | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 117 | -------------------------------------------------------------------------------- /test/include/gtest/internal/gtest-string.h: -------------------------------------------------------------------------------- 1 | // Copyright 2005, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // The Google C++ Testing and Mocking Framework (Google Test) 31 | // 32 | // This header file declares the String class and functions used internally by 33 | // Google Test. They are subject to change without notice. They should not used 34 | // by code external to Google Test. 35 | // 36 | // This header file is #included by gtest-internal.h. 37 | // It should not be #included by other files. 38 | 39 | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 40 | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 41 | 42 | #ifdef __BORLANDC__ 43 | // string.h is not guaranteed to provide strcpy on C++ Builder. 44 | # include 45 | #endif 46 | 47 | #include 48 | #include 49 | #include 50 | 51 | #include "gtest/internal/gtest-port.h" 52 | 53 | namespace testing { 54 | namespace internal { 55 | 56 | // String - an abstract class holding static string utilities. 57 | class GTEST_API_ String { 58 | public: 59 | // Static utility methods 60 | 61 | // Clones a 0-terminated C string, allocating memory using new. The 62 | // caller is responsible for deleting the return value using 63 | // delete[]. Returns the cloned string, or NULL if the input is 64 | // NULL. 65 | // 66 | // This is different from strdup() in string.h, which allocates 67 | // memory using malloc(). 68 | static const char* CloneCString(const char* c_str); 69 | 70 | #if GTEST_OS_WINDOWS_MOBILE 71 | // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be 72 | // able to pass strings to Win32 APIs on CE we need to convert them 73 | // to 'Unicode', UTF-16. 74 | 75 | // Creates a UTF-16 wide string from the given ANSI string, allocating 76 | // memory using new. The caller is responsible for deleting the return 77 | // value using delete[]. Returns the wide string, or NULL if the 78 | // input is NULL. 79 | // 80 | // The wide string is created using the ANSI codepage (CP_ACP) to 81 | // match the behaviour of the ANSI versions of Win32 calls and the 82 | // C runtime. 83 | static LPCWSTR AnsiToUtf16(const char* c_str); 84 | 85 | // Creates an ANSI string from the given wide string, allocating 86 | // memory using new. The caller is responsible for deleting the return 87 | // value using delete[]. Returns the ANSI string, or NULL if the 88 | // input is NULL. 89 | // 90 | // The returned string is created using the ANSI codepage (CP_ACP) to 91 | // match the behaviour of the ANSI versions of Win32 calls and the 92 | // C runtime. 93 | static const char* Utf16ToAnsi(LPCWSTR utf16_str); 94 | #endif 95 | 96 | // Compares two C strings. Returns true if and only if they have the same 97 | // content. 98 | // 99 | // Unlike strcmp(), this function can handle NULL argument(s). A 100 | // NULL C string is considered different to any non-NULL C string, 101 | // including the empty string. 102 | static bool CStringEquals(const char* lhs, const char* rhs); 103 | 104 | // Converts a wide C string to a String using the UTF-8 encoding. 105 | // NULL will be converted to "(null)". If an error occurred during 106 | // the conversion, "(failed to convert from wide string)" is 107 | // returned. 108 | static std::string ShowWideCString(const wchar_t* wide_c_str); 109 | 110 | // Compares two wide C strings. Returns true if and only if they have the 111 | // same content. 112 | // 113 | // Unlike wcscmp(), this function can handle NULL argument(s). A 114 | // NULL C string is considered different to any non-NULL C string, 115 | // including the empty string. 116 | static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); 117 | 118 | // Compares two C strings, ignoring case. Returns true if and only if 119 | // they have the same content. 120 | // 121 | // Unlike strcasecmp(), this function can handle NULL argument(s). 122 | // A NULL C string is considered different to any non-NULL C string, 123 | // including the empty string. 124 | static bool CaseInsensitiveCStringEquals(const char* lhs, 125 | const char* rhs); 126 | 127 | // Compares two wide C strings, ignoring case. Returns true if and only if 128 | // they have the same content. 129 | // 130 | // Unlike wcscasecmp(), this function can handle NULL argument(s). 131 | // A NULL C string is considered different to any non-NULL wide C string, 132 | // including the empty string. 133 | // NB: The implementations on different platforms slightly differ. 134 | // On windows, this method uses _wcsicmp which compares according to LC_CTYPE 135 | // environment variable. On GNU platform this method uses wcscasecmp 136 | // which compares according to LC_CTYPE category of the current locale. 137 | // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the 138 | // current locale. 139 | static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, 140 | const wchar_t* rhs); 141 | 142 | // Returns true if and only if the given string ends with the given suffix, 143 | // ignoring case. Any string is considered to end with an empty suffix. 144 | static bool EndsWithCaseInsensitive( 145 | const std::string& str, const std::string& suffix); 146 | 147 | // Formats an int value as "%02d". 148 | static std::string FormatIntWidth2(int value); // "%02d" for width == 2 149 | 150 | // Formats an int value to given width with leading zeros. 151 | static std::string FormatIntWidthN(int value, int width); 152 | 153 | // Formats an int value as "%X". 154 | static std::string FormatHexInt(int value); 155 | 156 | // Formats an int value as "%X". 157 | static std::string FormatHexUInt32(uint32_t value); 158 | 159 | // Formats a byte as "%02X". 160 | static std::string FormatByte(unsigned char value); 161 | 162 | private: 163 | String(); // Not meant to be instantiated. 164 | }; // class String 165 | 166 | // Gets the content of the stringstream's buffer as an std::string. Each '\0' 167 | // character in the buffer is replaced with "\\0". 168 | GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); 169 | 170 | } // namespace internal 171 | } // namespace testing 172 | 173 | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 174 | -------------------------------------------------------------------------------- /test/include/gtest/internal/gtest-type-util.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Google Inc. 2 | // All Rights Reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Type utilities needed for implementing typed and type-parameterized 31 | // tests. 32 | 33 | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 34 | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 35 | 36 | #include "gtest/internal/gtest-port.h" 37 | 38 | // #ifdef __GNUC__ is too general here. It is possible to use gcc without using 39 | // libstdc++ (which is where cxxabi.h comes from). 40 | # if GTEST_HAS_CXXABI_H_ 41 | # include 42 | # elif defined(__HP_aCC) 43 | # include 44 | # endif // GTEST_HASH_CXXABI_H_ 45 | 46 | namespace testing { 47 | namespace internal { 48 | 49 | // Canonicalizes a given name with respect to the Standard C++ Library. 50 | // This handles removing the inline namespace within `std` that is 51 | // used by various standard libraries (e.g., `std::__1`). Names outside 52 | // of namespace std are returned unmodified. 53 | inline std::string CanonicalizeForStdLibVersioning(std::string s) { 54 | static const char prefix[] = "std::__"; 55 | if (s.compare(0, strlen(prefix), prefix) == 0) { 56 | std::string::size_type end = s.find("::", strlen(prefix)); 57 | if (end != s.npos) { 58 | // Erase everything between the initial `std` and the second `::`. 59 | s.erase(strlen("std"), end - strlen("std")); 60 | } 61 | } 62 | return s; 63 | } 64 | 65 | #if GTEST_HAS_RTTI 66 | // GetTypeName(const std::type_info&) returns a human-readable name of type T. 67 | inline std::string GetTypeName(const std::type_info& type) { 68 | const char* const name = type.name(); 69 | #if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) 70 | int status = 0; 71 | // gcc's implementation of typeid(T).name() mangles the type name, 72 | // so we have to demangle it. 73 | #if GTEST_HAS_CXXABI_H_ 74 | using abi::__cxa_demangle; 75 | #endif // GTEST_HAS_CXXABI_H_ 76 | char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status); 77 | const std::string name_str(status == 0 ? readable_name : name); 78 | free(readable_name); 79 | return CanonicalizeForStdLibVersioning(name_str); 80 | #else 81 | return name; 82 | #endif // GTEST_HAS_CXXABI_H_ || __HP_aCC 83 | } 84 | #endif // GTEST_HAS_RTTI 85 | 86 | // GetTypeName() returns a human-readable name of type T if and only if 87 | // RTTI is enabled, otherwise it returns a dummy type name. 88 | // NB: This function is also used in Google Mock, so don't move it inside of 89 | // the typed-test-only section below. 90 | template 91 | std::string GetTypeName() { 92 | #if GTEST_HAS_RTTI 93 | return GetTypeName(typeid(T)); 94 | #else 95 | return ""; 96 | #endif // GTEST_HAS_RTTI 97 | } 98 | 99 | // A unique type indicating an empty node 100 | struct None {}; 101 | 102 | # define GTEST_TEMPLATE_ template class 103 | 104 | // The template "selector" struct TemplateSel is used to 105 | // represent Tmpl, which must be a class template with one type 106 | // parameter, as a type. TemplateSel::Bind::type is defined 107 | // as the type Tmpl. This allows us to actually instantiate the 108 | // template "selected" by TemplateSel. 109 | // 110 | // This trick is necessary for simulating typedef for class templates, 111 | // which C++ doesn't support directly. 112 | template 113 | struct TemplateSel { 114 | template 115 | struct Bind { 116 | typedef Tmpl type; 117 | }; 118 | }; 119 | 120 | # define GTEST_BIND_(TmplSel, T) \ 121 | TmplSel::template Bind::type 122 | 123 | template 124 | struct Templates { 125 | using Head = TemplateSel; 126 | using Tail = Templates; 127 | }; 128 | 129 | template 130 | struct Templates { 131 | using Head = TemplateSel; 132 | using Tail = None; 133 | }; 134 | 135 | // Tuple-like type lists 136 | template 137 | struct Types { 138 | using Head = Head_; 139 | using Tail = Types; 140 | }; 141 | 142 | template 143 | struct Types { 144 | using Head = Head_; 145 | using Tail = None; 146 | }; 147 | 148 | // Helper metafunctions to tell apart a single type from types 149 | // generated by ::testing::Types 150 | template 151 | struct ProxyTypeList { 152 | using type = Types; 153 | }; 154 | 155 | template 156 | struct is_proxy_type_list : std::false_type {}; 157 | 158 | template 159 | struct is_proxy_type_list> : std::true_type {}; 160 | 161 | // Generator which conditionally creates type lists. 162 | // It recognizes if a requested type list should be created 163 | // and prevents creating a new type list nested within another one. 164 | template 165 | struct GenerateTypeList { 166 | private: 167 | using proxy = typename std::conditional::value, T, 168 | ProxyTypeList>::type; 169 | 170 | public: 171 | using type = typename proxy::type; 172 | }; 173 | 174 | } // namespace internal 175 | 176 | template 177 | using Types = internal::ProxyTypeList; 178 | 179 | } // namespace testing 180 | 181 | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 182 | -------------------------------------------------------------------------------- /test/include/test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "gtest/gtest.h" 3 | #include "zpp_bits.h" 4 | 5 | inline std::string encode_hex(auto && view) 6 | { 7 | auto to_hex = [](auto value) constexpr { 8 | if (value < 0xa) { 9 | return '0' + value; 10 | } else { 11 | return 'a' + (value - 0xa); 12 | } 13 | }; 14 | 15 | std::string hex(view.size() * 2, '\0'); 16 | for (auto i = 0; auto byte : view) { 17 | hex[i++] = to_hex((static_cast(byte) >> 4) & 0xf); 18 | hex[i++] = to_hex(static_cast(byte) & 0xf); 19 | } 20 | 21 | return hex; 22 | } 23 | -------------------------------------------------------------------------------- /test/src/gtest/src/gtest-filepath.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include "gtest/internal/gtest-filepath.h" 31 | 32 | #include 33 | #include "gtest/internal/gtest-port.h" 34 | #include "gtest/gtest-message.h" 35 | 36 | #if GTEST_OS_WINDOWS_MOBILE 37 | # include 38 | #elif GTEST_OS_WINDOWS 39 | # include 40 | # include 41 | #else 42 | # include 43 | # include // Some Linux distributions define PATH_MAX here. 44 | #endif // GTEST_OS_WINDOWS_MOBILE 45 | 46 | #include "gtest/internal/gtest-string.h" 47 | 48 | #if GTEST_OS_WINDOWS 49 | # define GTEST_PATH_MAX_ _MAX_PATH 50 | #elif defined(PATH_MAX) 51 | # define GTEST_PATH_MAX_ PATH_MAX 52 | #elif defined(_XOPEN_PATH_MAX) 53 | # define GTEST_PATH_MAX_ _XOPEN_PATH_MAX 54 | #else 55 | # define GTEST_PATH_MAX_ _POSIX_PATH_MAX 56 | #endif // GTEST_OS_WINDOWS 57 | 58 | namespace testing { 59 | namespace internal { 60 | 61 | #if GTEST_OS_WINDOWS 62 | // On Windows, '\\' is the standard path separator, but many tools and the 63 | // Windows API also accept '/' as an alternate path separator. Unless otherwise 64 | // noted, a file path can contain either kind of path separators, or a mixture 65 | // of them. 66 | const char kPathSeparator = '\\'; 67 | const char kAlternatePathSeparator = '/'; 68 | const char kAlternatePathSeparatorString[] = "/"; 69 | # if GTEST_OS_WINDOWS_MOBILE 70 | // Windows CE doesn't have a current directory. You should not use 71 | // the current directory in tests on Windows CE, but this at least 72 | // provides a reasonable fallback. 73 | const char kCurrentDirectoryString[] = "\\"; 74 | // Windows CE doesn't define INVALID_FILE_ATTRIBUTES 75 | const DWORD kInvalidFileAttributes = 0xffffffff; 76 | # else 77 | const char kCurrentDirectoryString[] = ".\\"; 78 | # endif // GTEST_OS_WINDOWS_MOBILE 79 | #else 80 | const char kPathSeparator = '/'; 81 | const char kCurrentDirectoryString[] = "./"; 82 | #endif // GTEST_OS_WINDOWS 83 | 84 | // Returns whether the given character is a valid path separator. 85 | static bool IsPathSeparator(char c) { 86 | #if GTEST_HAS_ALT_PATH_SEP_ 87 | return (c == kPathSeparator) || (c == kAlternatePathSeparator); 88 | #else 89 | return c == kPathSeparator; 90 | #endif 91 | } 92 | 93 | // Returns the current working directory, or "" if unsuccessful. 94 | FilePath FilePath::GetCurrentDir() { 95 | #if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ 96 | GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32 || \ 97 | GTEST_OS_XTENSA 98 | // These platforms do not have a current directory, so we just return 99 | // something reasonable. 100 | return FilePath(kCurrentDirectoryString); 101 | #elif GTEST_OS_WINDOWS 102 | char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; 103 | return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd); 104 | #else 105 | char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; 106 | char* result = getcwd(cwd, sizeof(cwd)); 107 | # if GTEST_OS_NACL 108 | // getcwd will likely fail in NaCl due to the sandbox, so return something 109 | // reasonable. The user may have provided a shim implementation for getcwd, 110 | // however, so fallback only when failure is detected. 111 | return FilePath(result == nullptr ? kCurrentDirectoryString : cwd); 112 | # endif // GTEST_OS_NACL 113 | return FilePath(result == nullptr ? "" : cwd); 114 | #endif // GTEST_OS_WINDOWS_MOBILE 115 | } 116 | 117 | // Returns a copy of the FilePath with the case-insensitive extension removed. 118 | // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns 119 | // FilePath("dir/file"). If a case-insensitive extension is not 120 | // found, returns a copy of the original FilePath. 121 | FilePath FilePath::RemoveExtension(const char* extension) const { 122 | const std::string dot_extension = std::string(".") + extension; 123 | if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { 124 | return FilePath(pathname_.substr( 125 | 0, pathname_.length() - dot_extension.length())); 126 | } 127 | return *this; 128 | } 129 | 130 | // Returns a pointer to the last occurrence of a valid path separator in 131 | // the FilePath. On Windows, for example, both '/' and '\' are valid path 132 | // separators. Returns NULL if no path separator was found. 133 | const char* FilePath::FindLastPathSeparator() const { 134 | const char* const last_sep = strrchr(c_str(), kPathSeparator); 135 | #if GTEST_HAS_ALT_PATH_SEP_ 136 | const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); 137 | // Comparing two pointers of which only one is NULL is undefined. 138 | if (last_alt_sep != nullptr && 139 | (last_sep == nullptr || last_alt_sep > last_sep)) { 140 | return last_alt_sep; 141 | } 142 | #endif 143 | return last_sep; 144 | } 145 | 146 | // Returns a copy of the FilePath with the directory part removed. 147 | // Example: FilePath("path/to/file").RemoveDirectoryName() returns 148 | // FilePath("file"). If there is no directory part ("just_a_file"), it returns 149 | // the FilePath unmodified. If there is no file part ("just_a_dir/") it 150 | // returns an empty FilePath (""). 151 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 152 | FilePath FilePath::RemoveDirectoryName() const { 153 | const char* const last_sep = FindLastPathSeparator(); 154 | return last_sep ? FilePath(last_sep + 1) : *this; 155 | } 156 | 157 | // RemoveFileName returns the directory path with the filename removed. 158 | // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". 159 | // If the FilePath is "a_file" or "/a_file", RemoveFileName returns 160 | // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does 161 | // not have a file, like "just/a/dir/", it returns the FilePath unmodified. 162 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 163 | FilePath FilePath::RemoveFileName() const { 164 | const char* const last_sep = FindLastPathSeparator(); 165 | std::string dir; 166 | if (last_sep) { 167 | dir = std::string(c_str(), static_cast(last_sep + 1 - c_str())); 168 | } else { 169 | dir = kCurrentDirectoryString; 170 | } 171 | return FilePath(dir); 172 | } 173 | 174 | // Helper functions for naming files in a directory for xml output. 175 | 176 | // Given directory = "dir", base_name = "test", number = 0, 177 | // extension = "xml", returns "dir/test.xml". If number is greater 178 | // than zero (e.g., 12), returns "dir/test_12.xml". 179 | // On Windows platform, uses \ as the separator rather than /. 180 | FilePath FilePath::MakeFileName(const FilePath& directory, 181 | const FilePath& base_name, 182 | int number, 183 | const char* extension) { 184 | std::string file; 185 | if (number == 0) { 186 | file = base_name.string() + "." + extension; 187 | } else { 188 | file = base_name.string() + "_" + StreamableToString(number) 189 | + "." + extension; 190 | } 191 | return ConcatPaths(directory, FilePath(file)); 192 | } 193 | 194 | // Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". 195 | // On Windows, uses \ as the separator rather than /. 196 | FilePath FilePath::ConcatPaths(const FilePath& directory, 197 | const FilePath& relative_path) { 198 | if (directory.IsEmpty()) 199 | return relative_path; 200 | const FilePath dir(directory.RemoveTrailingPathSeparator()); 201 | return FilePath(dir.string() + kPathSeparator + relative_path.string()); 202 | } 203 | 204 | // Returns true if pathname describes something findable in the file-system, 205 | // either a file, directory, or whatever. 206 | bool FilePath::FileOrDirectoryExists() const { 207 | #if GTEST_OS_WINDOWS_MOBILE 208 | LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); 209 | const DWORD attributes = GetFileAttributes(unicode); 210 | delete [] unicode; 211 | return attributes != kInvalidFileAttributes; 212 | #else 213 | posix::StatStruct file_stat{}; 214 | return posix::Stat(pathname_.c_str(), &file_stat) == 0; 215 | #endif // GTEST_OS_WINDOWS_MOBILE 216 | } 217 | 218 | // Returns true if pathname describes a directory in the file-system 219 | // that exists. 220 | bool FilePath::DirectoryExists() const { 221 | bool result = false; 222 | #if GTEST_OS_WINDOWS 223 | // Don't strip off trailing separator if path is a root directory on 224 | // Windows (like "C:\\"). 225 | const FilePath& path(IsRootDirectory() ? *this : 226 | RemoveTrailingPathSeparator()); 227 | #else 228 | const FilePath& path(*this); 229 | #endif 230 | 231 | #if GTEST_OS_WINDOWS_MOBILE 232 | LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); 233 | const DWORD attributes = GetFileAttributes(unicode); 234 | delete [] unicode; 235 | if ((attributes != kInvalidFileAttributes) && 236 | (attributes & FILE_ATTRIBUTE_DIRECTORY)) { 237 | result = true; 238 | } 239 | #else 240 | posix::StatStruct file_stat{}; 241 | result = posix::Stat(path.c_str(), &file_stat) == 0 && 242 | posix::IsDir(file_stat); 243 | #endif // GTEST_OS_WINDOWS_MOBILE 244 | 245 | return result; 246 | } 247 | 248 | // Returns true if pathname describes a root directory. (Windows has one 249 | // root directory per disk drive.) 250 | bool FilePath::IsRootDirectory() const { 251 | #if GTEST_OS_WINDOWS 252 | return pathname_.length() == 3 && IsAbsolutePath(); 253 | #else 254 | return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); 255 | #endif 256 | } 257 | 258 | // Returns true if pathname describes an absolute path. 259 | bool FilePath::IsAbsolutePath() const { 260 | const char* const name = pathname_.c_str(); 261 | #if GTEST_OS_WINDOWS 262 | return pathname_.length() >= 3 && 263 | ((name[0] >= 'a' && name[0] <= 'z') || 264 | (name[0] >= 'A' && name[0] <= 'Z')) && 265 | name[1] == ':' && 266 | IsPathSeparator(name[2]); 267 | #else 268 | return IsPathSeparator(name[0]); 269 | #endif 270 | } 271 | 272 | // Returns a pathname for a file that does not currently exist. The pathname 273 | // will be directory/base_name.extension or 274 | // directory/base_name_.extension if directory/base_name.extension 275 | // already exists. The number will be incremented until a pathname is found 276 | // that does not already exist. 277 | // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. 278 | // There could be a race condition if two or more processes are calling this 279 | // function at the same time -- they could both pick the same filename. 280 | FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, 281 | const FilePath& base_name, 282 | const char* extension) { 283 | FilePath full_pathname; 284 | int number = 0; 285 | do { 286 | full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); 287 | } while (full_pathname.FileOrDirectoryExists()); 288 | return full_pathname; 289 | } 290 | 291 | // Returns true if FilePath ends with a path separator, which indicates that 292 | // it is intended to represent a directory. Returns false otherwise. 293 | // This does NOT check that a directory (or file) actually exists. 294 | bool FilePath::IsDirectory() const { 295 | return !pathname_.empty() && 296 | IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); 297 | } 298 | 299 | // Create directories so that path exists. Returns true if successful or if 300 | // the directories already exist; returns false if unable to create directories 301 | // for any reason. 302 | bool FilePath::CreateDirectoriesRecursively() const { 303 | if (!this->IsDirectory()) { 304 | return false; 305 | } 306 | 307 | if (pathname_.length() == 0 || this->DirectoryExists()) { 308 | return true; 309 | } 310 | 311 | const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); 312 | return parent.CreateDirectoriesRecursively() && this->CreateFolder(); 313 | } 314 | 315 | // Create the directory so that path exists. Returns true if successful or 316 | // if the directory already exists; returns false if unable to create the 317 | // directory for any reason, including if the parent directory does not 318 | // exist. Not named "CreateDirectory" because that's a macro on Windows. 319 | bool FilePath::CreateFolder() const { 320 | #if GTEST_OS_WINDOWS_MOBILE 321 | FilePath removed_sep(this->RemoveTrailingPathSeparator()); 322 | LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); 323 | int result = CreateDirectory(unicode, nullptr) ? 0 : -1; 324 | delete [] unicode; 325 | #elif GTEST_OS_WINDOWS 326 | int result = _mkdir(pathname_.c_str()); 327 | #elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA 328 | // do nothing 329 | int result = 0; 330 | #else 331 | int result = mkdir(pathname_.c_str(), 0777); 332 | #endif // GTEST_OS_WINDOWS_MOBILE 333 | 334 | if (result == -1) { 335 | return this->DirectoryExists(); // An error is OK if the directory exists. 336 | } 337 | return true; // No error. 338 | } 339 | 340 | // If input name has a trailing separator character, remove it and return the 341 | // name, otherwise return the name string unmodified. 342 | // On Windows platform, uses \ as the separator, other platforms use /. 343 | FilePath FilePath::RemoveTrailingPathSeparator() const { 344 | return IsDirectory() 345 | ? FilePath(pathname_.substr(0, pathname_.length() - 1)) 346 | : *this; 347 | } 348 | 349 | // Removes any redundant separators that might be in the pathname. 350 | // For example, "bar///foo" becomes "bar/foo". Does not eliminate other 351 | // redundancies that might be in a pathname involving "." or "..". 352 | void FilePath::Normalize() { 353 | auto out = pathname_.begin(); 354 | 355 | for (const char character : pathname_) { 356 | if (!IsPathSeparator(character)) { 357 | *(out++) = character; 358 | } else if (out == pathname_.begin() || *std::prev(out) != kPathSeparator) { 359 | *(out++) = kPathSeparator; 360 | } else { 361 | continue; 362 | } 363 | } 364 | 365 | pathname_.erase(out, pathname_.end()); 366 | } 367 | 368 | } // namespace internal 369 | } // namespace testing 370 | -------------------------------------------------------------------------------- /test/src/gtest/src/gtest-matchers.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2007, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // The Google C++ Testing and Mocking Framework (Google Test) 31 | // 32 | // This file implements just enough of the matcher interface to allow 33 | // EXPECT_DEATH and friends to accept a matcher argument. 34 | 35 | #include "gtest/internal/gtest-internal.h" 36 | #include "gtest/internal/gtest-port.h" 37 | #include "gtest/gtest-matchers.h" 38 | 39 | #include 40 | 41 | namespace testing { 42 | 43 | // Constructs a matcher that matches a const std::string& whose value is 44 | // equal to s. 45 | Matcher::Matcher(const std::string& s) { *this = Eq(s); } 46 | 47 | // Constructs a matcher that matches a const std::string& whose value is 48 | // equal to s. 49 | Matcher::Matcher(const char* s) { 50 | *this = Eq(std::string(s)); 51 | } 52 | 53 | // Constructs a matcher that matches a std::string whose value is equal to 54 | // s. 55 | Matcher::Matcher(const std::string& s) { *this = Eq(s); } 56 | 57 | // Constructs a matcher that matches a std::string whose value is equal to 58 | // s. 59 | Matcher::Matcher(const char* s) { *this = Eq(std::string(s)); } 60 | 61 | #if GTEST_INTERNAL_HAS_STRING_VIEW 62 | // Constructs a matcher that matches a const StringView& whose value is 63 | // equal to s. 64 | Matcher::Matcher(const std::string& s) { 65 | *this = Eq(s); 66 | } 67 | 68 | // Constructs a matcher that matches a const StringView& whose value is 69 | // equal to s. 70 | Matcher::Matcher(const char* s) { 71 | *this = Eq(std::string(s)); 72 | } 73 | 74 | // Constructs a matcher that matches a const StringView& whose value is 75 | // equal to s. 76 | Matcher::Matcher(internal::StringView s) { 77 | *this = Eq(std::string(s)); 78 | } 79 | 80 | // Constructs a matcher that matches a StringView whose value is equal to 81 | // s. 82 | Matcher::Matcher(const std::string& s) { *this = Eq(s); } 83 | 84 | // Constructs a matcher that matches a StringView whose value is equal to 85 | // s. 86 | Matcher::Matcher(const char* s) { 87 | *this = Eq(std::string(s)); 88 | } 89 | 90 | // Constructs a matcher that matches a StringView whose value is equal to 91 | // s. 92 | Matcher::Matcher(internal::StringView s) { 93 | *this = Eq(std::string(s)); 94 | } 95 | #endif // GTEST_INTERNAL_HAS_STRING_VIEW 96 | 97 | } // namespace testing 98 | -------------------------------------------------------------------------------- /test/src/gtest/src/gtest-test-part.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // 31 | // The Google C++ Testing and Mocking Framework (Google Test) 32 | 33 | #include "gtest/gtest-test-part.h" 34 | 35 | #include "gtest/internal/gtest-port.h" 36 | #include "src/gtest-internal-inl.h" 37 | 38 | namespace testing { 39 | 40 | using internal::GetUnitTestImpl; 41 | 42 | // Gets the summary of the failure message by omitting the stack trace 43 | // in it. 44 | std::string TestPartResult::ExtractSummary(const char* message) { 45 | const char* const stack_trace = strstr(message, internal::kStackTraceMarker); 46 | return stack_trace == nullptr ? message : std::string(message, stack_trace); 47 | } 48 | 49 | // Prints a TestPartResult object. 50 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { 51 | return os << internal::FormatFileLocation(result.file_name(), 52 | result.line_number()) 53 | << " " 54 | << (result.type() == TestPartResult::kSuccess 55 | ? "Success" 56 | : result.type() == TestPartResult::kSkip 57 | ? "Skipped" 58 | : result.type() == TestPartResult::kFatalFailure 59 | ? "Fatal failure" 60 | : "Non-fatal failure") 61 | << ":\n" 62 | << result.message() << std::endl; 63 | } 64 | 65 | // Appends a TestPartResult to the array. 66 | void TestPartResultArray::Append(const TestPartResult& result) { 67 | array_.push_back(result); 68 | } 69 | 70 | // Returns the TestPartResult at the given index (0-based). 71 | const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { 72 | if (index < 0 || index >= size()) { 73 | printf("\nInvalid index (%d) into TestPartResultArray.\n", index); 74 | internal::posix::Abort(); 75 | } 76 | 77 | return array_[static_cast(index)]; 78 | } 79 | 80 | // Returns the number of TestPartResult objects in the array. 81 | int TestPartResultArray::size() const { 82 | return static_cast(array_.size()); 83 | } 84 | 85 | namespace internal { 86 | 87 | HasNewFatalFailureHelper::HasNewFatalFailureHelper() 88 | : has_new_fatal_failure_(false), 89 | original_reporter_(GetUnitTestImpl()-> 90 | GetTestPartResultReporterForCurrentThread()) { 91 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); 92 | } 93 | 94 | HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { 95 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( 96 | original_reporter_); 97 | } 98 | 99 | void HasNewFatalFailureHelper::ReportTestPartResult( 100 | const TestPartResult& result) { 101 | if (result.fatally_failed()) 102 | has_new_fatal_failure_ = true; 103 | original_reporter_->ReportTestPartResult(result); 104 | } 105 | 106 | } // namespace internal 107 | 108 | } // namespace testing 109 | -------------------------------------------------------------------------------- /test/src/gtest/src/gtest-typed-test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Google Inc. 2 | // All Rights Reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | #include "gtest/gtest-typed-test.h" 32 | 33 | #include "gtest/gtest.h" 34 | 35 | namespace testing { 36 | namespace internal { 37 | 38 | // Skips to the first non-space char in str. Returns an empty string if str 39 | // contains only whitespace characters. 40 | static const char* SkipSpaces(const char* str) { 41 | while (IsSpace(*str)) 42 | str++; 43 | return str; 44 | } 45 | 46 | static std::vector SplitIntoTestNames(const char* src) { 47 | std::vector name_vec; 48 | src = SkipSpaces(src); 49 | for (; src != nullptr; src = SkipComma(src)) { 50 | name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src))); 51 | } 52 | return name_vec; 53 | } 54 | 55 | // Verifies that registered_tests match the test names in 56 | // registered_tests_; returns registered_tests if successful, or 57 | // aborts the program otherwise. 58 | const char* TypedTestSuitePState::VerifyRegisteredTestNames( 59 | const char* test_suite_name, const char* file, int line, 60 | const char* registered_tests) { 61 | RegisterTypeParameterizedTestSuite(test_suite_name, CodeLocation(file, line)); 62 | 63 | typedef RegisteredTestsMap::const_iterator RegisteredTestIter; 64 | registered_ = true; 65 | 66 | std::vector name_vec = SplitIntoTestNames(registered_tests); 67 | 68 | Message errors; 69 | 70 | std::set tests; 71 | for (std::vector::const_iterator name_it = name_vec.begin(); 72 | name_it != name_vec.end(); ++name_it) { 73 | const std::string& name = *name_it; 74 | if (tests.count(name) != 0) { 75 | errors << "Test " << name << " is listed more than once.\n"; 76 | continue; 77 | } 78 | 79 | if (registered_tests_.count(name) != 0) { 80 | tests.insert(name); 81 | } else { 82 | errors << "No test named " << name 83 | << " can be found in this test suite.\n"; 84 | } 85 | } 86 | 87 | for (RegisteredTestIter it = registered_tests_.begin(); 88 | it != registered_tests_.end(); 89 | ++it) { 90 | if (tests.count(it->first) == 0) { 91 | errors << "You forgot to list test " << it->first << ".\n"; 92 | } 93 | } 94 | 95 | const std::string& errors_str = errors.GetString(); 96 | if (errors_str != "") { 97 | fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), 98 | errors_str.c_str()); 99 | fflush(stderr); 100 | posix::Abort(); 101 | } 102 | 103 | return registered_tests; 104 | } 105 | 106 | } // namespace internal 107 | } // namespace testing 108 | -------------------------------------------------------------------------------- /test/src/gtest/src/gtest_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include "gtest/gtest.h" 32 | 33 | #if GTEST_OS_ESP8266 || GTEST_OS_ESP32 34 | #if GTEST_OS_ESP8266 35 | extern "C" { 36 | #endif 37 | void setup() { 38 | testing::InitGoogleTest(); 39 | } 40 | 41 | void loop() { RUN_ALL_TESTS(); } 42 | 43 | #if GTEST_OS_ESP8266 44 | } 45 | #endif 46 | 47 | #else 48 | 49 | GTEST_API_ int main(int argc, char **argv) { 50 | printf("Running main() from %s\n", __FILE__); 51 | testing::InitGoogleTest(&argc, argv); 52 | return RUN_ALL_TESTS(); 53 | } 54 | #endif 55 | -------------------------------------------------------------------------------- /test/src/test_alloc_limit.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_alloc_limit 4 | { 5 | 6 | TEST(test_alloc_limit, output) 7 | { 8 | constexpr auto limit = 128; 9 | auto [data, out] = data_out(zpp::bits::alloc_limit()); 10 | static_assert(decltype(out)::allocation_limit == limit); 11 | 12 | out(1,2,3,4).or_throw(); 13 | EXPECT_EQ((out(std::array{})), std::errc::no_buffer_space); 14 | } 15 | 16 | TEST(test_alloc_limit, input) 17 | { 18 | constexpr auto limit = 128; 19 | auto [data, in] = data_in(zpp::bits::alloc_limit()); 20 | static_assert(decltype(in)::allocation_limit == limit); 21 | 22 | std::vector vi; 23 | std::vector vb; 24 | zpp::bits::out{data}(std::vector{1, 2, 3, 4}) 25 | .or_throw(); 26 | in(vi).or_throw(); 27 | in.reset(); 28 | 29 | zpp::bits::out{data}(std::vector(limit / sizeof(std::uint32_t))) 30 | .or_throw(); 31 | in(vi).or_throw(); 32 | in.reset(); 33 | 34 | zpp::bits::out{data}(std::vector(limit / sizeof(std::uint32_t) + 1)) 35 | .or_throw(); 36 | EXPECT_EQ((in(vi)), std::errc::message_size); 37 | in.reset(); 38 | 39 | zpp::bits::out{data}(std::vector(limit)).or_throw(); 40 | in(vb).or_throw(); 41 | in.reset(); 42 | 43 | zpp::bits::out{data}(std::vector(limit + 1)).or_throw(); 44 | EXPECT_EQ((in(vb)), std::errc::message_size); 45 | in.reset(); 46 | 47 | zpp::bits::out{data}(std::vector(limit / 4), 48 | std::vector(limit / 4), 49 | std::vector(limit / 4), 50 | std::vector(limit / 4)) 51 | .or_throw(); 52 | in(vb).or_throw(); 53 | in(vb).or_throw(); 54 | in(vb).or_throw(); 55 | in(vb).or_throw(); 56 | in.reset(); 57 | } 58 | 59 | } // namespace test_alloc_limit 60 | -------------------------------------------------------------------------------- /test/src/test_append.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_append 4 | { 5 | 6 | TEST(append, integer) 7 | { 8 | std::vector data = {std::byte{0xff}}; 9 | auto [in, out] = in_out(data, zpp::bits::append{}); 10 | out(std::vector{1,2,3,4}).or_throw(); 11 | 12 | EXPECT_EQ(encode_hex(data), 13 | "ff" 14 | "04000000" 15 | "01000000" 16 | "02000000" 17 | "03000000" 18 | "04000000"); 19 | 20 | std::vector v; 21 | in.position() += sizeof(std::byte{}); 22 | in(v).or_throw(); 23 | 24 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 25 | } 26 | 27 | } // namespace test_append 28 | -------------------------------------------------------------------------------- /test/src/test_array.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | TEST(array, integer) 4 | { 5 | auto [data, in, out] = zpp::bits::data_in_out(); 6 | int a1[] = {1,2,3,4}; 7 | out(a1).or_throw(); 8 | 9 | EXPECT_EQ(encode_hex(data), 10 | "01000000" 11 | "02000000" 12 | "03000000" 13 | "04000000"); 14 | 15 | int a2[4]{}; 16 | in(a2).or_throw(); 17 | 18 | for (std::size_t i = 0; i < std::extent_v; ++i) { 19 | EXPECT_EQ(a1[i], a2[i]); 20 | } 21 | } 22 | 23 | TEST(array, const_integer) 24 | { 25 | auto [data, in, out] = zpp::bits::data_in_out(); 26 | const int a1[] = {1,2,3,4}; 27 | out(a1).or_throw(); 28 | 29 | EXPECT_EQ(encode_hex(data), 30 | "01000000" 31 | "02000000" 32 | "03000000" 33 | "04000000"); 34 | 35 | int a2[4]{}; 36 | in(a2).or_throw(); 37 | 38 | for (std::size_t i = 0; i < std::extent_v; ++i) { 39 | EXPECT_EQ(a1[i], a2[i]); 40 | } 41 | } 42 | 43 | TEST(array, string) 44 | { 45 | using namespace std::string_literals; 46 | auto [data, in, out] = zpp::bits::data_in_out(); 47 | std::string a1[] = {"1"s,"2"s,"3"s,"4"s}; 48 | out(a1).or_throw(); 49 | 50 | EXPECT_EQ(encode_hex(data), 51 | "01000000" 52 | "31" 53 | "01000000" 54 | "32" 55 | "01000000" 56 | "33" 57 | "01000000" 58 | "34"); 59 | 60 | std::string a2[4]{}; 61 | in(a2).or_throw(); 62 | 63 | for (std::size_t i = 0; i < std::extent_v; ++i) { 64 | EXPECT_EQ(a1[i], a2[i]); 65 | } 66 | } 67 | 68 | TEST(array, const_string) 69 | { 70 | using namespace std::string_literals; 71 | auto [data, in, out] = zpp::bits::data_in_out(); 72 | const std::string a1[] = {"1"s,"2"s,"3"s,"4"s}; 73 | out(a1).or_throw(); 74 | 75 | EXPECT_EQ(encode_hex(data), 76 | "01000000" 77 | "31" 78 | "01000000" 79 | "32" 80 | "01000000" 81 | "33" 82 | "01000000" 83 | "34"); 84 | 85 | std::string a2[4]{}; 86 | in(a2).or_throw(); 87 | 88 | for (std::size_t i = 0; i < std::extent_v; ++i) { 89 | EXPECT_EQ(a1[i], a2[i]); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /test/src/test_bitset.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | namespace test_bitset 5 | { 6 | 7 | TEST(test_bitset, sanity) 8 | { 9 | auto [data, in, out] = zpp::bits::data_in_out(); 10 | constexpr std::bitset<8> o(0x7f); 11 | out(o).or_throw(); 12 | EXPECT_EQ(out.position(), 1u); 13 | 14 | std::bitset<8> i; 15 | in(i).or_throw(); 16 | 17 | EXPECT_EQ(in.position(), 1u); 18 | EXPECT_EQ(o, i); 19 | } 20 | 21 | } // namespace test_bitset 22 | -------------------------------------------------------------------------------- /test/src/test_byte_serializable.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | namespace test_byte_serializable 5 | { 6 | 7 | struct integers 8 | { 9 | int x; 10 | int y; 11 | }; 12 | 13 | struct members_integers 14 | { 15 | using serialize = zpp::bits::members<2>; 16 | int x; 17 | int y; 18 | }; 19 | 20 | struct members_integers_outside 21 | { 22 | int x; 23 | int y; 24 | }; 25 | 26 | auto serialize(const members_integers_outside &) -> zpp::bits::members<2>; 27 | 28 | struct members_integers_auto 29 | { 30 | using serialize = zpp::bits::members<>; 31 | int x; 32 | int y; 33 | }; 34 | 35 | struct members_integers_outside_auto 36 | { 37 | int x; 38 | int y; 39 | }; 40 | 41 | auto serialize(const members_integers_outside_auto &) 42 | -> zpp::bits::members<>; 43 | 44 | struct ref 45 | { 46 | int & x; 47 | int y; 48 | }; 49 | 50 | struct pointer 51 | { 52 | int * x; 53 | int y; 54 | }; 55 | 56 | struct array 57 | { 58 | int x[5]; 59 | int y; 60 | }; 61 | 62 | struct stdarray 63 | { 64 | std::array x; 65 | int y; 66 | }; 67 | 68 | struct stdarray_array 69 | { 70 | std::array x[5]; 71 | int y; 72 | }; 73 | 74 | struct vector 75 | { 76 | std::vector x; 77 | int y; 78 | }; 79 | 80 | struct stdarray_custom 81 | { 82 | constexpr static void serialize(auto & archive, auto & self); 83 | 84 | std::array x; 85 | int y; 86 | }; 87 | 88 | struct stdarray_custom_outside 89 | { 90 | std::array x; 91 | int y; 92 | }; 93 | constexpr void serialize(auto & archive, 94 | const stdarray_custom_outside & self); 95 | 96 | static_assert(zpp::bits::concepts::byte_serializable); 97 | static_assert(zpp::bits::concepts::byte_serializable); 98 | static_assert( 99 | zpp::bits::concepts::byte_serializable); 100 | static_assert(!zpp::bits::concepts::byte_serializable); 101 | static_assert(!zpp::bits::concepts::byte_serializable); 102 | static_assert(!zpp::bits::concepts::byte_serializable); 103 | static_assert(!zpp::bits::concepts::byte_serializable>); 104 | static_assert(!zpp::bits::concepts::byte_serializable); 105 | static_assert(!zpp::bits::concepts::byte_serializable); 106 | static_assert(!zpp::bits::concepts::byte_serializable>); 107 | static_assert(zpp::bits::concepts::byte_serializable>); 108 | 109 | static_assert(!zpp::bits::concepts::byte_serializable); 110 | static_assert(!zpp::bits::concepts::byte_serializable); 111 | static_assert(!zpp::bits::concepts::byte_serializable>); 112 | static_assert(!zpp::bits::concepts::byte_serializable>); 113 | 114 | #if !ZPP_BITS_AUTODETECT_MEMBERS_MODE 115 | auto serialize(const array &) -> zpp::bits::members<2>; 116 | auto serialize(const stdarray &) -> zpp::bits::members<2>; 117 | auto serialize(const stdarray_array &) -> zpp::bits::members<2>; 118 | auto serialize(const integers &) -> zpp::bits::members<2>; 119 | auto serialize(const integers &) -> zpp::bits::members<2>; 120 | #endif 121 | 122 | static_assert(zpp::bits::concepts::byte_serializable); 123 | static_assert(zpp::bits::concepts::byte_serializable>); 124 | 125 | static_assert(zpp::bits::concepts::byte_serializable); 126 | static_assert(zpp::bits::concepts::byte_serializable); 127 | static_assert(!zpp::bits::concepts::serialize_as_bytes, 128 | stdarray_custom>); 129 | static_assert(!zpp::bits::concepts::serialize_as_bytes, 130 | stdarray_custom>); 131 | static_assert( 132 | !zpp::bits::concepts::serialize_as_bytes, 133 | stdarray_custom_outside>); 134 | static_assert( 135 | !zpp::bits::concepts::serialize_as_bytes, 136 | stdarray_custom_outside>); 137 | static_assert(zpp::bits::concepts::byte_serializable); 138 | static_assert(zpp::bits::concepts::byte_serializable); 139 | 140 | #if ZPP_BITS_AUTODETECT_MEMBERS_MODE > 0 141 | static_assert( 142 | zpp::bits::concepts::byte_serializable); 143 | static_assert( 144 | zpp::bits::concepts::byte_serializable); 145 | #endif 146 | 147 | struct requires_padding 148 | { 149 | std::byte b{}; 150 | std::int32_t i32{}; 151 | }; 152 | 153 | TEST(byte_serializable, requires_padding) 154 | { 155 | auto [data, in, out] = zpp::bits::data_in_out(); 156 | 157 | static_assert( 158 | !zpp::bits::concepts::byte_serializable); 159 | static_assert(sizeof(requires_padding) > 5); 160 | 161 | #if ZPP_BITS_AUTODETECT_MEMBERS_MODE > 0 162 | out(requires_padding{std::byte{0x25}, 0x1337}).or_throw(); 163 | 164 | EXPECT_EQ(data.size(), std::size_t{5}); 165 | EXPECT_EQ(encode_hex(data), 166 | "25" 167 | "37130000"); 168 | 169 | requires_padding s; 170 | in(s).or_throw(); 171 | if constexpr (!ZPP_BITS_AUTODETECT_MEMBERS_MODE) { 172 | EXPECT_EQ(in.position(), sizeof(requires_padding)); 173 | } else { 174 | EXPECT_EQ(in.position(), std::size_t{5}); 175 | } 176 | EXPECT_EQ(s.b, std::byte{0x25}); 177 | EXPECT_EQ(s.i32, 0x1337); 178 | #endif 179 | } 180 | 181 | class inaccessible_requires_padding 182 | { 183 | public: 184 | inaccessible_requires_padding() = default; 185 | inaccessible_requires_padding(auto b, auto i32) : b(b), i32(i32) 186 | { 187 | } 188 | 189 | std::strong_ordering operator<=>( 190 | const inaccessible_requires_padding & other) const = default; 191 | 192 | void dummy() 193 | { 194 | (void)b; 195 | (void)i32; 196 | } 197 | 198 | private: 199 | using serialize = zpp::bits::members<2>; 200 | std::byte b{}; 201 | std::int32_t i32{}; 202 | }; 203 | 204 | #if __cpp_structured_bindings < 202411L // This check is no longer supported until C++26 reflections. 205 | static_assert(!zpp::bits::concepts::byte_serializable< 206 | inaccessible_requires_padding>); 207 | #endif 208 | 209 | class inaccessible_friend_requires_padding 210 | { 211 | public: 212 | inaccessible_friend_requires_padding() = default; 213 | inaccessible_friend_requires_padding(auto b, auto i32) : b(b), i32(i32) 214 | { 215 | } 216 | 217 | std::strong_ordering 218 | operator<=>(const inaccessible_friend_requires_padding & other) const = 219 | default; 220 | 221 | private: 222 | friend zpp::bits::access; 223 | using serialize = zpp::bits::members<2>; 224 | std::byte b{}; 225 | std::int32_t i32{}; 226 | }; 227 | 228 | TEST(byte_serializable, inaccessible_friend_requires_padding) 229 | { 230 | auto [data, in, out] = zpp::bits::data_in_out(); 231 | 232 | static_assert(sizeof(requires_padding) == 233 | sizeof(inaccessible_friend_requires_padding)); 234 | static_assert(sizeof(inaccessible_friend_requires_padding) > 5); 235 | static_assert(!zpp::bits::concepts::byte_serializable< 236 | inaccessible_friend_requires_padding>); 237 | 238 | out(inaccessible_friend_requires_padding{std::byte{0x25}, 0x1337}) 239 | .or_throw(); 240 | 241 | EXPECT_EQ(data.size(), std::size_t{5}); 242 | EXPECT_EQ(encode_hex(data), 243 | "25" 244 | "37130000"); 245 | 246 | inaccessible_friend_requires_padding s; 247 | in(s).or_throw(); 248 | EXPECT_EQ(in.position(), std::size_t{5}); 249 | EXPECT_EQ( 250 | s, 251 | (inaccessible_friend_requires_padding{std::byte{0x25}, 0x1337})); 252 | } 253 | 254 | class inaccessible_members_requires_padding 255 | { 256 | public: 257 | inaccessible_members_requires_padding() = default; 258 | inaccessible_members_requires_padding(auto b, auto i32) : 259 | b(b), i32(i32) 260 | { 261 | } 262 | 263 | std::strong_ordering operator<=>( 264 | const inaccessible_members_requires_padding & other) const = 265 | default; 266 | 267 | using serialize = zpp::bits::members<2>; 268 | 269 | private: 270 | friend zpp::bits::access; 271 | std::byte b{}; 272 | std::int32_t i32{}; 273 | }; 274 | 275 | TEST(byte_serializable, inaccessible_members_requires_padding) 276 | { 277 | static_assert(sizeof(requires_padding) == 278 | sizeof(inaccessible_members_requires_padding)); 279 | static_assert(sizeof(inaccessible_members_requires_padding) > 5); 280 | 281 | auto [data, in, out] = zpp::bits::data_in_out(); 282 | out(inaccessible_members_requires_padding{std::byte{0x25}, 0x1337}) 283 | .or_throw(); 284 | 285 | EXPECT_EQ(data.size(), std::size_t{5}); 286 | EXPECT_EQ(encode_hex(data), 287 | "25" 288 | "37130000"); 289 | 290 | inaccessible_members_requires_padding s; 291 | in(s).or_throw(); 292 | EXPECT_EQ(in.position(), std::size_t{5}); 293 | EXPECT_EQ( 294 | s, 295 | (inaccessible_members_requires_padding{std::byte{0x25}, 0x1337})); 296 | } 297 | 298 | struct members_requires_padding 299 | { 300 | using serialize = zpp::bits::members<2>; 301 | std::byte b{}; 302 | std::int32_t i32{}; 303 | }; 304 | 305 | TEST(byte_serializable, members_requires_padding) 306 | { 307 | static_assert( 308 | !zpp::bits::concepts::byte_serializable); 309 | static_assert(sizeof(requires_padding) == 310 | sizeof(members_requires_padding)); 311 | static_assert(sizeof(members_requires_padding) > 5); 312 | 313 | auto [data, in, out] = zpp::bits::data_in_out(); 314 | out(members_requires_padding{std::byte{0x25}, 0x1337}).or_throw(); 315 | 316 | EXPECT_EQ(data.size(), std::size_t{5}); 317 | EXPECT_EQ(encode_hex(data), 318 | "25" 319 | "37130000"); 320 | 321 | members_requires_padding s; 322 | in(s).or_throw(); 323 | EXPECT_EQ(in.position(), std::size_t{5}); 324 | EXPECT_EQ(s.b, std::byte{0x25}); 325 | EXPECT_EQ(s.i32, 0x1337); 326 | } 327 | 328 | struct members_requires_padding_outside 329 | { 330 | std::byte b{}; 331 | std::int32_t i32{}; 332 | }; 333 | 334 | auto serialize(const members_requires_padding_outside &) 335 | -> zpp::bits::members<2>; 336 | 337 | TEST(byte_serializable, members_requires_padding_outside) 338 | { 339 | static_assert(!zpp::bits::concepts::byte_serializable< 340 | members_requires_padding_outside>); 341 | static_assert(sizeof(requires_padding) == 342 | sizeof(members_requires_padding_outside)); 343 | static_assert(sizeof(members_requires_padding_outside) > 5); 344 | 345 | auto [data, in, out] = zpp::bits::data_in_out(); 346 | out(members_requires_padding_outside{std::byte{0x25}, 0x1337}) 347 | .or_throw(); 348 | 349 | EXPECT_EQ(data.size(), std::size_t{5}); 350 | EXPECT_EQ(encode_hex(data), 351 | "25" 352 | "37130000"); 353 | 354 | members_requires_padding_outside s; 355 | in(s).or_throw(); 356 | EXPECT_EQ(in.position(), std::size_t{5}); 357 | EXPECT_EQ(s.b, std::byte{0x25}); 358 | EXPECT_EQ(s.i32, 0x1337); 359 | } 360 | 361 | #if ZPP_BITS_AUTODETECT_MEMBERS_MODE > 0 362 | struct members_requires_padding_auto 363 | { 364 | using serialize = zpp::bits::members<>; 365 | std::byte b{}; 366 | std::int32_t i32{}; 367 | }; 368 | 369 | TEST(byte_serializable, members_requires_padding_auto) 370 | { 371 | static_assert(!zpp::bits::concepts::byte_serializable< 372 | members_requires_padding_auto>); 373 | static_assert(sizeof(requires_padding) == 374 | sizeof(members_requires_padding_auto)); 375 | static_assert(sizeof(members_requires_padding_auto) > 5); 376 | 377 | auto [data, in, out] = zpp::bits::data_in_out(); 378 | out(members_requires_padding_auto{std::byte{0x25}, 0x1337}).or_throw(); 379 | 380 | EXPECT_EQ(data.size(), std::size_t{5}); 381 | EXPECT_EQ(encode_hex(data), 382 | "25" 383 | "37130000"); 384 | 385 | members_requires_padding_auto s; 386 | in(s).or_throw(); 387 | EXPECT_EQ(in.position(), std::size_t{5}); 388 | EXPECT_EQ(s.b, std::byte{0x25}); 389 | EXPECT_EQ(s.i32, 0x1337); 390 | } 391 | 392 | struct members_requires_padding_outside_auto 393 | { 394 | std::byte b{}; 395 | std::int32_t i32{}; 396 | }; 397 | 398 | auto serialize(const members_requires_padding_outside_auto &) 399 | -> zpp::bits::members<>; 400 | 401 | TEST(byte_serializable, members_requires_padding_outside_auto) 402 | { 403 | static_assert(!zpp::bits::concepts::byte_serializable< 404 | members_requires_padding_outside_auto>); 405 | static_assert(sizeof(requires_padding) == 406 | sizeof(members_requires_padding_outside_auto)); 407 | static_assert(sizeof(members_requires_padding_outside_auto) > 5); 408 | 409 | auto [data, in, out] = zpp::bits::data_in_out(); 410 | out(members_requires_padding_outside_auto{std::byte{0x25}, 0x1337}) 411 | .or_throw(); 412 | 413 | EXPECT_EQ(data.size(), std::size_t{5}); 414 | EXPECT_EQ(encode_hex(data), 415 | "25" 416 | "37130000"); 417 | 418 | members_requires_padding_outside_auto s; 419 | in(s).or_throw(); 420 | EXPECT_EQ(in.position(), std::size_t{5}); 421 | EXPECT_EQ(s.b, std::byte{0x25}); 422 | EXPECT_EQ(s.i32, 0x1337); 423 | } 424 | 425 | #endif // ZPP_BITS_AUTODETECT_MEMBERS_MODE > 0 426 | 427 | } // namespace test_byte_serializable 428 | -------------------------------------------------------------------------------- /test/src/test_constexpr.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_constexpr 4 | { 5 | 6 | constexpr auto integers() 7 | { 8 | std::array data{}; 9 | auto [in, out] = zpp::bits::in_out(data); 10 | out(1,2,3,4,5).or_throw(); 11 | 12 | int _1 = 0; 13 | int _2 = 0; 14 | int _3 = 0; 15 | int _4 = 0; 16 | int _5 = 0; 17 | in(_1, _2, _3, _4, _5).or_throw(); 18 | return std::tuple{_1, _2, _3, _4, _5}; 19 | } 20 | 21 | TEST(test_constexpr, integers) 22 | { 23 | static_assert(integers() == std::tuple{1,2,3,4,5}); 24 | EXPECT_TRUE((integers() == std::tuple{1,2,3,4,5})); 25 | } 26 | 27 | constexpr auto tuple_integers() 28 | { 29 | std::array data{}; 30 | auto [in, out] = zpp::bits::in_out(data); 31 | out(std::tuple{1,2,3,4,5}).or_throw(); 32 | 33 | std::tuple t{0,0,0,0,0}; 34 | in(t).or_throw(); 35 | return t; 36 | } 37 | 38 | TEST(test_constexpr, tuple_integers) 39 | { 40 | static_assert(tuple_integers() == std::tuple{1,2,3,4,5}); 41 | EXPECT_TRUE((tuple_integers() == std::tuple{1,2,3,4,5})); 42 | } 43 | 44 | constexpr auto unsized_string_view() 45 | { 46 | std::array data{}; 47 | auto [in, out] = zpp::bits::in_out(data); 48 | out(zpp::bits::unsized(std::string_view{"Hello World"})).or_throw(); 49 | 50 | std::array storage{}; 51 | in(storage).or_throw(); 52 | return storage; 53 | } 54 | 55 | TEST(test_constexpr, unsized_string_view) 56 | { 57 | static_assert(0 == std::char_traits::compare( 58 | unsized_string_view().data(), 59 | std::string_view{"Hello World"}.data(), 60 | std::string_view{"Hello World"}.size())); 61 | 62 | EXPECT_TRUE((0 == std::char_traits::compare( 63 | unsized_string_view().data(), 64 | std::string_view{"Hello World"}.data(), 65 | std::string_view{"Hello World"}.size()))); 66 | } 67 | 68 | } // namespace test_constexpr 69 | -------------------------------------------------------------------------------- /test/src/test_data_sources.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | TEST(data_sources, vector_bytes) 4 | { 5 | std::vector data; 6 | auto [in, out] = zpp::bits::in_out(data); 7 | out(std::vector{1,2,3,4}).or_throw(); 8 | 9 | EXPECT_EQ(encode_hex(data), 10 | "04000000" 11 | "01000000" 12 | "02000000" 13 | "03000000" 14 | "04000000"); 15 | 16 | std::vector v; 17 | in(v).or_throw(); 18 | 19 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 20 | } 21 | 22 | TEST(data_sources, vector_unsigned_char) 23 | { 24 | std::vector data; 25 | auto [in, out] = zpp::bits::in_out(data); 26 | out(std::vector{1,2,3,4}).or_throw(); 27 | 28 | EXPECT_EQ(encode_hex(data), 29 | "04000000" 30 | "01000000" 31 | "02000000" 32 | "03000000" 33 | "04000000"); 34 | 35 | std::vector v; 36 | in(v).or_throw(); 37 | 38 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 39 | } 40 | 41 | TEST(data_sources, vector_char) 42 | { 43 | std::vector data; 44 | auto [in, out] = zpp::bits::in_out(data); 45 | out(std::vector{1,2,3,4}).or_throw(); 46 | 47 | EXPECT_EQ(encode_hex(data), 48 | "04000000" 49 | "01000000" 50 | "02000000" 51 | "03000000" 52 | "04000000"); 53 | 54 | std::vector v; 55 | in(v).or_throw(); 56 | 57 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 58 | } 59 | 60 | TEST(data_sources, string) 61 | { 62 | std::string data; 63 | auto [in, out] = zpp::bits::in_out(data); 64 | out(std::vector{1,2,3,4}).or_throw(); 65 | 66 | EXPECT_EQ(encode_hex(data), 67 | "04000000" 68 | "01000000" 69 | "02000000" 70 | "03000000" 71 | "04000000"); 72 | 73 | std::vector v; 74 | in(v).or_throw(); 75 | 76 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 77 | } 78 | 79 | TEST(data_sources, stdarray) 80 | { 81 | std::array data; 82 | auto [in, out] = zpp::bits::in_out(data); 83 | static_assert(decltype(in)::view_type::extent == data.size()); 84 | static_assert(decltype(out)::view_type::extent == data.size()); 85 | 86 | out(std::vector{1,2,3,4}).or_throw(); 87 | 88 | EXPECT_EQ(encode_hex(std::span{data.data(), out.position()}), 89 | "04000000" 90 | "01000000" 91 | "02000000" 92 | "03000000" 93 | "04000000"); 94 | 95 | std::vector v; 96 | in(v).or_throw(); 97 | 98 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 99 | } 100 | 101 | 102 | TEST(data_sources, array) 103 | { 104 | std::byte data[128]; 105 | auto [in, out] = zpp::bits::in_out(data); 106 | static_assert(decltype(in)::view_type::extent == std::size(data)); 107 | static_assert(decltype(out)::view_type::extent == std::size(data)); 108 | out(std::vector{1,2,3,4}).or_throw(); 109 | 110 | EXPECT_EQ(encode_hex(std::span{std::data(data), out.position()}), 111 | "04000000" 112 | "01000000" 113 | "02000000" 114 | "03000000" 115 | "04000000"); 116 | 117 | std::vector v; 118 | in(v).or_throw(); 119 | 120 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 121 | } 122 | 123 | TEST(data_sources, array_over_span) 124 | { 125 | std::byte data[128]; 126 | auto [in, out] = zpp::bits::in_out(std::span(data)); 127 | out(std::vector{1,2,3,4}).or_throw(); 128 | 129 | EXPECT_EQ(encode_hex(std::span{data, out.position()}), 130 | "04000000" 131 | "01000000" 132 | "02000000" 133 | "03000000" 134 | "04000000"); 135 | 136 | std::vector v; 137 | in(v).or_throw(); 138 | 139 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 140 | } 141 | 142 | TEST(data_sources, array_over_span_extent) 143 | { 144 | std::byte data[128]; 145 | auto [in, out] = zpp::bits::in_out(std::span(data)); 146 | static_assert(decltype(in)::view_type::extent == std::size(data)); 147 | static_assert(decltype(out)::view_type::extent == std::size(data)); 148 | out(std::vector{1,2,3,4}).or_throw(); 149 | 150 | EXPECT_EQ(encode_hex(std::span{data, out.position()}), 151 | "04000000" 152 | "01000000" 153 | "02000000" 154 | "03000000" 155 | "04000000"); 156 | 157 | std::vector v; 158 | in(v).or_throw(); 159 | 160 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 161 | } 162 | -------------------------------------------------------------------------------- /test/src/test_default_size_type.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_default_size_type 4 | { 5 | 6 | TEST(default_size_type, size1b) 7 | { 8 | auto [data, in, out] = zpp::bits::data_in_out(zpp::bits::size1b{}); 9 | out(std::vector{1,2,3,4}).or_throw(); 10 | 11 | EXPECT_EQ(encode_hex(data), 12 | "04" 13 | "01000000" 14 | "02000000" 15 | "03000000" 16 | "04000000"); 17 | 18 | std::vector v; 19 | in(v).or_throw(); 20 | 21 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 22 | } 23 | 24 | TEST(default_size_type, size2b) 25 | { 26 | auto [data, in, out] = zpp::bits::data_in_out(zpp::bits::size2b{}); 27 | out(std::vector{1,2,3,4}).or_throw(); 28 | 29 | EXPECT_EQ(encode_hex(data), 30 | "0400" 31 | "01000000" 32 | "02000000" 33 | "03000000" 34 | "04000000"); 35 | 36 | std::vector v; 37 | in(v).or_throw(); 38 | 39 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 40 | } 41 | 42 | TEST(default_size_type, size4b) 43 | { 44 | auto [data, in, out] = zpp::bits::data_in_out(zpp::bits::size4b{}); 45 | out(std::vector{1,2,3,4}).or_throw(); 46 | 47 | EXPECT_EQ(encode_hex(data), 48 | "04000000" 49 | "01000000" 50 | "02000000" 51 | "03000000" 52 | "04000000"); 53 | 54 | std::vector v; 55 | in(v).or_throw(); 56 | 57 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 58 | } 59 | 60 | TEST(default_size_type, size8b) 61 | { 62 | auto [data, in, out] = zpp::bits::data_in_out(zpp::bits::size8b{}); 63 | out(std::vector{1,2,3,4}).or_throw(); 64 | 65 | EXPECT_EQ(encode_hex(data), 66 | "0400000000000000" 67 | "01000000" 68 | "02000000" 69 | "03000000" 70 | "04000000"); 71 | 72 | std::vector v; 73 | in(v).or_throw(); 74 | 75 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 76 | } 77 | 78 | TEST(default_size_type, size_native) 79 | { 80 | auto [data, in, out] = zpp::bits::data_in_out(zpp::bits::size_native{}); 81 | out(std::vector{1,2,3,4}).or_throw(); 82 | 83 | if constexpr (sizeof(std::size_t) == 8) { 84 | EXPECT_EQ(encode_hex(data), 85 | "0400000000000000" 86 | "01000000" 87 | "02000000" 88 | "03000000" 89 | "04000000"); 90 | } else { 91 | EXPECT_EQ(encode_hex(data), 92 | "04000000" 93 | "01000000" 94 | "02000000" 95 | "03000000" 96 | "04000000"); 97 | } 98 | 99 | std::vector v; 100 | in(v).or_throw(); 101 | 102 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 103 | } 104 | 105 | } // namespace test_default_size_type 106 | -------------------------------------------------------------------------------- /test/src/test_detect_members_serialize.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_detect_members_serialize 4 | { 5 | using namespace std::literals; 6 | 7 | struct person 8 | { 9 | #if __cpp_structured_bindings >= 202411L 10 | person(auto &&...) 11 | { 12 | } 13 | person(std::string name, int age, auto && ...) : name(std::move(name)), age(age) 14 | { 15 | } 16 | #endif 17 | std::string name; 18 | int age{}; 19 | }; 20 | 21 | TEST(detect_members_serialize, sanity) 22 | { 23 | auto [data, in, out] = zpp::bits::data_in_out(); 24 | 25 | out(person{"Person1"s, 25}, person{"Person2"s, 35}).or_throw(); 26 | 27 | person p1, p2; 28 | 29 | in(p1, p2).or_throw(); 30 | 31 | EXPECT_EQ(p1.name, "Person1"s); 32 | EXPECT_EQ(p1.age, 25); 33 | 34 | EXPECT_EQ(p2.name, "Person2"s); 35 | EXPECT_EQ(p2.age, 35); 36 | } 37 | 38 | struct point 39 | { 40 | #if __cpp_structured_bindings >= 202411L 41 | point(auto &&...) 42 | { 43 | } 44 | point(int x, int y, auto && ...) : x(x), y(y) 45 | { 46 | } 47 | #endif 48 | 49 | int x{}; 50 | int y{}; 51 | }; 52 | 53 | TEST(detect_members_serialize, point) 54 | { 55 | auto [data, in, out] = zpp::bits::data_in_out(); 56 | 57 | out(point{1337, 1338}, point{1339, 1340}).or_throw(); 58 | 59 | point p1, p2; 60 | 61 | in(p1, p2).or_throw(); 62 | 63 | EXPECT_EQ(p1.x, 1337); 64 | EXPECT_EQ(p1.y, 1338); 65 | 66 | EXPECT_EQ(p2.x, 1339); 67 | EXPECT_EQ(p2.y, 1340); 68 | } 69 | 70 | struct number 71 | { 72 | #if __cpp_structured_bindings >= 202411L 73 | number(auto &&...) 74 | { 75 | } 76 | number(int x, auto && ...) : x(x) 77 | { 78 | } 79 | #endif 80 | 81 | int x{}; 82 | }; 83 | 84 | TEST(detect_members_serialize, number) 85 | { 86 | auto [data, in, out] = zpp::bits::data_in_out(); 87 | 88 | out(number{1337}, number{1338}).or_throw(); 89 | 90 | number n1, n2; 91 | 92 | in(n1, n2).or_throw(); 93 | 94 | EXPECT_EQ(n1.x, 1337); 95 | EXPECT_EQ(n2.x, 1338); 96 | } 97 | 98 | #if __cpp_structured_bindings >= 202411L 99 | class private_person 100 | { 101 | private_person(auto &&...) 102 | { 103 | } 104 | 105 | friend zpp::bits::access; 106 | 107 | std::string name; 108 | int age{}; 109 | 110 | friend void private_sanity_test(); 111 | }; 112 | 113 | void private_sanity_test() 114 | { 115 | auto [data, in, out] = zpp::bits::data_in_out(); 116 | private_person op1, op2; 117 | op1.name = "Person1"s; 118 | op1.age = 25; 119 | op2.name = "Person2"s; 120 | op2.age = 35; 121 | 122 | out(op1, op2).or_throw(); 123 | 124 | private_person p1, p2; 125 | 126 | in(p1, p2).or_throw(); 127 | 128 | EXPECT_EQ(p1.name, "Person1"s); 129 | EXPECT_EQ(p1.age, 25); 130 | 131 | EXPECT_EQ(p2.name, "Person2"s); 132 | EXPECT_EQ(p2.age, 35); 133 | } 134 | 135 | TEST(detect_members_serialize, private_sanity) 136 | { 137 | private_sanity_test(); 138 | } 139 | #endif 140 | 141 | } // namespace test_detect_members_serialize 142 | -------------------------------------------------------------------------------- /test/src/test_endian.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_endian 4 | { 5 | 6 | struct integers 7 | { 8 | std::uint8_t i8; 9 | std::uint16_t i16; 10 | std::uint32_t i32; 11 | std::uint64_t i64; 12 | }; 13 | 14 | TEST(test_endian, big) 15 | { 16 | auto [data, in, out] = 17 | data_in_out(zpp::bits::endian::big{}); 18 | 19 | out(0x13371337u, 20 | integers{0x12u, 0x1234u, 0x12345678u, 0x123456789abcdef0u}) 21 | .or_throw(); 22 | 23 | std::uint32_t i = {}; 24 | integers ints = {}; 25 | in(i, ints).or_throw(); 26 | 27 | EXPECT_EQ(i, 0x13371337u); 28 | EXPECT_EQ(ints.i8, 0x12u); 29 | EXPECT_EQ(ints.i16, 0x1234u); 30 | EXPECT_EQ(ints.i32, 0x12345678u); 31 | EXPECT_EQ(ints.i64, 0x123456789abcdef0u); 32 | } 33 | 34 | TEST(test_endian, big_out) 35 | { 36 | auto [data, out] = data_out(zpp::bits::endian::big{}); 37 | 38 | zpp::bits::in in{data}; 39 | 40 | out(0x13371337u, 41 | integers{0x12u, 0x1234u, 0x12345678u, 0x123456789abcdef0u}) 42 | .or_throw(); 43 | 44 | std::uint32_t i = {}; 45 | integers ints = {}; 46 | in(i, ints).or_throw(); 47 | 48 | EXPECT_EQ(i, 0x37133713u); 49 | EXPECT_EQ(ints.i8, 0x12u); 50 | EXPECT_EQ(ints.i16, 0x3412u); 51 | EXPECT_EQ(ints.i32, 0x78563412u); 52 | EXPECT_EQ(ints.i64, 0xf0debc9a78563412u); 53 | } 54 | 55 | TEST(test_endian, big_in) 56 | { 57 | auto [data, in] = data_in(zpp::bits::endian::big{}); 58 | 59 | zpp::bits::out out{data}; 60 | 61 | out(0x13371337u, 62 | integers{0x12u, 0x1234u, 0x12345678u, 0x123456789abcdef0u}) 63 | .or_throw(); 64 | 65 | std::uint32_t i = {}; 66 | integers ints = {}; 67 | in(i, ints).or_throw(); 68 | 69 | EXPECT_EQ(i, 0x37133713u); 70 | EXPECT_EQ(ints.i8, 0x12u); 71 | EXPECT_EQ(ints.i16, 0x3412u); 72 | EXPECT_EQ(ints.i32, 0x78563412u); 73 | EXPECT_EQ(ints.i64, 0xf0debc9a78563412u); 74 | } 75 | 76 | TEST(test_endian, little) 77 | { 78 | auto [data, in, out] = data_in_out(zpp::bits::endian::little{}); 79 | 80 | out(0x13371337u, 81 | integers{0x12u, 0x1234u, 0x12345678u, 0x123456789abcdef0u}) 82 | .or_throw(); 83 | 84 | std::uint32_t i = {}; 85 | integers ints = {}; 86 | in(i, ints).or_throw(); 87 | 88 | EXPECT_EQ(i, 0x13371337u); 89 | EXPECT_EQ(ints.i8, 0x12u); 90 | EXPECT_EQ(ints.i16, 0x1234u); 91 | EXPECT_EQ(ints.i32, 0x12345678u); 92 | EXPECT_EQ(ints.i64, 0x123456789abcdef0u); 93 | } 94 | 95 | TEST(test_endian, little_out) 96 | { 97 | auto [data, out] = data_out(zpp::bits::endian::little{}); 98 | 99 | zpp::bits::in in{data}; 100 | 101 | out(0x13371337u, 102 | integers{0x12u, 0x1234u, 0x12345678u, 0x123456789abcdef0u}) 103 | .or_throw(); 104 | 105 | std::uint32_t i = {}; 106 | integers ints = {}; 107 | in(i, ints).or_throw(); 108 | 109 | EXPECT_EQ(i, 0x13371337u); 110 | EXPECT_EQ(ints.i8, 0x12u); 111 | EXPECT_EQ(ints.i16, 0x1234u); 112 | EXPECT_EQ(ints.i32, 0x12345678u); 113 | EXPECT_EQ(ints.i64, 0x123456789abcdef0u); 114 | } 115 | 116 | TEST(test_endian, little_in) 117 | { 118 | auto [data, in] = data_in(zpp::bits::endian::little{}); 119 | 120 | zpp::bits::out out{data}; 121 | 122 | out(0x13371337u, 123 | integers{0x12u, 0x1234u, 0x12345678u, 0x123456789abcdef0u}) 124 | .or_throw(); 125 | 126 | std::uint32_t i = {}; 127 | integers ints = {}; 128 | in(i, ints).or_throw(); 129 | 130 | EXPECT_EQ(i, 0x13371337u); 131 | EXPECT_EQ(ints.i8, 0x12u); 132 | EXPECT_EQ(ints.i16, 0x1234u); 133 | EXPECT_EQ(ints.i32, 0x12345678u); 134 | EXPECT_EQ(ints.i64, 0x123456789abcdef0u); 135 | } 136 | 137 | } // namespace test_endian 138 | -------------------------------------------------------------------------------- /test/src/test_function.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_function 4 | { 5 | using namespace std::literals; 6 | 7 | int test_function_normal(std::string s, int i) 8 | { 9 | EXPECT_EQ(s, "hello"s); 10 | EXPECT_EQ(i, 1337); 11 | return 1338; 12 | } 13 | 14 | void test_function_void(std::string s, int i) 15 | { 16 | EXPECT_EQ(s, "hello"s); 17 | EXPECT_EQ(i, 1337); 18 | } 19 | 20 | int test_function_no_parameters() 21 | { 22 | return 1338; 23 | } 24 | 25 | void test_function_void_no_parameters() 26 | { 27 | } 28 | 29 | std::unique_ptr test_function_return_move(std::string s, int i) 30 | { 31 | EXPECT_EQ(s, "hello"s); 32 | EXPECT_EQ(i, 1337); 33 | return std::make_unique(1338); 34 | } 35 | 36 | int test_function_move_only(std::unique_ptr p) 37 | { 38 | EXPECT_EQ(*p, 1337); 39 | return 1338; 40 | } 41 | 42 | struct a 43 | { 44 | int test_member_function(std::string s, int i) 45 | { 46 | test_function_normal(std::move(s), i); 47 | return 1339; 48 | } 49 | 50 | void test_member_function_void(std::string s, int i) 51 | { 52 | return test_function_void(std::move(s), i); 53 | } 54 | 55 | int test_member_move_only(std::unique_ptr p) 56 | { 57 | test_function_move_only(std::move(p)); 58 | return 1339; 59 | } 60 | }; 61 | 62 | TEST(test_function, normal_function) 63 | { 64 | auto [data, in, out] = zpp::bits::data_in_out(); 65 | out("hello"s, 1337).or_throw(); 66 | 67 | EXPECT_EQ((zpp::bits::apply(test_function_normal, in).or_throw()), 68 | 1338); 69 | } 70 | 71 | TEST(test_function, normal_function_ret) 72 | { 73 | auto [data, in, out] = zpp::bits::data_in_out(); 74 | out("hello"s, 1337).or_throw(); 75 | 76 | if (auto result = zpp::bits::apply(test_function_normal, in); 77 | failure(result)) { 78 | FAIL(); 79 | } else { 80 | EXPECT_EQ(result.value(), 1338); 81 | } 82 | } 83 | 84 | TEST(test_function, function_return_move) 85 | { 86 | auto [data, in, out] = zpp::bits::data_in_out(); 87 | out("hello"s, 1337).or_throw(); 88 | 89 | EXPECT_EQ( 90 | *(zpp::bits::apply(test_function_return_move, in).or_throw()), 91 | 1338); 92 | } 93 | 94 | TEST(test_function, function_void) 95 | { 96 | auto [data, in, out] = zpp::bits::data_in_out(); 97 | out("hello"s, 1337).or_throw(); 98 | 99 | zpp::bits::apply(test_function_return_move, in).or_throw(); 100 | 101 | out("hello"s, 1337).or_throw(); 102 | int j = 0; 103 | zpp::bits::apply([&](std::string, int){ j = 1; }, in).or_throw(); 104 | EXPECT_EQ(j, 1); 105 | } 106 | 107 | TEST(test_function, function_no_parameters) 108 | { 109 | auto [data, in] = zpp::bits::data_in(); 110 | EXPECT_EQ(zpp::bits::apply(test_function_no_parameters, in), 1338); 111 | } 112 | 113 | TEST(test_function, function_void_no_parameters) 114 | { 115 | auto [data, in] = zpp::bits::data_in(); 116 | zpp::bits::apply(test_function_void_no_parameters, in); 117 | 118 | int i = 0; 119 | zpp::bits::apply([&] { i = 1; }, in); 120 | 121 | EXPECT_EQ(i, 1); 122 | } 123 | 124 | TEST(test_function, member_function) 125 | { 126 | auto [data, in, out] = zpp::bits::data_in_out(); 127 | out("hello"s, 1337).or_throw(); 128 | 129 | a a1; 130 | EXPECT_EQ( 131 | (zpp::bits::apply(a1, &a::test_member_function, in).or_throw()), 132 | 1339); 133 | } 134 | 135 | TEST(test_function, move_only) 136 | { 137 | auto [data, in, out] = zpp::bits::data_in_out(); 138 | out(1337).or_throw(); 139 | 140 | EXPECT_EQ( 141 | (zpp::bits::apply(test_function_move_only, in).or_throw()), 142 | 1338); 143 | } 144 | 145 | TEST(test_function, member_move_only) 146 | { 147 | auto [data, in, out] = zpp::bits::data_in_out(); 148 | out(1337).or_throw(); 149 | 150 | a a1; 151 | EXPECT_EQ( 152 | (zpp::bits::apply(a1, &a::test_member_move_only, in).or_throw()), 153 | 1339); 154 | } 155 | 156 | TEST(test_function, member_function_void) 157 | { 158 | auto [data, in, out] = zpp::bits::data_in_out(); 159 | out("hello"s, 1337).or_throw(); 160 | 161 | a a1; 162 | zpp::bits::apply(a1, &a::test_member_function_void, in).or_throw(); 163 | } 164 | 165 | TEST(test_function, lambda) 166 | { 167 | auto [data, in, out] = zpp::bits::data_in_out(); 168 | out("hello"s, 1337).or_throw(); 169 | 170 | EXPECT_EQ((zpp::bits::apply( 171 | [](std::string s, int i) { 172 | EXPECT_EQ(s, "hello"s); 173 | EXPECT_EQ(i, 1337); 174 | return 1338; 175 | }, 176 | in) 177 | .or_throw()), 178 | 1338); 179 | } 180 | 181 | TEST(test_function, lambda_with_capture) 182 | { 183 | auto [data, in, out] = zpp::bits::data_in_out(); 184 | out("hello"s, 1337).or_throw(); 185 | 186 | int n = 1; 187 | EXPECT_EQ((zpp::bits::apply( 188 | [&](std::string s, int i) { 189 | EXPECT_EQ(s, "hello"s); 190 | EXPECT_EQ(i, (1336 + n)); 191 | return 1338; 192 | }, 193 | in) 194 | .or_throw()), 195 | 1338); 196 | } 197 | 198 | #if __has_include("zpp_throwing.h") 199 | TEST(test_function, throwing_normal_function) 200 | { 201 | zpp::try_catch([]() -> zpp::throwing { 202 | auto [data, in, out] = zpp::bits::data_in_out(); 203 | co_await out("hello"s, 1337); 204 | 205 | EXPECT_EQ( 206 | (co_await zpp::bits::apply(test_function_normal, in)), 207 | 1338); 208 | }, 209 | []() { 210 | FAIL(); 211 | }); 212 | } 213 | 214 | TEST(test_function, throwing_function_return_move) 215 | { 216 | zpp::try_catch([]() -> zpp::throwing { 217 | auto [data, in, out] = zpp::bits::data_in_out(); 218 | co_await out("hello"s, 1337); 219 | 220 | EXPECT_EQ( 221 | *(co_await zpp::bits::apply(test_function_return_move, in)), 222 | 1338); 223 | }, []() { 224 | FAIL(); 225 | }); 226 | } 227 | #endif 228 | 229 | } // namespace test_function 230 | -------------------------------------------------------------------------------- /test/src/test_graph.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_graph 4 | { 5 | 6 | struct node 7 | { 8 | int value; 9 | std::vector nodes; 10 | }; 11 | 12 | struct person 13 | { 14 | std::string name; 15 | int age; 16 | }; 17 | 18 | static_assert(zpp::bits::concepts::self_referencing); 19 | static_assert(!zpp::bits::concepts::self_referencing); 20 | 21 | TEST(test_graph, tree) 22 | { 23 | auto [data, in, out] = zpp::bits::data_in_out(); 24 | node o = 25 | {1, 26 | std::vector { 27 | node { 28 | 2, 29 | std::vector { 30 | node { 31 | 3, 32 | std::vector { 33 | node{4, {}} 34 | } 35 | } 36 | } 37 | }, 38 | node {5, {}} 39 | } 40 | }; 41 | out(o).or_throw(); 42 | 43 | node i; 44 | in(i).or_throw(); 45 | 46 | EXPECT_EQ(o.value, i.value); 47 | EXPECT_EQ(o.nodes.size(), i.nodes.size()); 48 | 49 | EXPECT_EQ(i.value, 1); 50 | ASSERT_EQ(i.nodes.size(), 2u); 51 | EXPECT_EQ(i.nodes[0].value, 2); 52 | ASSERT_EQ(i.nodes[0].nodes.size(), 1u); 53 | EXPECT_EQ(i.nodes[0].nodes[0].value, 3); 54 | ASSERT_EQ(i.nodes[0].nodes[0].nodes.size(), 1u); 55 | EXPECT_EQ(i.nodes[0].nodes[0].nodes[0].value, 4); 56 | EXPECT_EQ(i.nodes[0].nodes[0].nodes[0].nodes.size(), 0u); 57 | EXPECT_EQ(i.nodes[1].value, 5); 58 | ASSERT_EQ(i.nodes[1].nodes.size(), 0u); 59 | } 60 | 61 | } // namespace test_graph 62 | -------------------------------------------------------------------------------- /test/src/test_hash.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_hash 4 | { 5 | using namespace zpp::bits::literals; 6 | using namespace std::literals; 7 | 8 | static_assert(""_sha1 == 9 | "da39a3ee5e6b4b0d3255bfef95601890afd80709"_decode_hex); 10 | static_assert( 11 | ""_sha256 == 12 | "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"_decode_hex); 13 | 14 | static_assert("The quick brown fox jumps over the lazy dog"_sha1 == 15 | "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"_decode_hex); 16 | 17 | static_assert( 18 | "The quick brown fox jumps over the lazy dog"_sha256 == 19 | "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"_decode_hex); 20 | } // namespace test_hash 21 | -------------------------------------------------------------------------------- /test/src/test_list.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | #include 4 | 5 | namespace test_list 6 | { 7 | 8 | TEST(list, integer) 9 | { 10 | auto [data, in, out] = zpp::bits::data_in_out(); 11 | out(std::list{1,2,3,4}).or_throw(); 12 | 13 | EXPECT_EQ(encode_hex(data), 14 | "04000000" 15 | "01000000" 16 | "02000000" 17 | "03000000" 18 | "04000000"); 19 | 20 | std::list v; 21 | in(v).or_throw(); 22 | 23 | EXPECT_EQ(v, (std::list{1,2,3,4})); 24 | } 25 | 26 | TEST(list, const_integer) 27 | { 28 | auto [data, in, out] = zpp::bits::data_in_out(); 29 | const std::list o{1,2,3,4}; 30 | out(o).or_throw(); 31 | 32 | EXPECT_EQ(encode_hex(data), 33 | "04000000" 34 | "01000000" 35 | "02000000" 36 | "03000000" 37 | "04000000"); 38 | 39 | std::list v; 40 | in(v).or_throw(); 41 | 42 | EXPECT_EQ(v, (std::list{1,2,3,4})); 43 | } 44 | 45 | TEST(list, string) 46 | { 47 | using namespace std::string_literals; 48 | auto [data, in, out] = zpp::bits::data_in_out(); 49 | out(std::list{"1"s,"2"s,"3"s,"4"s}).or_throw(); 50 | 51 | EXPECT_EQ(encode_hex(data), 52 | "04000000" 53 | "01000000" 54 | "31" 55 | "01000000" 56 | "32" 57 | "01000000" 58 | "33" 59 | "01000000" 60 | "34"); 61 | 62 | std::list v; 63 | in(v).or_throw(); 64 | 65 | EXPECT_EQ(v, (std::list{"1"s,"2"s,"3"s,"4"s})); 66 | } 67 | 68 | TEST(list, const_string) 69 | { 70 | using namespace std::string_literals; 71 | auto [data, in, out] = zpp::bits::data_in_out(); 72 | const std::list o{"1"s, "2"s, "3"s, "4"s}; 73 | out(o).or_throw(); 74 | 75 | EXPECT_EQ(encode_hex(data), 76 | "04000000" 77 | "01000000" 78 | "31" 79 | "01000000" 80 | "32" 81 | "01000000" 82 | "33" 83 | "01000000" 84 | "34"); 85 | 86 | std::list v; 87 | in(v).or_throw(); 88 | 89 | EXPECT_EQ(v, (std::list{"1"s,"2"s,"3"s,"4"s})); 90 | } 91 | 92 | TEST(list, sized_1b_integer) 93 | { 94 | auto [data, in, out] = zpp::bits::data_in_out(); 95 | out(zpp::bits::sized(std::list{1,2,3,4})).or_throw(); 96 | 97 | EXPECT_EQ(encode_hex(data), 98 | "04" 99 | "01000000" 100 | "02000000" 101 | "03000000" 102 | "04000000"); 103 | 104 | std::list v; 105 | in(zpp::bits::sized(v)).or_throw(); 106 | 107 | EXPECT_EQ(v, (std::list{1,2,3,4})); 108 | } 109 | 110 | TEST(list, unsized_integer) 111 | { 112 | auto [data, in, out] = zpp::bits::data_in_out(); 113 | out(zpp::bits::unsized(std::list{1,2,3,4})).or_throw(); 114 | 115 | EXPECT_EQ(encode_hex(data), 116 | "01000000" 117 | "02000000" 118 | "03000000" 119 | "04000000"); 120 | 121 | std::list v(4); 122 | in(zpp::bits::unsized(v)).or_throw(); 123 | 124 | EXPECT_EQ(v, (std::list{1,2,3,4})); 125 | } 126 | 127 | TEST(list, sized_t_1b_integer) 128 | { 129 | auto [data, in, out] = zpp::bits::data_in_out(); 130 | out(zpp::bits::sized_t, std::uint8_t>{1,2,3,4}).or_throw(); 131 | 132 | EXPECT_EQ(encode_hex(data), 133 | "04" 134 | "01000000" 135 | "02000000" 136 | "03000000" 137 | "04000000"); 138 | 139 | zpp::bits::sized_t, std::uint8_t> v; 140 | in(v).or_throw(); 141 | 142 | EXPECT_EQ(v, (std::list{1,2,3,4})); 143 | } 144 | 145 | TEST(list, unsized_t_integer) 146 | { 147 | auto [data, in, out] = zpp::bits::data_in_out(); 148 | out(zpp::bits::unsized_t>{1,2,3,4}).or_throw(); 149 | 150 | EXPECT_EQ(encode_hex(data), 151 | "01000000" 152 | "02000000" 153 | "03000000" 154 | "04000000"); 155 | 156 | zpp::bits::unsized_t> v(4); 157 | in(v).or_throw(); 158 | 159 | EXPECT_EQ(v, (std::list{1,2,3,4})); 160 | } 161 | 162 | } // namespace test_list 163 | -------------------------------------------------------------------------------- /test/src/test_map.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | TEST(map, integer) 5 | { 6 | auto [data, in, out] = zpp::bits::data_in_out(); 7 | out(std::map{{1, 1}, {2, 2}, {3, 3}, {4, 4}}).or_throw(); 8 | 9 | auto count_bytes = encode_hex(data); 10 | count_bytes.resize(8); 11 | EXPECT_EQ(count_bytes, "04000000"); 12 | 13 | std::map s; 14 | in(s).or_throw(); 15 | 16 | EXPECT_EQ(s, (std::map{{1, 1}, {2, 2}, {3, 3}, {4, 4}})); 17 | } 18 | 19 | TEST(map, const_integer) 20 | { 21 | auto [data, in, out] = zpp::bits::data_in_out(); 22 | const std::map m{{1, 1}, {2, 2}, {3, 3}, {4, 4}}; 23 | out(m).or_throw(); 24 | 25 | auto count_bytes = encode_hex(data); 26 | count_bytes.resize(8); 27 | EXPECT_EQ(count_bytes, "04000000"); 28 | 29 | std::map s; 30 | in(s).or_throw(); 31 | 32 | EXPECT_EQ(s, (std::map{{1, 1}, {2, 2}, {3, 3}, {4, 4}})); 33 | } 34 | 35 | TEST(map, string) 36 | { 37 | using namespace std::string_literals; 38 | auto [data, in, out] = zpp::bits::data_in_out(); 39 | out(std::map{ 40 | {"1"s, "1"s}, {"2"s, "2"s}, {"3"s, "3"s}, {"4"s, "4"s}}) 41 | .or_throw(); 42 | 43 | auto count_bytes = encode_hex(data); 44 | count_bytes.resize(8); 45 | EXPECT_EQ(count_bytes, "04000000"); 46 | 47 | std::map s; 48 | in(s).or_throw(); 49 | 50 | EXPECT_EQ( 51 | s, 52 | (std::map{ 53 | {"1"s, "1"s}, {"2"s, "2"s}, {"3"s, "3"s}, {"4"s, "4"s}})); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /test/src/test_members_serialize.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_members_serialize 4 | { 5 | struct person 6 | { 7 | using serialize = zpp::bits::members<2>; 8 | std::string name; 9 | int age{}; 10 | }; 11 | 12 | TEST(members_serialize, sanity) 13 | { 14 | auto [data, in, out] = zpp::bits::data_in_out(); 15 | 16 | out(person{"Person1", 25}, person{"Person2", 35}).or_throw(); 17 | 18 | person p1, p2; 19 | 20 | in(p1, p2).or_throw(); 21 | 22 | EXPECT_EQ(p1.name, "Person1"); 23 | EXPECT_EQ(p1.age, 25); 24 | 25 | EXPECT_EQ(p2.name, "Person2"); 26 | EXPECT_EQ(p2.age, 35); 27 | } 28 | 29 | class private_person 30 | { 31 | friend zpp::bits::access; 32 | using serialize = zpp::bits::members<2>; 33 | std::string name; 34 | int age{}; 35 | 36 | friend void private_sanity_test(); 37 | }; 38 | 39 | void private_sanity_test() 40 | { 41 | auto [data, in, out] = zpp::bits::data_in_out(); 42 | private_person op1, op2; 43 | op1.name = "Person1"; 44 | op1.age = 25; 45 | op2.name = "Person2"; 46 | op2.age = 35; 47 | 48 | out(op1, op2).or_throw(); 49 | 50 | private_person p1, p2; 51 | 52 | in(p1, p2).or_throw(); 53 | 54 | EXPECT_EQ(p1.name, "Person1"); 55 | EXPECT_EQ(p1.age, 25); 56 | 57 | EXPECT_EQ(p2.name, "Person2"); 58 | EXPECT_EQ(p2.age, 35); 59 | } 60 | 61 | TEST(members_serialize, private_sanity) 62 | { 63 | private_sanity_test(); 64 | } 65 | 66 | struct outside_person 67 | { 68 | std::string name; 69 | int age{}; 70 | }; 71 | 72 | auto serialize(const outside_person &) -> zpp::bits::members<2>; 73 | 74 | TEST(members_serialize, outside) 75 | { 76 | auto [data, in, out] = zpp::bits::data_in_out(); 77 | 78 | out(outside_person{"Person1", 25}, outside_person{"Person2", 35}) 79 | .or_throw(); 80 | 81 | outside_person p1, p2; 82 | 83 | in(p1, p2).or_throw(); 84 | 85 | EXPECT_EQ(p1.name, "Person1"); 86 | EXPECT_EQ(p1.age, 25); 87 | 88 | EXPECT_EQ(p2.name, "Person2"); 89 | EXPECT_EQ(p2.age, 35); 90 | } 91 | 92 | struct point 93 | { 94 | using serialize = zpp::bits::members<2>; 95 | 96 | int x{}; 97 | int y{}; 98 | }; 99 | 100 | TEST(members_serialize, point) 101 | { 102 | auto [data, in, out] = zpp::bits::data_in_out(); 103 | 104 | out(point{1337, 1338}, point{1339, 1340}).or_throw(); 105 | 106 | point p1, p2; 107 | 108 | in(p1, p2).or_throw(); 109 | 110 | EXPECT_EQ(p1.x, 1337); 111 | EXPECT_EQ(p1.y, 1338); 112 | 113 | EXPECT_EQ(p2.x, 1339); 114 | EXPECT_EQ(p2.y, 1340); 115 | } 116 | 117 | struct number 118 | { 119 | using serialize = zpp::bits::members<1>; 120 | 121 | int x{}; 122 | }; 123 | 124 | TEST(members_serialize, number) 125 | { 126 | auto [data, in, out] = zpp::bits::data_in_out(); 127 | 128 | out(number{1337}, number{1338}).or_throw(); 129 | 130 | number n1, n2; 131 | 132 | in(n1, n2).or_throw(); 133 | 134 | EXPECT_EQ(n1.x, 1337); 135 | EXPECT_EQ(n2.x, 1338); 136 | } 137 | 138 | } // namespace test_members_serialize 139 | -------------------------------------------------------------------------------- /test/src/test_optional.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_optional 4 | { 5 | 6 | TEST(optional, valid) 7 | { 8 | auto [data, in, out] = zpp::bits::data_in_out(); 9 | out(std::optional{std::vector{1,2,3,4}}).or_throw(); 10 | 11 | EXPECT_EQ(encode_hex(data), 12 | "01" 13 | "04000000" 14 | "01000000" 15 | "02000000" 16 | "03000000" 17 | "04000000"); 18 | 19 | std::optional> o; 20 | in(o).or_throw(); 21 | 22 | EXPECT_EQ(*o, (std::vector{1,2,3,4})); 23 | } 24 | 25 | TEST(optional, const_valid) 26 | { 27 | auto [data, in, out] = zpp::bits::data_in_out(); 28 | const std::optional o{std::vector{1,2,3,4}}; 29 | out(o).or_throw(); 30 | 31 | EXPECT_EQ(encode_hex(data), 32 | "01" 33 | "04000000" 34 | "01000000" 35 | "02000000" 36 | "03000000" 37 | "04000000"); 38 | 39 | std::optional> opt; 40 | in(opt).or_throw(); 41 | 42 | EXPECT_EQ(*opt, (std::vector{1,2,3,4})); 43 | } 44 | 45 | TEST(optional, nullopt) 46 | { 47 | auto [data, in, out] = zpp::bits::data_in_out(); 48 | out(std::optional>{}).or_throw(); 49 | 50 | EXPECT_EQ(encode_hex(data), 51 | "00"); 52 | 53 | std::optional> o = std::vector{1, 2, 3}; 54 | in(o).or_throw(); 55 | 56 | EXPECT_FALSE(o.has_value()); 57 | } 58 | 59 | } // namespace test_optional 60 | -------------------------------------------------------------------------------- /test/src/test_optional_ptr.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_implicit_optional 4 | { 5 | 6 | TEST(optional_ptr, ptr_valid) 7 | { 8 | auto [data, in, out] = zpp::bits::data_in_out(); 9 | out(zpp::bits::optional_ptr{std::make_unique(0x1337)}).or_throw(); 10 | 11 | EXPECT_EQ(encode_hex(data), 12 | "01" 13 | "37130000"); 14 | 15 | zpp::bits::optional_ptr o; 16 | in(o).or_throw(); 17 | 18 | EXPECT_TRUE(o != nullptr); 19 | EXPECT_EQ(*o, 0x1337); 20 | } 21 | 22 | TEST(optional_ptr, ptr_invalid) 23 | { 24 | auto [data, in, out] = zpp::bits::data_in_out(); 25 | out(zpp::bits::optional_ptr{}).or_throw(); 26 | 27 | EXPECT_EQ(encode_hex(data), 28 | "00"); 29 | 30 | zpp::bits::optional_ptr o = std::make_unique(1337); 31 | in(o).or_throw(); 32 | 33 | EXPECT_TRUE(o == nullptr); 34 | } 35 | 36 | } // namespace test_implicit_optional 37 | -------------------------------------------------------------------------------- /test/src/test_reflect.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_reflect 4 | { 5 | 6 | struct point 7 | { 8 | int x; 9 | int y; 10 | }; 11 | 12 | #if !ZPP_BITS_AUTODETECT_MEMBERS_MODE 13 | auto serialize(point) -> zpp::bits::members<2>; 14 | #endif 15 | 16 | static_assert(zpp::bits::number_of_members() == 2); 17 | 18 | TEST(test_reflect, sanity) 19 | { 20 | constexpr auto sum = zpp::bits::visit_members( 21 | point{1, 2}, [](auto x, auto y) { return x + y; }); 22 | 23 | static_assert(sum == 3); 24 | 25 | constexpr auto generic_sum = zpp::bits::visit_members( 26 | point{1, 2}, [](auto... members) { return (0 + ... + members); }); 27 | 28 | static_assert(generic_sum == 3); 29 | 30 | #if !(defined __clang__ && __clang_major__ < 13) 31 | constexpr auto is_two_integers = 32 | zpp::bits::visit_members_types([]() { 33 | if constexpr (std::same_as, 34 | std::tuple>) { 35 | return std::true_type{}; 36 | } else { 37 | return std::false_type{}; 38 | } 39 | })(); 40 | 41 | static_assert(is_two_integers); 42 | #endif 43 | } 44 | 45 | TEST(test_reflect, visit_point) 46 | { 47 | auto result = zpp::bits::visit_members(point{1337, 1338}, [](auto x, auto y) { 48 | EXPECT_EQ(x, 1337); 49 | EXPECT_EQ(y, 1338); 50 | return 1339; 51 | }); 52 | 53 | EXPECT_EQ(result, 1339); 54 | 55 | result = zpp::bits::visit_members(point{1337, 1338}, [](auto... members){ 56 | return (0 + ... + members); 57 | }); 58 | 59 | EXPECT_EQ(result, (1337 + 1338)); 60 | } 61 | 62 | #if !(defined __clang__ && __clang_major__ < 13) 63 | TEST(test_reflect, visit_point_types) 64 | { 65 | auto result = zpp::bits::visit_members_types([]() { 66 | EXPECT_EQ(sizeof...(Types), std::size_t{2}); 67 | EXPECT_TRUE((std::same_as, std::tuple>)); 68 | return std::integral_constant{}; 69 | })(); 70 | 71 | EXPECT_EQ(result, 1337); 72 | } 73 | #endif 74 | 75 | } // namespace test_reflect 76 | -------------------------------------------------------------------------------- /test/src/test_rpc_opaque.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_rpc_opaque 4 | { 5 | 6 | using namespace std::literals; 7 | using namespace zpp::bits::literals; 8 | 9 | int foo(std::span input) 10 | { 11 | int i = 0; 12 | std::string s; 13 | zpp::bits::in{input}(i, s).or_throw(); 14 | 15 | EXPECT_EQ(i, 1337); 16 | EXPECT_EQ(s, "hello"); 17 | return 1338; 18 | } 19 | 20 | int foo_partial(std::span & input) 21 | { 22 | int i = 0; 23 | zpp::bits::in in{input}; 24 | in(i).or_throw(); 25 | 26 | EXPECT_EQ(i, 1337); 27 | 28 | input = in.processed_data(); 29 | return 1338; 30 | } 31 | 32 | int bar(int i, std::string s) 33 | { 34 | EXPECT_EQ(i, 1337); 35 | EXPECT_EQ(s, "hello"); 36 | return 1339; 37 | } 38 | 39 | struct a 40 | { 41 | int foo(std::span input) 42 | { 43 | int i = 0; 44 | std::string s; 45 | zpp::bits::in{input}(i, s).or_throw(); 46 | 47 | EXPECT_EQ(i, 1337); 48 | EXPECT_EQ(s, "hello"); 49 | EXPECT_EQ(i2, 1339); 50 | return 1340; 51 | } 52 | 53 | #if __has_include("zpp_throwing.h") 54 | zpp::throwing foo_throwing(std::span input) 55 | { 56 | int i = 0; 57 | std::string s; 58 | zpp::bits::in{input}(i, s).or_throw(); 59 | 60 | EXPECT_EQ(i, 1337); 61 | EXPECT_EQ(s, "hello"); 62 | EXPECT_EQ(i2, 1339); 63 | return 1340; 64 | } 65 | #endif 66 | 67 | int i2 = 1339; 68 | }; 69 | 70 | TEST(test_rpc_opaque, opaque_function) 71 | { 72 | auto [data, in, out] = zpp::bits::data_in_out(); 73 | 74 | using rpc = zpp::bits::rpc< 75 | zpp::bits::bind_opaque, 76 | zpp::bits::bind 77 | >; 78 | 79 | auto [client, server] = rpc::client_server(in, out); 80 | client.request<"foo"_sha256_int>(1337, "hello"s).or_throw(); 81 | server.serve().or_throw(); 82 | 83 | EXPECT_EQ((client.response<"foo"_sha256_int>().or_throw()), 1338); 84 | } 85 | 86 | TEST(test_rpc, opaque_member_function) 87 | { 88 | auto [data, in, out] = zpp::bits::data_in_out(); 89 | 90 | using rpc = zpp::bits::rpc< 91 | zpp::bits::bind_opaque<&a::foo, "foo"_sha256_int>, 92 | zpp::bits::bind 93 | >; 94 | 95 | a a1; 96 | auto [client, server] = rpc::client_server(in, out, a1); 97 | client.request<"foo"_sha256_int>(1337, "hello"s).or_throw(); 98 | server.serve().or_throw(); 99 | 100 | EXPECT_EQ((client.response<"foo"_sha256_int>().or_throw()), 1340); 101 | } 102 | 103 | TEST(test_rpc_opaque, opaque_function_partial) 104 | { 105 | auto [data, in, out] = zpp::bits::data_in_out(); 106 | 107 | using rpc = zpp::bits::rpc< 108 | zpp::bits::bind_opaque, 109 | zpp::bits::bind 110 | >; 111 | 112 | auto [client, server] = rpc::client_server(in, out); 113 | client.request<"foo_partial"_sha256_int>(1337, "hello"s).or_throw(); 114 | server.serve().or_throw(); 115 | 116 | EXPECT_EQ(in.position(), (2 * sizeof(int))); 117 | 118 | std::string s; 119 | in(s).or_throw(); 120 | EXPECT_EQ(s, "hello"s); 121 | 122 | EXPECT_EQ((client.response<"foo_partial"_sha256_int>().or_throw()), 1338); 123 | } 124 | 125 | #if __has_include("zpp_throwing.h") 126 | TEST(test_rpc, opaque_member_function_throwing) 127 | { 128 | zpp::try_catch([]() -> zpp::throwing { 129 | auto [data, in, out] = zpp::bits::data_in_out(); 130 | 131 | using rpc = zpp::bits::rpc< 132 | zpp::bits::bind_opaque<&a::foo_throwing, 133 | "a::foo_throwing"_sha256_int>, 134 | zpp::bits::bind>; 135 | 136 | a a1; 137 | auto [client, server] = rpc::client_server(in, out, a1); 138 | co_await client.request<"a::foo_throwing"_sha256_int>(1337, 139 | "hello"s); 140 | co_await server.serve(); 141 | 142 | EXPECT_EQ( 143 | (co_await client.response<"a::foo_throwing"_sha256_int>()), 144 | 1340); 145 | }, []() { 146 | FAIL(); 147 | }); 148 | } 149 | #endif 150 | 151 | } // namespace test_rpc_opaque 152 | -------------------------------------------------------------------------------- /test/src/test_sanity.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_sanity 4 | { 5 | struct person 6 | { 7 | constexpr static auto serialize(auto & archive, auto & self) 8 | { 9 | return archive(self.name, self.age); 10 | } 11 | 12 | std::string name; 13 | int age{}; 14 | }; 15 | 16 | TEST(sanity, exception) 17 | { 18 | auto [data, in, out] = zpp::bits::data_in_out(); 19 | 20 | out(person{"Person1", 25}, person{"Person2", 35}).or_throw(); 21 | 22 | person p1, p2; 23 | 24 | in(p1, p2).or_throw(); 25 | 26 | EXPECT_EQ(p1.name, "Person1"); 27 | EXPECT_EQ(p1.age, 25); 28 | 29 | EXPECT_EQ(p2.name, "Person2"); 30 | EXPECT_EQ(p2.age, 35); 31 | } 32 | 33 | TEST(sanity, return_value) 34 | { 35 | auto [data, in, out] = zpp::bits::data_in_out(); 36 | 37 | auto result = out(person{"Person1", 25}, person{"Person2", 35}); 38 | if (failure(result)) { 39 | FAIL(); 40 | } 41 | 42 | person p1, p2; 43 | 44 | result = in(p1, p2); 45 | if (failure(result)) { 46 | FAIL(); 47 | } 48 | 49 | EXPECT_EQ(p1.name, "Person1"); 50 | EXPECT_EQ(p1.age, 25); 51 | 52 | EXPECT_EQ(p2.name, "Person2"); 53 | EXPECT_EQ(p2.age, 35); 54 | } 55 | 56 | #if __has_include("zpp_throwing.h") 57 | TEST(sanity, zpp_throwing) 58 | { 59 | return zpp::try_catch([&]() -> zpp::throwing { 60 | auto [data, in, out] = zpp::bits::data_in_out(); 61 | 62 | co_await out(person{"Person1", 25}, person{"Person2", 35}); 63 | 64 | person p1, p2; 65 | 66 | co_await in(p1, p2); 67 | 68 | EXPECT_EQ(p1.name, "Person1"); 69 | EXPECT_EQ(p1.age, 25); 70 | 71 | EXPECT_EQ(p2.name, "Person2"); 72 | EXPECT_EQ(p2.age, 35); 73 | }, [&]() { 74 | FAIL(); 75 | }); 76 | } 77 | #endif 78 | 79 | struct outside_person 80 | { 81 | std::string name; 82 | int age{}; 83 | }; 84 | 85 | constexpr static auto serialize(auto & archive, const outside_person & self) 86 | { 87 | return archive(self.name, self.age); 88 | } 89 | 90 | constexpr static auto serialize(auto & archive, outside_person & self) 91 | { 92 | return archive(self.name, self.age); 93 | } 94 | 95 | TEST(sanity, outside) 96 | { 97 | auto [data, in, out] = zpp::bits::data_in_out(); 98 | 99 | out(person{"Person1", 25}, person{"Person2", 35}).or_throw(); 100 | 101 | person p1, p2; 102 | 103 | in(p1, p2).or_throw(); 104 | 105 | EXPECT_EQ(p1.name, "Person1"); 106 | EXPECT_EQ(p1.age, 25); 107 | 108 | EXPECT_EQ(p2.name, "Person2"); 109 | EXPECT_EQ(p2.age, 35); 110 | } 111 | 112 | } // namespace test_sanity 113 | -------------------------------------------------------------------------------- /test/src/test_set.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | TEST(set, integer) 5 | { 6 | auto [data, in, out] = zpp::bits::data_in_out(); 7 | out(std::set{1,2,3,4}).or_throw(); 8 | 9 | auto count_bytes = encode_hex(data); 10 | count_bytes.resize(8); 11 | EXPECT_EQ(count_bytes, "04000000"); 12 | 13 | std::set s; 14 | in(s).or_throw(); 15 | 16 | EXPECT_EQ(s, (std::set{1,2,3,4})); 17 | } 18 | 19 | TEST(set, const_integer) 20 | { 21 | auto [data, in, out] = zpp::bits::data_in_out(); 22 | const std::set o{1,2,3,4}; 23 | out(o).or_throw(); 24 | 25 | auto count_bytes = encode_hex(data); 26 | count_bytes.resize(8); 27 | EXPECT_EQ(count_bytes, "04000000"); 28 | 29 | std::set s; 30 | in(s).or_throw(); 31 | 32 | EXPECT_EQ(s, (std::set{1,2,3,4})); 33 | } 34 | 35 | TEST(set, string) 36 | { 37 | using namespace std::string_literals; 38 | auto [data, in, out] = zpp::bits::data_in_out(); 39 | out(std::set{"1"s,"2"s,"3"s,"4"s}).or_throw(); 40 | 41 | auto count_bytes = encode_hex(data); 42 | count_bytes.resize(8); 43 | EXPECT_EQ(count_bytes, "04000000"); 44 | 45 | std::set s; 46 | in(s).or_throw(); 47 | 48 | EXPECT_EQ(s, (std::set{"1"s,"2"s,"3"s,"4"s})); 49 | } 50 | 51 | TEST(set, const_string) 52 | { 53 | using namespace std::string_literals; 54 | auto [data, in, out] = zpp::bits::data_in_out(); 55 | const std::set o{"1"s,"2"s,"3"s,"4"s}; 56 | out(o).or_throw(); 57 | 58 | auto count_bytes = encode_hex(data); 59 | count_bytes.resize(8); 60 | EXPECT_EQ(count_bytes, "04000000"); 61 | 62 | std::set s; 63 | in(s).or_throw(); 64 | 65 | EXPECT_EQ(s, (std::set{"1"s,"2"s,"3"s,"4"s})); 66 | } 67 | -------------------------------------------------------------------------------- /test/src/test_shared_ptr.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | TEST(shared_ptr, regular) 4 | { 5 | auto [data, in, out] = zpp::bits::data_in_out(); 6 | out(std::make_shared>(std::vector{1, 2, 3, 4})) 7 | .or_throw(); 8 | 9 | EXPECT_EQ(encode_hex(data), 10 | "04000000" 11 | "01000000" 12 | "02000000" 13 | "03000000" 14 | "04000000"); 15 | 16 | std::shared_ptr> p; 17 | in(p).or_throw(); 18 | 19 | EXPECT_EQ(*p, (std::vector{1,2,3,4})); 20 | } 21 | -------------------------------------------------------------------------------- /test/src/test_span.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_span 4 | { 5 | 6 | TEST(span, integer) 7 | { 8 | auto [data, in, out] = zpp::bits::data_in_out(); 9 | std::vector o{1,2,3,4}; 10 | out(std::span{o}).or_throw(); 11 | 12 | EXPECT_EQ(encode_hex(data), 13 | "04000000" 14 | "01000000" 15 | "02000000" 16 | "03000000" 17 | "04000000"); 18 | 19 | std::vector v(4); 20 | std::span s(v); 21 | in(s).or_throw(); 22 | 23 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 24 | } 25 | 26 | TEST(span, const_integer) 27 | { 28 | auto [data, in, out] = zpp::bits::data_in_out(); 29 | const std::vector v{1,2,3,4}; 30 | const std::span o{v}; 31 | out(o).or_throw(); 32 | 33 | EXPECT_EQ(encode_hex(data), 34 | "04000000" 35 | "01000000" 36 | "02000000" 37 | "03000000" 38 | "04000000"); 39 | 40 | std::vector v1(4); 41 | in(std::span{v1}).or_throw(); 42 | 43 | EXPECT_EQ(v1, (std::vector{1,2,3,4})); 44 | } 45 | 46 | TEST(span, string) 47 | { 48 | using namespace std::string_literals; 49 | auto [data, in, out] = zpp::bits::data_in_out(); 50 | std::vector o{"1"s,"2"s,"3"s,"4"s}; 51 | out(std::span{o}).or_throw(); 52 | 53 | EXPECT_EQ(encode_hex(data), 54 | "04000000" 55 | "01000000" 56 | "31" 57 | "01000000" 58 | "32" 59 | "01000000" 60 | "33" 61 | "01000000" 62 | "34"); 63 | 64 | std::vector v(4); 65 | in(std::span(v)).or_throw(); 66 | 67 | EXPECT_EQ(v, (std::vector{"1"s,"2"s,"3"s,"4"s})); 68 | } 69 | 70 | TEST(span, string_input_out_of_range) 71 | { 72 | using namespace std::string_literals; 73 | auto [data, in, out] = zpp::bits::data_in_out(); 74 | std::vector o{"1"s,"2"s,"3"s,"4"s}; 75 | out(std::span{o}).or_throw(); 76 | 77 | EXPECT_EQ(encode_hex(data), 78 | "04000000" 79 | "01000000" 80 | "31" 81 | "01000000" 82 | "32" 83 | "01000000" 84 | "33" 85 | "01000000" 86 | "34"); 87 | 88 | std::vector v; 89 | #ifdef __cpp_exceptions 90 | EXPECT_THROW(in(std::span(v)).or_throw(), std::system_error); 91 | #else 92 | EXPECT_EQ(in(std::span(v)), std::errc::value_too_large); 93 | #endif 94 | 95 | v.resize(3); 96 | in.reset(); 97 | #ifdef __cpp_exceptions 98 | EXPECT_THROW(in(std::span(v)).or_throw(), std::system_error); 99 | #else 100 | EXPECT_EQ(in(std::span(v)), std::errc::value_too_large); 101 | #endif 102 | 103 | v.resize(4); 104 | in.reset(); 105 | in(std::span(v)).or_throw(); 106 | 107 | EXPECT_EQ(v, (std::vector{"1"s,"2"s,"3"s,"4"s})); 108 | } 109 | 110 | TEST(span, const_string) 111 | { 112 | using namespace std::string_literals; 113 | auto [data, in, out] = zpp::bits::data_in_out(); 114 | const std::vector o{"1"s, "2"s, "3"s, "4"s}; 115 | out(std::span{o}).or_throw(); 116 | 117 | EXPECT_EQ(encode_hex(data), 118 | "04000000" 119 | "01000000" 120 | "31" 121 | "01000000" 122 | "32" 123 | "01000000" 124 | "33" 125 | "01000000" 126 | "34"); 127 | 128 | std::vector v(4); 129 | in(std::span(v)).or_throw(); 130 | 131 | EXPECT_EQ(v, (std::vector{"1"s,"2"s,"3"s,"4"s})); 132 | } 133 | 134 | } // namespace test_span 135 | -------------------------------------------------------------------------------- /test/src/test_span_extent.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_span_extent 4 | { 5 | 6 | TEST(span_extent, integer) 7 | { 8 | auto [data, in, out] = zpp::bits::data_in_out(); 9 | std::vector o{1,2,3,4}; 10 | out(std::span{o}).or_throw(); 11 | 12 | EXPECT_EQ(encode_hex(data), 13 | "01000000" 14 | "02000000" 15 | "03000000" 16 | "04000000"); 17 | 18 | std::vector v(4); 19 | std::span s(v); 20 | in(s).or_throw(); 21 | 22 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 23 | } 24 | 25 | TEST(span_extent, const_integer) 26 | { 27 | auto [data, in, out] = zpp::bits::data_in_out(); 28 | const std::vector v{1,2,3,4}; 29 | const std::span o{v}; 30 | out(o).or_throw(); 31 | 32 | EXPECT_EQ(encode_hex(data), 33 | "01000000" 34 | "02000000" 35 | "03000000" 36 | "04000000"); 37 | 38 | std::vector v1(4); 39 | in(std::span{v1}).or_throw(); 40 | 41 | EXPECT_EQ(v1, (std::vector{1,2,3,4})); 42 | } 43 | 44 | TEST(span_extent, string) 45 | { 46 | using namespace std::string_literals; 47 | auto [data, in, out] = zpp::bits::data_in_out(); 48 | std::vector o{"1"s,"2"s,"3"s,"4"s}; 49 | out(std::span{o}).or_throw(); 50 | 51 | EXPECT_EQ(encode_hex(data), 52 | "01000000" 53 | "31" 54 | "01000000" 55 | "32" 56 | "01000000" 57 | "33" 58 | "01000000" 59 | "34"); 60 | 61 | std::vector v(4); 62 | in(std::span(v)).or_throw(); 63 | 64 | EXPECT_EQ(v, (std::vector{"1"s,"2"s,"3"s,"4"s})); 65 | } 66 | 67 | TEST(span_extent, const_string) 68 | { 69 | using namespace std::string_literals; 70 | auto [data, in, out] = zpp::bits::data_in_out(); 71 | const std::vector o{"1"s, "2"s, "3"s, "4"s}; 72 | out(std::span{o}).or_throw(); 73 | 74 | EXPECT_EQ(encode_hex(data), 75 | "01000000" 76 | "31" 77 | "01000000" 78 | "32" 79 | "01000000" 80 | "33" 81 | "01000000" 82 | "34"); 83 | 84 | std::vector v(4); 85 | in(std::span(v)).or_throw(); 86 | 87 | EXPECT_EQ(v, (std::vector{"1"s,"2"s,"3"s,"4"s})); 88 | } 89 | 90 | } // namespace test_span_extent 91 | -------------------------------------------------------------------------------- /test/src/test_stdarray.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | TEST(stdarray, integer) 4 | { 5 | auto [data, in, out] = zpp::bits::data_in_out(); 6 | std::array a1 = {1,2,3,4}; 7 | out(a1).or_throw(); 8 | 9 | EXPECT_EQ(encode_hex(data), 10 | "01000000" 11 | "02000000" 12 | "03000000" 13 | "04000000"); 14 | 15 | std::array a2{}; 16 | in(a2).or_throw(); 17 | 18 | for (std::size_t i = 0; i < std::extent_v; ++i) { 19 | EXPECT_EQ(a1[i], a2[i]); 20 | } 21 | } 22 | 23 | TEST(stdarray, const_integer) 24 | { 25 | auto [data, in, out] = zpp::bits::data_in_out(); 26 | const std::array a1 = {1,2,3,4}; 27 | out(a1).or_throw(); 28 | 29 | EXPECT_EQ(encode_hex(data), 30 | "01000000" 31 | "02000000" 32 | "03000000" 33 | "04000000"); 34 | 35 | std::array a2{}; 36 | in(a2).or_throw(); 37 | 38 | for (std::size_t i = 0; i < std::extent_v; ++i) { 39 | EXPECT_EQ(a1[i], a2[i]); 40 | } 41 | } 42 | 43 | TEST(stdarray, string) 44 | { 45 | using namespace std::string_literals; 46 | auto [data, in, out] = zpp::bits::data_in_out(); 47 | std::array a1 = {"1"s,"2"s,"3"s,"4"s}; 48 | out(a1).or_throw(); 49 | 50 | EXPECT_EQ(encode_hex(data), 51 | "01000000" 52 | "31" 53 | "01000000" 54 | "32" 55 | "01000000" 56 | "33" 57 | "01000000" 58 | "34"); 59 | 60 | std::array a2{}; 61 | in(a2).or_throw(); 62 | 63 | for (std::size_t i = 0; i < std::extent_v; ++i) { 64 | EXPECT_EQ(a1[i], a2[i]); 65 | } 66 | } 67 | 68 | TEST(stdarray, large_array) 69 | { 70 | auto [data, in, out] = zpp::bits::data_in_out(); 71 | std::array a1 = {1,2,3,4}; 72 | out(a1).or_throw(); 73 | 74 | std::array a2{}; 75 | in(a2).or_throw(); 76 | 77 | for (std::size_t i = 0; i < std::extent_v; ++i) { 78 | EXPECT_EQ(a1[i], a2[i]); 79 | } 80 | } 81 | 82 | TEST(stdarray, large_array_in_struct) 83 | { 84 | auto [data, in, out] = zpp::bits::data_in_out(); 85 | struct a 86 | { 87 | std::array a1 = {1,2,3,4}; 88 | }; 89 | 90 | a a1 = {1,2,3,4}; 91 | out(a1).or_throw(); 92 | 93 | a a2; 94 | in(a2).or_throw(); 95 | 96 | for (std::size_t i = 0; i < std::extent_v; ++i) { 97 | EXPECT_EQ(a1.a1[i], a2.a1[i]); 98 | } 99 | } 100 | 101 | TEST(stdarray, large_array_endian) 102 | { 103 | auto [data, in, out] = 104 | zpp::bits::data_in_out(zpp::bits::endian::swapped{}); 105 | std::array a1 = {1, 2, 3, 4}; 106 | out(a1).or_throw(); 107 | 108 | std::array a2{}; 109 | in(a2).or_throw(); 110 | 111 | for (std::size_t i = 0; i < std::extent_v; ++i) { 112 | EXPECT_EQ(a1[i], a2[i]); 113 | } 114 | } 115 | 116 | TEST(stdarray, large_array_in_struct_endian) 117 | { 118 | auto [data, in, out] = 119 | zpp::bits::data_in_out(zpp::bits::endian::swapped{}); 120 | struct a 121 | { 122 | std::array a1 = {1,2,3,4}; 123 | }; 124 | 125 | a a1 = {1,2,3,4}; 126 | out(a1).or_throw(); 127 | 128 | a a2; 129 | in(a2).or_throw(); 130 | 131 | for (std::size_t i = 0; i < std::extent_v; ++i) { 132 | EXPECT_EQ(a1.a1[i], a2.a1[i]); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /test/src/test_unique_ptr.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | TEST(unique_ptr, regular) 4 | { 5 | auto [data, in, out] = zpp::bits::data_in_out(); 6 | out(std::make_unique>(std::vector{1, 2, 3, 4})) 7 | .or_throw(); 8 | 9 | EXPECT_EQ(encode_hex(data), 10 | "04000000" 11 | "01000000" 12 | "02000000" 13 | "03000000" 14 | "04000000"); 15 | 16 | std::unique_ptr> p; 17 | in(p).or_throw(); 18 | 19 | EXPECT_EQ(*p, (std::vector{1,2,3,4})); 20 | } 21 | -------------------------------------------------------------------------------- /test/src/test_unordered_map.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | TEST(unordered_map, integer) 5 | { 6 | auto [data, in, out] = zpp::bits::data_in_out(); 7 | out(std::unordered_map{{1, 1}, {2, 2}, {3, 3}, {4, 4}}) 8 | .or_throw(); 9 | 10 | auto count_bytes = encode_hex(data); 11 | count_bytes.resize(8); 12 | EXPECT_EQ(count_bytes, "04000000"); 13 | 14 | std::unordered_map s; 15 | in(s).or_throw(); 16 | 17 | EXPECT_EQ( 18 | s, (std::unordered_map{{1, 1}, {2, 2}, {3, 3}, {4, 4}})); 19 | } 20 | 21 | TEST(unordered_map, const_integer) 22 | { 23 | auto [data, in, out] = zpp::bits::data_in_out(); 24 | const std::unordered_map m{{1, 1}, {2, 2}, {3, 3}, {4, 4}}; 25 | out(m).or_throw(); 26 | 27 | auto count_bytes = encode_hex(data); 28 | count_bytes.resize(8); 29 | EXPECT_EQ(count_bytes, "04000000"); 30 | 31 | std::unordered_map s; 32 | in(s).or_throw(); 33 | 34 | EXPECT_EQ( 35 | s, (std::unordered_map{{1, 1}, {2, 2}, {3, 3}, {4, 4}})); 36 | } 37 | 38 | TEST(unordered_map, string) 39 | { 40 | using namespace std::string_literals; 41 | auto [data, in, out] = zpp::bits::data_in_out(); 42 | out(std::unordered_map{ 43 | {"1"s, "1"s}, {"2"s, "2"s}, {"3"s, "3"s}, {"4"s, "4"s}}) 44 | .or_throw(); 45 | 46 | auto count_bytes = encode_hex(data); 47 | count_bytes.resize(8); 48 | EXPECT_EQ(count_bytes, "04000000"); 49 | 50 | std::unordered_map s; 51 | in(s).or_throw(); 52 | 53 | EXPECT_EQ( 54 | s, 55 | (std::unordered_map{ 56 | {"1"s, "1"s}, {"2"s, "2"s}, {"3"s, "3"s}, {"4"s, "4"s}})); 57 | } 58 | -------------------------------------------------------------------------------- /test/src/test_unordered_set.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include 3 | 4 | TEST(unordered_set, integer) 5 | { 6 | auto [data, in, out] = zpp::bits::data_in_out(); 7 | out(std::unordered_set{1,2,3,4}).or_throw(); 8 | 9 | auto count_bytes = encode_hex(data); 10 | count_bytes.resize(8); 11 | EXPECT_EQ(count_bytes, "04000000"); 12 | 13 | std::unordered_set s; 14 | in(s).or_throw(); 15 | 16 | EXPECT_EQ(s, (std::unordered_set{1,2,3,4})); 17 | } 18 | 19 | TEST(unordered_set, const_integer) 20 | { 21 | auto [data, in, out] = zpp::bits::data_in_out(); 22 | const std::unordered_set o{1,2,3,4}; 23 | out(o).or_throw(); 24 | 25 | auto count_bytes = encode_hex(data); 26 | count_bytes.resize(8); 27 | EXPECT_EQ(count_bytes, "04000000"); 28 | 29 | std::unordered_set s; 30 | in(s).or_throw(); 31 | 32 | EXPECT_EQ(s, (std::unordered_set{1,2,3,4})); 33 | } 34 | 35 | TEST(unordered_set, string) 36 | { 37 | using namespace std::string_literals; 38 | auto [data, in, out] = zpp::bits::data_in_out(); 39 | out(std::unordered_set{"1"s,"2"s,"3"s,"4"s}).or_throw(); 40 | 41 | auto count_bytes = encode_hex(data); 42 | count_bytes.resize(8); 43 | EXPECT_EQ(count_bytes, "04000000"); 44 | 45 | std::unordered_set s; 46 | in(s).or_throw(); 47 | 48 | EXPECT_EQ(s, (std::unordered_set{"1"s,"2"s,"3"s,"4"s})); 49 | } 50 | 51 | TEST(unordered_set, const_string) 52 | { 53 | using namespace std::string_literals; 54 | auto [data, in, out] = zpp::bits::data_in_out(); 55 | const std::unordered_set o{"1"s,"2"s,"3"s,"4"s}; 56 | out(o).or_throw(); 57 | 58 | auto count_bytes = encode_hex(data); 59 | count_bytes.resize(8); 60 | EXPECT_EQ(count_bytes, "04000000"); 61 | 62 | std::unordered_set s; 63 | in(s).or_throw(); 64 | 65 | EXPECT_EQ(s, (std::unordered_set{"1"s,"2"s,"3"s,"4"s})); 66 | } 67 | 68 | -------------------------------------------------------------------------------- /test/src/test_varint.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_varint 4 | { 5 | using namespace zpp::bits::literals; 6 | 7 | static_assert(zpp::bits::to_bytes{}>() == "00"_decode_hex); 8 | static_assert(zpp::bits::from_bytes<"9601"_decode_hex, zpp::bits::vint32_t>() == 150); 9 | static_assert(zpp::bits::from_bytes<"960100000000000000000000"_decode_hex, zpp::bits::vint32_t>() == 150); 10 | static_assert(zpp::bits::from_bytes<"960100000000000000000000"_decode_hex, zpp::bits::vsize_t>() == 150); 11 | static_assert(zpp::bits::from_bytes<"96818000"_decode_hex, zpp::bits::vint32_t>() == 150); 12 | static_assert(zpp::bits::from_bytes<"96818000"_decode_hex, zpp::bits::vsize_t>() == 150); 13 | 14 | static_assert(zpp::bits::to_bytes() == "9601"_decode_hex); 15 | 16 | static_assert(zpp::bits::varint_size( 17 | std::numeric_limits::max()) == 5); 18 | 19 | static_assert(zpp::bits::varint_size( 20 | std::numeric_limits::max()) == 10); 21 | 22 | static_assert(zpp::bits::varint_size(0) == 1); 23 | static_assert(zpp::bits::varint_size(0x7f) == 1); 24 | static_assert(zpp::bits::varint_size(0x80) == 2); 25 | static_assert(zpp::bits::varint_size(0x3fff) == 2); 26 | static_assert(zpp::bits::varint_size(0x1fffff) == 3); 27 | static_assert(zpp::bits::varint_size(0x3fffff) == 4); 28 | static_assert(zpp::bits::varint_size(0xfffffff) == 4); 29 | static_assert(zpp::bits::varint_size(0x1fffffff) == 5); 30 | static_assert(zpp::bits::varint_size(0xffffffff) == 5); 31 | static_assert(zpp::bits::varint_size(-1) == 5); 32 | 33 | static_assert( 34 | zpp::bits::to_bytes() == "ffffffff0f"_decode_hex); 35 | 36 | static_assert(zpp::bits::from_bytes<"ffffffff0f"_decode_hex, 37 | zpp::bits::vint32_t>() == -1); 38 | 39 | static_assert(zpp::bits::to_bytes() == 40 | "ffffffffffffffffff01"_decode_hex); 41 | 42 | static_assert(zpp::bits::from_bytes<"ffffffffffffffffff01"_decode_hex, 43 | zpp::bits::vint64_t>() == -1); 44 | 45 | static_assert( 46 | zpp::bits::from_bytes< 47 | zpp::bits::to_bytes(), 48 | zpp::bits::vint32_t>() == 0); 49 | 50 | static_assert( 51 | zpp::bits::from_bytes< 52 | zpp::bits::to_bytes(), 53 | zpp::bits::vint32_t>() == 1); 54 | 55 | static_assert( 56 | zpp::bits::from_bytes< 57 | zpp::bits::to_bytes(), 58 | zpp::bits::vint32_t>() == -1); 59 | 60 | static_assert( 61 | zpp::bits::from_bytes< 62 | zpp::bits::to_bytes(), 63 | zpp::bits::vint32_t>() == 0x7f); 64 | 65 | static_assert( 66 | zpp::bits::from_bytes< 67 | zpp::bits::to_bytes(), 68 | zpp::bits::vint64_t>() == 0x80); 69 | 70 | static_assert( 71 | zpp::bits::from_bytes< 72 | zpp::bits::to_bytes(), 73 | zpp::bits::vint64_t>() == 0); 74 | 75 | static_assert( 76 | zpp::bits::from_bytes< 77 | zpp::bits::to_bytes(), 78 | zpp::bits::vint64_t>() == 1); 79 | 80 | static_assert( 81 | zpp::bits::from_bytes< 82 | zpp::bits::to_bytes(), 83 | zpp::bits::vint64_t>() == -1); 84 | 85 | static_assert( 86 | zpp::bits::from_bytes< 87 | zpp::bits::to_bytes(), 88 | zpp::bits::vint64_t>() == 0x7f); 89 | 90 | static_assert( 91 | zpp::bits::from_bytes< 92 | zpp::bits::to_bytes(), 93 | zpp::bits::vint64_t>() == 0x80); 94 | 95 | static_assert(zpp::bits::to_bytes() == 96 | zpp::bits::to_bytes()); 97 | 98 | static_assert(zpp::bits::to_bytes() == 99 | zpp::bits::to_bytes()); 100 | 101 | static_assert(zpp::bits::to_bytes() == 102 | zpp::bits::to_bytes()); 103 | 104 | static_assert(zpp::bits::to_bytes() == 105 | zpp::bits::to_bytes()); 106 | 107 | static_assert(zpp::bits::to_bytes() == 108 | zpp::bits::to_bytes()); 109 | 110 | static_assert(zpp::bits::to_bytes() == 111 | zpp::bits::to_bytes()); 112 | 113 | static_assert(zpp::bits::to_bytes() == 114 | zpp::bits::to_bytes()); 115 | 116 | static_assert(zpp::bits::to_bytes() == 117 | zpp::bits::to_bytes()); 118 | 119 | static_assert(zpp::bits::to_bytes() == 120 | zpp::bits::to_bytes()); 121 | 122 | static_assert(zpp::bits::to_bytes() == 123 | zpp::bits::to_bytes()); 124 | 125 | static_assert(zpp::bits::to_bytes() == 126 | zpp::bits::to_bytes()); 127 | 128 | static_assert(zpp::bits::to_bytes() == 129 | zpp::bits::to_bytes()); 130 | 131 | static_assert( 132 | zpp::bits::from_bytes(), 133 | zpp::bits::vsint32_t>() == 0); 134 | 135 | static_assert(zpp::bits::to_bytes() == 136 | zpp::bits::to_bytes()); 137 | 138 | static_assert( 139 | zpp::bits::from_bytes(), 140 | zpp::bits::vsint32_t>() == 1); 141 | 142 | static_assert( 143 | zpp::bits::from_bytes(), 144 | zpp::bits::vsint32_t>() == 2); 145 | 146 | static_assert( 147 | zpp::bits::from_bytes(), 148 | zpp::bits::vsint32_t>() == 2147483647); 149 | 150 | static_assert( 151 | zpp::bits::from_bytes(), 152 | zpp::bits::vsint32_t>() == -2); 153 | 154 | static_assert( 155 | zpp::bits::from_bytes(), 156 | zpp::bits::vsint32_t>() == -2147483648); 157 | static_assert( 158 | zpp::bits::to_bytes{std::byte{0x7f}}>() == 159 | "7f"_decode_hex); 160 | 161 | TEST(varint, sanity) 162 | { 163 | auto [data, in, out] = zpp::bits::data_in_out(); 164 | out(zpp::bits::varint{150}).or_throw(); 165 | 166 | zpp::bits::varint i{0}; 167 | in(i).or_throw(); 168 | 169 | EXPECT_EQ(i, 150); 170 | } 171 | 172 | TEST(varint, representation) 173 | { 174 | auto [data, in, out] = zpp::bits::data_in_out(); 175 | out(zpp::bits::varint{150}).or_throw(); 176 | 177 | std::array representation{}; 178 | in(representation).or_throw(); 179 | 180 | EXPECT_EQ(out.position(), std::size_t{2}); 181 | EXPECT_EQ(representation, "9601"_decode_hex); 182 | } 183 | 184 | TEST(varint, varint_size) 185 | { 186 | auto [data, in, out] = data_in_out(zpp::bits::size_varint{}); 187 | auto o = 188 | std::vector{0x13, 0x80, 0x82, 0x1000, -1}; 189 | out(o).or_throw(); 190 | 191 | zpp::bits::vsize_t size; 192 | zpp::bits::in{data}(size).or_throw(); 193 | EXPECT_EQ(size, o.size()); 194 | 195 | std::vector v; 196 | in(v).or_throw(); 197 | 198 | EXPECT_EQ(v, o); 199 | } 200 | 201 | } // namespace test_varint 202 | -------------------------------------------------------------------------------- /test/src/test_vector.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_vector 4 | { 5 | 6 | TEST(vector, integer) 7 | { 8 | auto [data, in, out] = zpp::bits::data_in_out(); 9 | out(std::vector{1,2,3,4}).or_throw(); 10 | 11 | EXPECT_EQ(encode_hex(data), 12 | "04000000" 13 | "01000000" 14 | "02000000" 15 | "03000000" 16 | "04000000"); 17 | 18 | std::vector v; 19 | in(v).or_throw(); 20 | 21 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 22 | } 23 | 24 | TEST(vector, const_integer) 25 | { 26 | auto [data, in, out] = zpp::bits::data_in_out(); 27 | const std::vector o{1,2,3,4}; 28 | out(o).or_throw(); 29 | 30 | EXPECT_EQ(encode_hex(data), 31 | "04000000" 32 | "01000000" 33 | "02000000" 34 | "03000000" 35 | "04000000"); 36 | 37 | std::vector v; 38 | in(v).or_throw(); 39 | 40 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 41 | } 42 | 43 | TEST(vector, string) 44 | { 45 | using namespace std::string_literals; 46 | auto [data, in, out] = zpp::bits::data_in_out(); 47 | out(std::vector{"1"s,"2"s,"3"s,"4"s}).or_throw(); 48 | 49 | EXPECT_EQ(encode_hex(data), 50 | "04000000" 51 | "01000000" 52 | "31" 53 | "01000000" 54 | "32" 55 | "01000000" 56 | "33" 57 | "01000000" 58 | "34"); 59 | 60 | std::vector v; 61 | in(v).or_throw(); 62 | 63 | EXPECT_EQ(v, (std::vector{"1"s,"2"s,"3"s,"4"s})); 64 | } 65 | 66 | TEST(vector, const_string) 67 | { 68 | using namespace std::string_literals; 69 | auto [data, in, out] = zpp::bits::data_in_out(); 70 | const std::vector o{"1"s, "2"s, "3"s, "4"s}; 71 | out(o).or_throw(); 72 | 73 | EXPECT_EQ(encode_hex(data), 74 | "04000000" 75 | "01000000" 76 | "31" 77 | "01000000" 78 | "32" 79 | "01000000" 80 | "33" 81 | "01000000" 82 | "34"); 83 | 84 | std::vector v; 85 | in(v).or_throw(); 86 | 87 | EXPECT_EQ(v, (std::vector{"1"s,"2"s,"3"s,"4"s})); 88 | } 89 | 90 | TEST(vector, sized_1b_integer) 91 | { 92 | auto [data, in, out] = zpp::bits::data_in_out(); 93 | out(zpp::bits::sized(std::vector{1,2,3,4})).or_throw(); 94 | 95 | EXPECT_EQ(encode_hex(data), 96 | "04" 97 | "01000000" 98 | "02000000" 99 | "03000000" 100 | "04000000"); 101 | 102 | std::vector v; 103 | in(zpp::bits::sized(v)).or_throw(); 104 | 105 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 106 | } 107 | 108 | TEST(vector, unsized_integer) 109 | { 110 | auto [data, in, out] = zpp::bits::data_in_out(); 111 | out(zpp::bits::unsized(std::vector{1,2,3,4})).or_throw(); 112 | 113 | EXPECT_EQ(encode_hex(data), 114 | "01000000" 115 | "02000000" 116 | "03000000" 117 | "04000000"); 118 | 119 | std::vector v(4); 120 | in(zpp::bits::unsized(v)).or_throw(); 121 | 122 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 123 | } 124 | 125 | TEST(vector, sized_t_1b_integer) 126 | { 127 | auto [data, in, out] = zpp::bits::data_in_out(); 128 | out(zpp::bits::sized_t, std::uint8_t>{1,2,3,4}).or_throw(); 129 | 130 | EXPECT_EQ(encode_hex(data), 131 | "04" 132 | "01000000" 133 | "02000000" 134 | "03000000" 135 | "04000000"); 136 | 137 | zpp::bits::sized_t, std::uint8_t> v; 138 | in(v).or_throw(); 139 | 140 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 141 | } 142 | 143 | TEST(vector, unsized_t_integer) 144 | { 145 | auto [data, in, out] = zpp::bits::data_in_out(); 146 | out(zpp::bits::unsized_t>{1,2,3,4}).or_throw(); 147 | 148 | EXPECT_EQ(encode_hex(data), 149 | "01000000" 150 | "02000000" 151 | "03000000" 152 | "04000000"); 153 | 154 | zpp::bits::unsized_t> v(4); 155 | in(v).or_throw(); 156 | 157 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 158 | } 159 | 160 | TEST(vector, static_vector) 161 | { 162 | auto [data, in, out] = zpp::bits::data_in_out(); 163 | out(zpp::bits::static_vector{1,2,3,4}).or_throw(); 164 | 165 | EXPECT_EQ(encode_hex(data), 166 | "01000000" 167 | "02000000" 168 | "03000000" 169 | "04000000"); 170 | 171 | zpp::bits::static_vector v(4); 172 | in(v).or_throw(); 173 | 174 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 175 | } 176 | 177 | TEST(vector, vector1b) 178 | { 179 | auto [data, in, out] = zpp::bits::data_in_out(); 180 | out(zpp::bits::vector1b{1,2,3,4}).or_throw(); 181 | 182 | EXPECT_EQ(encode_hex(data), 183 | "04" 184 | "01000000" 185 | "02000000" 186 | "03000000" 187 | "04000000"); 188 | 189 | zpp::bits::vector1b v(4); 190 | in(v).or_throw(); 191 | 192 | EXPECT_EQ(v, (std::vector{1,2,3,4})); 193 | } 194 | 195 | } // namespace test_vector 196 | -------------------------------------------------------------------------------- /test/src/test_zero_copy_byte_types.cpp: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | namespace test_zero_copy_byte_types 4 | { 5 | 6 | using namespace std::literals; 7 | using namespace zpp::bits::literals; 8 | 9 | TEST(test_zero_copy_byte_types, span_const_byte) 10 | { 11 | auto [data, in, out] = zpp::bits::data_in_out(); 12 | out("hello"sv).or_throw(); 13 | 14 | std::span s; 15 | in(s).or_throw(); 16 | 17 | EXPECT_EQ(s.size(), "hello"sv.size()); 18 | EXPECT_EQ(std::memcmp("hello"sv.data(), s.data(), "hello"sv.size()), 0); 19 | } 20 | 21 | TEST(test_zero_copy_byte_types, unsized_span_const_byte) 22 | { 23 | auto [data, in, out] = zpp::bits::data_in_out(); 24 | out(zpp::bits::unsized("hello"sv)).or_throw(); 25 | 26 | std::span s; 27 | in(zpp::bits::unsized(s)).or_throw(); 28 | 29 | EXPECT_EQ(s.size(), "hello"sv.size()); 30 | EXPECT_EQ(std::memcmp("hello"sv.data(), s.data(), "hello"sv.size()), 0); 31 | } 32 | 33 | TEST(test_zero_copy_byte_types, span_const_char) 34 | { 35 | auto [data, in, out] = zpp::bits::data_in_out(); 36 | out("hello"sv).or_throw(); 37 | 38 | std::span s; 39 | in(s).or_throw(); 40 | 41 | EXPECT_EQ(s.size(), "hello"sv.size()); 42 | EXPECT_EQ(std::memcmp("hello"sv.data(), s.data(), "hello"sv.size()), 0); 43 | } 44 | 45 | TEST(test_zero_copy_byte_types, unsized_span_const_char) 46 | { 47 | auto [data, in, out] = zpp::bits::data_in_out(); 48 | out(zpp::bits::unsized("hello"sv)).or_throw(); 49 | 50 | std::span s; 51 | in(zpp::bits::unsized(s)).or_throw(); 52 | 53 | EXPECT_EQ(s.size(), "hello"sv.size()); 54 | EXPECT_EQ(std::memcmp("hello"sv.data(), s.data(), "hello"sv.size()), 0); 55 | } 56 | 57 | TEST(test_zero_copy_byte_types, span_const_unsigned_char) 58 | { 59 | auto [data, in, out] = zpp::bits::data_in_out(); 60 | out("hello"sv).or_throw(); 61 | 62 | std::span s; 63 | in(s).or_throw(); 64 | 65 | EXPECT_EQ(s.size(), "hello"sv.size()); 66 | EXPECT_EQ(std::memcmp("hello"sv.data(), s.data(), "hello"sv.size()), 0); 67 | } 68 | 69 | TEST(test_zero_copy_byte_types, unsized_span_const_unsigned_char) 70 | { 71 | auto [data, in, out] = zpp::bits::data_in_out(); 72 | out(zpp::bits::unsized("hello"sv)).or_throw(); 73 | 74 | std::span s; 75 | in(zpp::bits::unsized(s)).or_throw(); 76 | 77 | EXPECT_EQ(s.size(), "hello"sv.size()); 78 | EXPECT_EQ(std::memcmp("hello"sv.data(), s.data(), "hello"sv.size()), 0); 79 | } 80 | 81 | TEST(test_zero_copy_byte_types, string_view) 82 | { 83 | auto [data, in, out] = zpp::bits::data_in_out(); 84 | out("hello"sv).or_throw(); 85 | 86 | std::string_view s; 87 | in(s).or_throw(); 88 | 89 | EXPECT_EQ(s.size(), "hello"sv.size()); 90 | EXPECT_EQ(std::memcmp("hello"sv.data(), s.data(), "hello"sv.size()), 0); 91 | } 92 | 93 | TEST(test_zero_copy_byte_types, unsized_string_view) 94 | { 95 | auto [data, in, out] = zpp::bits::data_in_out(); 96 | out(zpp::bits::unsized("hello"sv)).or_throw(); 97 | 98 | std::string_view s; 99 | in(zpp::bits::unsized(s)).or_throw(); 100 | 101 | EXPECT_EQ(s.size(), "hello"sv.size()); 102 | EXPECT_EQ(std::memcmp("hello"sv.data(), s.data(), "hello"sv.size()), 0); 103 | } 104 | 105 | } // namespace test_zero_copy_byte_types 106 | -------------------------------------------------------------------------------- /test/zpp_project.mk: -------------------------------------------------------------------------------- 1 | ifeq ($(ZPP_PROJECT_SETTINGS), true) 2 | ZPP_TARGET_NAME := output 3 | ZPP_TARGET_TYPES := default 4 | ZPP_LINK_TYPE := default 5 | ZPP_CPP_MODULES_TYPE := 6 | ZPP_OUTPUT_DIRECTORY_ROOT := out 7 | ZPP_INTERMEDIATE_DIRECTORY_ROOT = obj 8 | ZPP_SOURCE_DIRECTORIES := src 9 | ZPP_SOURCE_FILES := 10 | ZPP_INCLUDE_PROJECTS := 11 | ZPP_COMPILE_COMMANDS_JSON := compile_commands.json 12 | endif 13 | 14 | ifeq ($(ZPP_PROJECT_FLAGS), true) 15 | ZPP_BITS_AUTODETECT_MEMBERS_MODE ?= 0 16 | ZPP_FLAGS := \ 17 | $(patsubst %, -I%, $(shell find . -type d -name "inc" -or -name "include")) \ 18 | -pedantic -Wall -Wextra -Werror -fPIE -Isrc/gtest -pthread -I../ -I../../zpp_throwing \ 19 | -DZPP_BITS_AUTODETECT_MEMBERS_MODE=$(ZPP_BITS_AUTODETECT_MEMBERS_MODE) 20 | ZPP_FLAGS_DEBUG := -g -fsanitize=address -O2 21 | ZPP_FLAGS_RELEASE := \ 22 | -O2 -DNDEBUG -ffunction-sections \ 23 | -fdata-sections -fvisibility=hidden 24 | ZPP_CFLAGS := $(ZPP_FLAGS) -std=c11 25 | ZPP_CFLAGS_DEBUG := $(ZPP_FLAGS_DEBUG) 26 | ZPP_CFLAGS_RELEASE := $(ZPP_FLAGS_RELEASE) 27 | ZPP_CXXFLAGS := $(ZPP_FLAGS) -std=c++20 -stdlib=libc++ 28 | ZPP_CXXFLAGS_DEBUG := $(ZPP_FLAGS_DEBUG) 29 | ZPP_CXXFLAGS_RELEASE := $(ZPP_FLAGS_RELEASE) 30 | ZPP_CXXMFLAGS := -fPIE 31 | ZPP_CXXMFLAGS_DEBUG := -g 32 | ZPP_CXXMFLAGS_RELEASE := 33 | ZPP_ASFLAGS := $(ZPP_FLAGS) -x assembler-with-cpp 34 | ZPP_ASFLAGS_DEBUG := $(ZPP_FLAGS_DEBUG) 35 | ZPP_ASFLAGS_RELEASE := $(ZPP_FLAGS_RELEASE) 36 | ifneq ($(shell uname -s), Darwin) 37 | ZPP_LFLAGS := $(ZPP_FLAGS) $(ZPP_CXXFLAGS) -pie -Wl,--no-undefined 38 | ZPP_LFLAGS_DEBUG := $(ZPP_FLAGS_DEBUG) 39 | ZPP_LFLAGS_RELEASE := $(ZPP_FLAGS_RELEASE) \ 40 | -Wl,--strip-all -Wl,--gc-sections 41 | else 42 | ZPP_LFLAGS := $(ZPP_FLAGS) $(ZPP_CXXFLAGS) 43 | ZPP_LFLAGS_DEBUG := $(ZPP_FLAGS_DEBUG) 44 | ZPP_LFLAGS_RELEASE := $(ZPP_FLAGS_RELEASE) \ 45 | -Wl,-dead_strip 46 | endif 47 | endif 48 | 49 | ifeq ($(ZPP_PROJECT_RULES), true) 50 | endif 51 | 52 | ifeq ($(ZPP_TOOLCHAIN_SETTINGS), true) 53 | ZPP_CC := clang 54 | ZPP_CXX := clang++ 55 | ZPP_AS := $(ZPP_CC) 56 | ZPP_LINK := $(ZPP_CXX) 57 | ZPP_AR := ar 58 | ZPP_PYTHON := python3 59 | ZPP_POSTLINK_COMMANDS := 60 | endif 61 | 62 | --------------------------------------------------------------------------------