├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── doc ├── Doxyfile.in └── graphics │ ├── complex.png │ ├── complex.tex │ ├── eventchaining.png │ ├── eventchaining.tex │ ├── example.png │ ├── example.tex │ ├── multicast.png │ └── multicast.tex ├── include └── sigcxx │ ├── binode.hpp │ ├── delegate.hpp │ ├── macros.hpp │ └── sigcxx.hpp ├── src ├── CMakeLists.txt ├── binode.cpp └── sigcxx.cpp └── test ├── CMakeLists.txt ├── common ├── CMakeLists.txt ├── observer.cpp ├── observer.hpp ├── subject.cpp └── subject.hpp ├── gtest ├── CHANGES ├── CMakeLists.txt ├── CONTRIBUTORS ├── LICENSE ├── README ├── README.md ├── cmake │ └── internal_utils.cmake ├── include │ └── gtest │ │ ├── gtest-death-test.h │ │ ├── gtest-message.h │ │ ├── gtest-param-test.h │ │ ├── gtest-param-test.h.pump │ │ ├── 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 │ │ ├── gtest-port.h │ │ ├── gtest-printers.h │ │ └── gtest.h │ │ ├── gtest-death-test-internal.h │ │ ├── gtest-filepath.h │ │ ├── gtest-internal.h │ │ ├── gtest-linked_ptr.h │ │ ├── gtest-param-util-generated.h │ │ ├── gtest-param-util-generated.h.pump │ │ ├── gtest-param-util.h │ │ ├── gtest-port-arch.h │ │ ├── gtest-port.h │ │ ├── gtest-string.h │ │ ├── gtest-tuple.h │ │ ├── gtest-tuple.h.pump │ │ ├── gtest-type-util.h │ │ └── gtest-type-util.h.pump └── src │ ├── gtest-all.cc │ ├── gtest-death-test.cc │ ├── gtest-filepath.cc │ ├── gtest-internal-inl.h │ ├── gtest-port.cc │ ├── gtest-printers.cc │ ├── gtest-test-part.cc │ ├── gtest-typed-test.cc │ ├── gtest.cc │ └── gtest_main.cc └── unit ├── CMakeLists.txt ├── compare_boost_signal2 ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── compare_qt5 ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── delegate ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── disconnect_on_fire ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── disconnect_with_slot ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── signal_base ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── signal_check_connection ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── signal_connect ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── signal_delete_this ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── signal_disconnect ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── signal_virtual ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp ├── thread_safe ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp └── trackable_unbind ├── CMakeLists.txt ├── main.cpp ├── test.cpp └── test.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /build/ 3 | /cmake-build-debug/ 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake project for sigcxx 2 | # 3 | 4 | cmake_minimum_required(VERSION 2.8.11) 5 | 6 | project(sigcxx) 7 | 8 | # The project version number. 9 | set(VERSION_MAJOR 1 CACHE STRING "Project major version number.") 10 | set(VERSION_MINOR 0 CACHE STRING "Project minor version number.") 11 | set(VERSION_PATCH 0 CACHE STRING "Project patch version number.") 12 | mark_as_advanced(VERSION_MAJOR VERSION_MINOR VERSION_PATCH) 13 | 14 | # You may need to set environment variable CMAKE_PREFIX_PATH, see http://doc.qt.io/qt-5/cmake-manual.html 15 | option(BUILD_UNIT_TEST "Build unit test code" OFF) 16 | option(WITH_QT5 "Build unit test to compare this with Qt5" OFF) 17 | 18 | find_package(Doxygen) 19 | option(BUILD_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" ${DOXYGEN_FOUND}) 20 | 21 | if (BUILD_DOCUMENTATION) 22 | if (NOT DOXYGEN_FOUND) 23 | message(FATAL_ERROR "Doxygen is needed to build the documentation.") 24 | endif () 25 | 26 | set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in) 27 | set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) 28 | set(doxy_main_page ${CMAKE_CURRENT_SOURCE_DIR}/README.md) 29 | 30 | configure_file(${doxyfile_in} ${doxyfile} @ONLY) 31 | 32 | add_custom_target(doc 33 | COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile} 34 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 35 | COMMENT "Generating API documentation with Doxygen" 36 | VERBATIM) 37 | add_custom_command(TARGET doc 38 | POST_BUILD 39 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_BINARY_DIR}/html/doc 40 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 41 | COMMENT "Copy \"${CMAKE_CURRENT_SOURCE_DIR}/doc\" to \"${CMAKE_CURRENT_BINARY_DIR}/html\"" 42 | VERBATIM) 43 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/doc) 44 | endif () 45 | 46 | 47 | if (CMAKE_BUILD_TYPE STREQUAL "Debug") 48 | add_definitions(-D__DEBUG__) 49 | if (CMAKE_SYSTEM_NAME STREQUAL "Windows") 50 | set(CMAKE_CXX_FLAGS "/W4") 51 | else () 52 | set(CMAKE_CXX_FLAGS "-g -Wall -std=c++14") 53 | endif () 54 | else () 55 | if (CMAKE_SYSTEM_NAME STREQUAL "Windows") 56 | set(CMAKE_CXX_FLAGS "/W4") 57 | else () 58 | set(CMAKE_CXX_FLAGS "-O3 -Wall -std=c++14") 59 | endif () 60 | endif () 61 | 62 | include_directories(${PROJECT_SOURCE_DIR}/include) 63 | 64 | add_subdirectory(src) 65 | 66 | if (BUILD_UNIT_TEST) 67 | add_subdirectory(test) 68 | endif () 69 | 70 | install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/sigcxx" DESTINATION include) 71 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Freeman Zhang 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sigcxx 2 | ====== 3 | 4 | **Note:** The code in this repository may be out-of-dated, the latest can be found [here](https://github.com/wiztk/framework). 5 | 6 | ## Overview 7 | 8 | [sigcxx](https://github.com/zhanggyb/sigcxx) is a lightweight, fast C++11 9 | signal/slot (event/delegate) framework, inspired by: 10 | 11 | - [Member Function Pointers and the Fastest Possible C++ 12 | Delegates](http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible), 13 | author: Don Clugston 14 | - [The Impossibly Fast C++ 15 | Delegates](http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates), 16 | author: Sergey Ryazanov 17 | 18 | - [Fast C++ Delegate: Boost.Function 'drop-in' replacement and 19 | multicast](http://www.codeproject.com/Articles/18389/Fast-C-Delegate-Boost-Function-drop-in-replacement), 20 | author: JaeWook Choi 21 | 22 | - [CppEvents](http://code.google.com/p/cpp-events/), author: Nickolas 23 | V. Pohilets 24 | 25 | Originally [signals and slots](http://doc.qt.io/qt-5/signalsandslots.html) is a 26 | language construct introduced in Qt for communication between objects. In other 27 | language or framework, the similar technique is called [events and 28 | delegates](https://www.google.com/search?q=event+delegate&ie=utf-8&oe=utf-8). Signal 29 | and slot makes it easy to implement the Subject/Observer pattern while avoiding 30 | boilerplate code. The concept is that objects (typically GUI widgets) can send 31 | signals containing event information which can be received by other objects 32 | using special functions known as slots. This is similar to C/C++ callbacks 33 | (function pointers), but signal/slot system ensures the type-correctness of 34 | callback arguments. 35 | 36 | This project is another C++ signal/slot implementation, it requires and takes 37 | advantage of C++11 standard, provides a simple and fast way by minimal and 38 | comprehensible code. 39 | 40 | ## Features 41 | 42 | - Based on fast C++ delegates 43 | - Powered by variadic template in C++11 44 | - Multicast 45 | - Slot can be virtual and pure virtual 46 | - Signal chaining 47 | - Automatic disconnecting 48 | - etc. 49 | 50 | ## Installation 51 | 52 | Just drag the header files in `include/` and source files in `src/` to your 53 | project. Or use CMake to build and install a library: 54 | 55 | ```shell 56 | $ mkdir build 57 | $ cd build 58 | $ cmake ../ -DCMAKE_INSTALL_PREFIX=/usr/local 59 | $ make 60 | $ sudo make install 61 | ``` 62 | 63 | This will finally install 2 header files into 64 | `/usr/local/include/sigcxx`, and a `libsigcxx.a` into 65 | `/usr/local/lib`. 66 | 67 | ## Usage 68 | 69 | Let's use an example to show how to use `sigcxx`. Assume that you are trying to 70 | develop a new GUI application and need a signal/slot framework for communication 71 | between GUI objects. This is a typical scenario in which a signal/slot 72 | (event/delegate) works as a basic function. For example, when a button is 73 | clicked, or the value of a slider bar is changed, you want to emit a signal to 74 | notify another object to react and do something (update the framebuffer, change 75 | the text displayed, etc.). In general, a button may have more than one `clicked` 76 | signal, there may be 'toggled', 'hovered' signals. Such situation can be 77 | illustrated as below: 78 | 79 |
80 | Example 81 |
82 | 83 | ### Include necessary header file 84 | 85 | There's only one header file need to be included: 86 | 87 | ```c++ 88 | #include 89 | ``` 90 | 91 | ### Inherit from `sigcxx::Trackable` 92 | 93 | Not any member function can be connected by a signal, the slot method must be 94 | member function of a `sigcxx::Trackable` or its subclass. 95 | 96 | ```c++ 97 | class Widget: public sigcxx::Trackable 98 | { 99 | // ... 100 | }; 101 | ``` 102 | 103 | Slot method can have arbitray number of arguments, but must ended with 104 | `sigcxx::SLOT`. 105 | 106 | ```c++ 107 | class Observer: public Widget 108 | { 109 | public: 110 | // ... 111 | 112 | void onUpdate1 (sigcxx::SLOT slot = nullptr); 113 | void onUpdate2 (const Foo* param, sigcxx::SLOT slot = nullptr); 114 | }; 115 | ``` 116 | 117 | The `SLOT` here is just a `typedef`: 118 | 119 | ```c++ 120 | namespace sigcxx { 121 | // ... 122 | typedef Slot *SLOT; 123 | } 124 | ``` 125 | 126 | It's recommended to give it a default value of `nullptr`. You can use a macro to 127 | make the code cleaner: 128 | 129 | ```c++ 130 | #define __SLOT__ sigcxx::SLOT slot = nullptr 131 | 132 | class Observer: public sigcxx::Trackable 133 | { 134 | public: 135 | // ... 136 | 137 | void onUpdate3 (__SLOT__); 138 | void onUpdate4 (int a, int b, const Foo* foo, __SLOT__); 139 | }; 140 | ``` 141 | 142 | ### Decleare and expose signals in Subject 143 | 144 | It's highly recommended to use the template class `sigcxx::Signal<>` to declare 145 | signals as a member variable, and expose the signal with 146 | `sigcxx::SignalRefT<>`. Both of them are variadic templates and can take arbitray 147 | number of template arguments. 148 | 149 | ```c++ 150 | class Subject 151 | { 152 | public: 153 | 154 | // ... 155 | 156 | sigcxx::SignalRefT<> notify1 () { 157 | return notify1_; 158 | } 159 | 160 | sigcxx::SignalRefT notify2 () { 161 | return notify2_; 162 | } 163 | 164 | protected: 165 | virtual void mousePressEvent (MouseEvent* event) 166 | { 167 | // ... 168 | notify1_.Emit(); 169 | } 170 | 171 | virtual void keyPressEvent (KeyEvent* event) 172 | { 173 | // ... 174 | notify2_.Emit(foo); 175 | } 176 | 177 | private: 178 | sigcxx::Signal<> notify1_; 179 | sigcxx::Signal notify2_; 180 | }; 181 | ``` 182 | 183 | ### Connect signals when you want 184 | 185 | Use the `Connect` method of `sigcxx::SignalRefT<>`: 186 | 187 | ```c++ 188 | Subject subject; 189 | Observer observer1; 190 | Observer observer2; 191 | 192 | // ... 193 | 194 | subject.notify1().Connect(&observer1, &Observer::onUpdate1); 195 | subject.notify2().Connect(&observer2, &Observer::onUpdate2); 196 | ``` 197 | 198 | Now when any event in `subject` is emitted, it will call corresponding method in 199 | Observer objects. Note that the template arguments in the signal must match the 200 | arguments of a slot method, except the last `sigcxx::SLOT`, it's reserved to 201 | work as a signature to avoid any method to be a slot and has special usage in 202 | runtime. 203 | 204 | A signal supports multi-cast, can be connected to a virtual (even pure virtual) 205 | function, it can also be disconnected manually or automatically when observer 206 | object is destroyed. For more information, please see the [Wiki 207 | page](https://github.com/zhanggyb/sigcxx/wiki). 208 | 209 | ## Known Issue 210 | 211 | This project currently does not support MSVC.(FIXME) 212 | 213 | ## License 214 | 215 | This project is licensed under [MIT License](https://github.com/zhanggyb/sigcxx/blob/master/LICENSE). 216 | -------------------------------------------------------------------------------- /doc/graphics/complex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhanggyb/sigcxx/b50f35bfb76ce6d46ca80c424152bc05c5ad72e5/doc/graphics/complex.png -------------------------------------------------------------------------------- /doc/graphics/complex.tex: -------------------------------------------------------------------------------- 1 | % file: example.tex 2 | % 3 | % Use: 4 | % $ pdflatex -shell-escape 5 | % to generate a png image. 6 | 7 | \documentclass[11pt,tikz,border=1,convert={outfile=\jobname.png}]{standalone} 8 | \usetikzlibrary{calc,positioning,arrows.meta,shadows} 9 | 10 | \begin{document} 11 | \begin{tikzpicture}[ 12 | object/.style={thick,fill=white,rectangle,rounded corners=5pt,draw,minimum width=100pt,minimum height=120pt,drop shadow}, 13 | token/.style={circle,draw,fill=yellow!50,minimum size=6pt}, 14 | binding/.style={circle,draw,fill=violet!50,minimum size=6pt} 15 | ] 16 | 17 | \node(subject) [object] {}; 18 | \node(subjectName) [below] at (subject.north) {\bf Subject1}; 19 | \node(event1) [token] at (subject.east) {}; 20 | 21 | \node(subject2) [object,below=of subject,xshift=5mm] {}; 22 | \node(subjectName2) [below] at (subject2.north) {\bf Subject2}; 23 | \node(event2) [token] at (subject2.east) {}; 24 | 25 | \node(observer1) [right=5cm of subject,yshift=4cm,object] {}; 26 | \node(observer1Name) [below] at (observer1.north) {\bf Observer1}; 27 | \node(method1) [binding,yshift=-10pt] at (observer1.west) {}; 28 | 29 | \node(observer2) [right=5cm of subject,yshift=-1cm,object] {}; 30 | \node(observer2Name) [below] at (observer2.north) {\bf Observer2}; 31 | \node(method2) [binding,yshift=-10pt] at (observer2.west) {}; 32 | 33 | \node(observer3) [right=5cm of subject,yshift=-7cm,object] {}; 34 | \node(observer3Name) [below] at (observer3.north) {\bf Observer($n$)}; 35 | \node(method3) [binding,yshift=-10pt] at (observer3.west) {}; 36 | 37 | \node [below,rotate=90,xshift=-9mm] at (observer2.south) {\large $\ldots$}; 38 | 39 | \coordinate(a) at ($(event1.east)+(25mm,0)$); 40 | \coordinate(a1) at ($(event2.east)+(25mm,0)$); 41 | \coordinate(b) at ($(method1.west)-(25mm,0)$); 42 | \coordinate(c) at ($(method2.west)-(25mm,0)$); 43 | \coordinate(d) at ($(method3.west)-(25mm,0)$); 44 | 45 | \draw[->,dashed,-{Stealth}] (event1) .. controls (a) and (b) .. (method1); 46 | \draw[->,dashed,-{Stealth}] (event1) .. controls (a) and (c) .. (method2); 47 | \draw[->,dashed,-{Stealth}] (event1) .. controls (a) and (d) .. (method3); 48 | 49 | \draw[->,dashed,-{Stealth}] (event2) .. controls (a1) and (c) .. (method2); 50 | \draw[->,dashed,-{Stealth}] (event2) .. controls (a1) and (d) .. (method3); 51 | 52 | \node [left] at (event1.west) {\ttfamily event1}; 53 | \node [left] at (event2.west) {\ttfamily event2}; 54 | 55 | \end{tikzpicture} 56 | \end{document} 57 | -------------------------------------------------------------------------------- /doc/graphics/eventchaining.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhanggyb/sigcxx/b50f35bfb76ce6d46ca80c424152bc05c5ad72e5/doc/graphics/eventchaining.png -------------------------------------------------------------------------------- /doc/graphics/eventchaining.tex: -------------------------------------------------------------------------------- 1 | % file: example.tex 2 | % 3 | % Use: 4 | % $ pdflatex -shell-escape 5 | % to generate a png image. 6 | 7 | \documentclass[11pt,tikz,border=1,convert={outfile=\jobname.png}]{standalone} 8 | \usetikzlibrary{calc,positioning,arrows.meta,shadows} 9 | 10 | \begin{document} 11 | \begin{tikzpicture}[ 12 | object/.style={thick,fill=white,rectangle,rounded corners=5pt,draw,minimum width=100pt,minimum height=120pt,drop shadow}, 13 | token/.style={circle,draw,fill=yellow!50,minimum size=6pt}, 14 | binding/.style={circle,draw,fill=violet!50,minimum size=6pt} 15 | ] 16 | 17 | \node(subject) [object] {}; 18 | \node(subjectName) [below] at (subject.north) {\bf Object1}; 19 | \node(event1) [token] at (subject.east) {}; 20 | 21 | \node(observer1) [right=2cm of subject,yshift=3cm,object] {}; 22 | \node(observer1Name) [below] at (observer1.north) {\bf Object2}; 23 | \node(event2) [token,yshift=-10pt] at (observer1.east) {}; 24 | 25 | \node(observer2) [right=10cm of subject,yshift=-1cm,object] {}; 26 | \node(observer2Name) [below] at (observer2.north) {\bf Object3}; 27 | \node(method2) [binding,yshift=-10pt] at (observer2.west) {}; 28 | 29 | \coordinate(a) at ($(event1.east)+(25mm,0)$); 30 | \coordinate(b) at ($(event2.west)-(25mm,0)$); 31 | \coordinate(c) at ($(event2.east)+(25mm,0)$); 32 | \coordinate(d) at ($(method2.west)-(25mm,0)$); 33 | 34 | \draw[->,dashed,-{Stealth}] (event1) .. controls (a) and (b) .. (event2); 35 | \draw[->,dashed,-{Stealth}] (event2) .. controls (c) and (d) .. (method2); 36 | 37 | \node [left] at (event1.west) {\ttfamily event1}; 38 | \node [right,yshift=2mm] at (event2.north east) {\ttfamily event2}; 39 | \node [right] at (method2.east) {\ttfamily onUpdate()}; 40 | 41 | \end{tikzpicture} 42 | \end{document} 43 | -------------------------------------------------------------------------------- /doc/graphics/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhanggyb/sigcxx/b50f35bfb76ce6d46ca80c424152bc05c5ad72e5/doc/graphics/example.png -------------------------------------------------------------------------------- /doc/graphics/example.tex: -------------------------------------------------------------------------------- 1 | % file: example.tex 2 | % 3 | % Use: 4 | % $ pdflatex -shell-escape 5 | % to generate a png image. 6 | 7 | \documentclass[11pt,tikz,border=1,convert={outfile=\jobname.png}]{standalone} 8 | \usetikzlibrary{calc,positioning,arrows.meta,shadows} 9 | 10 | \begin{document} 11 | \begin{tikzpicture}[ 12 | object/.style={thick,fill=white,rectangle,rounded corners=5pt,draw,minimum width=100pt,minimum height=120pt,drop shadow}, 13 | token/.style={circle,draw,fill=yellow!50,minimum size=6pt}, 14 | binding/.style={circle,draw,fill=violet!50,minimum size=6pt} 15 | ] 16 | 17 | \node(subject) [object] {}; 18 | \node(subjectName) [below] at (subject.north) {\bf Subject}; 19 | \node(event1) [token] at (subject.east) {}; 20 | \node(event2) [token,yshift=-20pt] at (subject.east) {}; 21 | 22 | \node(observer1) [right=5cm of subject,yshift=4cm,object] {}; 23 | \node(observer1Name) [below] at (observer1.north) {\bf Observer1}; 24 | \node(method1) [binding,yshift=-10pt] at (observer1.west) {}; 25 | 26 | \node(observer2) [right=4cm of subject,yshift=-3cm,object] {}; 27 | \node(observer2Name) [below] at (observer2.north) {\bf Observer2}; 28 | \node(method2) [binding,yshift=-10pt] at (observer2.west) {}; 29 | 30 | \coordinate(a) at ($(event1.east)+(25mm,0)$); 31 | \coordinate(b) at ($(method1.west)-(25mm,0)$); 32 | \coordinate(c) at ($(event2.east)+(25mm,0)$); 33 | \coordinate(d) at ($(method2.west)-(25mm,0)$); 34 | 35 | \draw[->,dashed,-{Stealth}] (event1) .. controls (a) and (b) .. (method1); 36 | \draw[->,dashed,-{Stealth}] (event2) .. controls (c) and (d) .. (method2); 37 | 38 | \node [left] at (event1.west) {\ttfamily notify1}; 39 | \node [left] at (event2.west) {\ttfamily notify2}; 40 | \node [right] at (method1.east) {\ttfamily onUpdate1()}; 41 | \node [right] at (method2.east) {\ttfamily onUpdate2()}; 42 | 43 | \end{tikzpicture} 44 | \end{document} 45 | -------------------------------------------------------------------------------- /doc/graphics/multicast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhanggyb/sigcxx/b50f35bfb76ce6d46ca80c424152bc05c5ad72e5/doc/graphics/multicast.png -------------------------------------------------------------------------------- /doc/graphics/multicast.tex: -------------------------------------------------------------------------------- 1 | % file: example.tex 2 | % 3 | % Use: 4 | % $ pdflatex -shell-escape 5 | % to generate a png image. 6 | 7 | \documentclass[11pt,tikz,border=1,convert={outfile=\jobname.png}]{standalone} 8 | \usetikzlibrary{calc,positioning,arrows.meta,shadows} 9 | 10 | \begin{document} 11 | \begin{tikzpicture}[ 12 | object/.style={thick,fill=white,rectangle,rounded corners=5pt,draw,minimum width=100pt,minimum height=120pt,drop shadow}, 13 | token/.style={circle,draw,fill=yellow!50,minimum size=6pt}, 14 | binding/.style={circle,draw,fill=violet!50,minimum size=6pt} 15 | ] 16 | 17 | \node(subject) [object] {}; 18 | \node(subjectName) [below] at (subject.north) {\bf Subject}; 19 | \node(event1) [token] at (subject.east) {}; 20 | 21 | \node(observer1) [right=5cm of subject,yshift=6cm,object] {}; 22 | \node(observer1Name) [below] at (observer1.north) {\bf Observer1}; 23 | \node(method1) [binding,yshift=-10pt] at (observer1.west) {}; 24 | 25 | \node(observer2) [right=5cm of subject,yshift=1cm,object] {}; 26 | \node(observer2Name) [below] at (observer2.north) {\bf Observer2}; 27 | \node(method2) [binding,yshift=-10pt] at (observer2.west) {}; 28 | 29 | \node(observer3) [right=5cm of subject,yshift=-5cm,object] {}; 30 | \node(observer3Name) [below] at (observer3.north) {\bf Observer($n$)}; 31 | \node(method3) [binding,yshift=-10pt] at (observer3.west) {}; 32 | 33 | \node [below,rotate=90,xshift=-9mm] at (observer2.south) {\large $\ldots$}; 34 | 35 | \coordinate(a) at ($(event1.east)+(25mm,0)$); 36 | \coordinate(b) at ($(method1.west)-(25mm,0)$); 37 | \coordinate(c) at ($(method2.west)-(25mm,0)$); 38 | \coordinate(d) at ($(method3.west)-(25mm,0)$); 39 | 40 | \draw[->,dashed,-{Stealth}] (event1) .. controls (a) and (b) .. (method1); 41 | \draw[->,dashed,-{Stealth}] (event1) .. controls (a) and (c) .. (method2); 42 | \draw[->,dashed,-{Stealth}] (event1) .. controls (a) and (d) .. (method3); 43 | 44 | \node [left] at (event1.west) {\ttfamily event}; 45 | 46 | \end{tikzpicture} 47 | \end{document} 48 | -------------------------------------------------------------------------------- /include/sigcxx/binode.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The WizTK Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * @file binode.hpp 19 | * @brief Header file for bidirectional node classes. 20 | */ 21 | 22 | #ifndef WIZTK_BASE_BINODE_HPP_ 23 | #define WIZTK_BASE_BINODE_HPP_ 24 | 25 | #include "sigcxx/macros.hpp" 26 | 27 | namespace sigcxx { 28 | 29 | /** 30 | * @ingroup base 31 | * @brief Base class for bidirectional node. 32 | * 33 | * You cannot initialize an instance of this base class directly. Instead, 34 | * create and use a subclass. 35 | */ 36 | class WIZTK_EXPORT BinodeBase { 37 | 38 | template friend 39 | class Deque; 40 | 41 | friend class CountedDequeNodeBase; 42 | friend class CountedDequeBase; 43 | 44 | template friend 45 | class CountedDeque; 46 | 47 | public: 48 | 49 | WIZTK_DECLARE_NONCOPYABLE(BinodeBase); 50 | 51 | /** 52 | * @brief Move constructor. 53 | * @param other 54 | */ 55 | BinodeBase(BinodeBase &&other) noexcept 56 | : previous_(other.previous_), next_(other.next_) { 57 | other.previous_ = nullptr; 58 | other.next_ = nullptr; 59 | } 60 | 61 | /** 62 | * @brief Destructor. 63 | * 64 | * The destructor will break the link to other node. 65 | */ 66 | virtual ~BinodeBase(); 67 | 68 | /** 69 | * @brief Move operator. 70 | * @param other 71 | * @return 72 | */ 73 | BinodeBase &operator=(BinodeBase &&other) noexcept { 74 | previous_ = other.previous_; 75 | next_ = other.next_; 76 | other.previous_ = nullptr; 77 | other.next_ = nullptr; 78 | return *this; 79 | } 80 | 81 | protected: 82 | 83 | static void PushFront(BinodeBase *node, BinodeBase *other); 84 | 85 | static void PushBack(BinodeBase *node, BinodeBase *other); 86 | 87 | static void Unlink(BinodeBase *node); 88 | 89 | static bool IsLinked(const BinodeBase *node) { 90 | return (nullptr != node->previous_) || (nullptr != node->next_); 91 | } 92 | 93 | virtual void OnUnlinked() {/* override this in subclass */} 94 | 95 | /** 96 | * @brief Default constructor 97 | */ 98 | BinodeBase() = default; 99 | 100 | BinodeBase *previous_ = nullptr; 101 | BinodeBase *next_ = nullptr; 102 | 103 | }; 104 | 105 | /** 106 | * @ingroup base 107 | * @brief A template class represents a bidirectional node. 108 | * @tparam T Usually a type of subclass 109 | * 110 | * Example usage: 111 | * @code 112 | * class MyNode : public base::Binode {}; 113 | * @endcode 114 | */ 115 | template 116 | class WIZTK_EXPORT Binode : public BinodeBase { 117 | 118 | public: 119 | 120 | /** 121 | * @brief Declare non-copyable. 122 | */ 123 | WIZTK_DECLARE_NONCOPYABLE(Binode); 124 | 125 | /** 126 | * @brief Default constructor. 127 | */ 128 | Binode() = default; 129 | 130 | /** 131 | * @brief Default move constructor. 132 | */ 133 | Binode(Binode &&) noexcept = default; 134 | 135 | /** 136 | * @brief Destructor. 137 | */ 138 | ~Binode() override = default; 139 | 140 | /** 141 | * @brief Default move operator. 142 | * @return Reference to this object. 143 | */ 144 | Binode &operator=(Binode &&) noexcept = default; 145 | 146 | /** 147 | * @brief Push a node with the same type at the back. 148 | * @param node 149 | */ 150 | inline void push_back(T *node) { PushBack(this, node); } 151 | 152 | /** 153 | * @brief Push a node with the same type at the front. 154 | * @param node 155 | */ 156 | inline void push_front(T *node) { PushFront(this, node); } 157 | 158 | /** 159 | * @brief Unlink this node. 160 | */ 161 | inline void unlink() { Unlink(this); } 162 | 163 | /** 164 | * @brief Returns if this node is linked with another. 165 | * @return 166 | */ 167 | inline bool is_linked() const { return IsLinked(this); } 168 | 169 | /** 170 | * @brief Get the previous node. 171 | * @return 172 | */ 173 | inline T *previous() const { return static_cast(previous_); } 174 | 175 | /** 176 | * @brief Get the next node. 177 | * @return 178 | */ 179 | inline T *next() const { return static_cast(next_); } 180 | 181 | }; 182 | 183 | } // namespace sigcxx 184 | 185 | #endif // WIZTK_BASE_BINODE_HPP_ 186 | -------------------------------------------------------------------------------- /include/sigcxx/macros.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2018 The WizTK Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef WIZTK_BASE_DEFINES_HPP_ 18 | #define WIZTK_BASE_DEFINES_HPP_ 19 | 20 | #ifdef __DEBUG__ 21 | 22 | //#ifdef __UNIX__ 23 | #include 24 | #define FILE_BASE_NAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) 25 | //#else 26 | //#include 27 | //#define FILE_BASE_FILENAME (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) 28 | //#endif 29 | 30 | #include 31 | #define _DEBUG(fmt, args...) \ 32 | do { \ 33 | fprintf(stderr, "%s:%d:%s(): " fmt, FILE_BASE_NAME, __LINE__, __FUNCTION__, args); \ 34 | } while (false) 35 | 36 | #include 37 | #define _ASSERT(expr) \ 38 | do { \ 39 | assert(expr); \ 40 | } while (false) 41 | 42 | #else // NOT __DEBUG__ 43 | 44 | #define _DEBUG(fmt, args...) ((void)0) 45 | #define _ASSERT(expr) ((void)0) 46 | 47 | #endif // END __DEBUG__ 48 | 49 | #define WIZTK_DISABLE_COPY_CONSTRUCTOR(CLASS) CLASS(const CLASS&) = delete 50 | #define WIZTK_DISABLE_COPY_ASSIGNMENT(CLASS) CLASS& operator=(const CLASS&) = delete 51 | #define WIZTK_DISABLE_MOVE_CONSTRUCTOR(CLASS) CLASS(CLASS&&) = delete 52 | #define WIZTK_DISABLE_MOVE_ASSIGNMENT(CLASS) CLASS& operator=(CLASS&&) = delete 53 | 54 | #define WIZTK_DECLARE_NONCOPYABLE(CLASS) \ 55 | CLASS (const CLASS&) = delete; \ 56 | CLASS& operator = (const CLASS&) = delete 57 | 58 | #define WIZTK_DECLARE_NONMOVABLE(CLASS) \ 59 | CLASS (CLASS&&) = delete; \ 60 | CLASS& operator = (CLASS&&) = delete 61 | 62 | #define WIZTK_DECLARE_NONCOPYABLE_AND_NONMOVALE(CLASS) \ 63 | CLASS (const CLASS&) = delete; \ 64 | CLASS& operator = (const CLASS&) = delete; \ 65 | CLASS (CLASS&&) = delete; \ 66 | CLASS& operator = (CLASS&&) = delete 67 | 68 | #ifdef WIZTK_SHARED_EXPORT 69 | #define WIZTK_EXPORT __attribute__((visibility("default"))) 70 | #define WIZTK_NO_EXPORT __attribute__((visibility("hidden"))) 71 | #else 72 | #define WIZTK_EXPORT 73 | #define WIZTK_NO_EXPORT 74 | #endif // WIZTK_SHARED_EXPORT 75 | 76 | #ifndef WIZTK_DEPRECATED 77 | #define WIZTK_DEPRECATED __attribute__ ((__deprecated__)) 78 | #endif 79 | 80 | #ifndef WIZTK_DEPRECATED_EXPORT 81 | #define WIZTK_DEPRECATED_EXPORT WIZTK_EXPORT WIZTK_DEPRECATED 82 | #endif 83 | 84 | #ifndef WIZTK_DEPRECATED_NO_EXPORT 85 | #define WIZTK_DEPRECATED_NO_EXPORT WIZTK_NO_EXPORT WIZTK_DEPRECATED 86 | #endif 87 | 88 | #endif // WIZTK_BASE_DEFINES_HPP_ 89 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake file for sigcxx project 2 | # 3 | 4 | file(GLOB Header_Files "${PROJECT_SOURCE_DIR}/include/sigcxx/*.hpp") 5 | file(GLOB Source_Files "*.cpp") 6 | 7 | add_library (sigcxx ${Header_Files} ${Source_Files}) 8 | 9 | set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) 10 | 11 | if(NOT DEFINED BUILD_STATIC_LIBRARY) 12 | set_target_properties(sigcxx PROPERTIES VERSION 1 SOVERSION 1) 13 | endif() 14 | 15 | install(TARGETS sigcxx DESTINATION lib) 16 | -------------------------------------------------------------------------------- /src/binode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Freeman Zhang 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sigcxx/binode.hpp" 18 | 19 | namespace sigcxx { 20 | 21 | BinodeBase::~BinodeBase() { 22 | Unlink(this); 23 | } 24 | 25 | void BinodeBase::PushFront(BinodeBase *node, BinodeBase *other) { 26 | if (other == node) return; 27 | if (node->previous_ == other) return; 28 | 29 | Unlink(other); 30 | 31 | if (nullptr != node->previous_) node->previous_->next_ = other; 32 | other->previous_ = node->previous_; 33 | node->previous_ = other; 34 | other->next_ = node; 35 | } 36 | 37 | void BinodeBase::PushBack(BinodeBase *node, BinodeBase *other) { 38 | if (other == node) return; 39 | if (node->next_ == other)return; 40 | 41 | Unlink(other); 42 | 43 | if (nullptr != node->next_) node->next_->previous_ = other; 44 | other->next_ = node->next_; 45 | node->next_ = other; 46 | other->previous_ = node; 47 | } 48 | 49 | void BinodeBase::Unlink(BinodeBase *node) { 50 | bool notify = false; 51 | 52 | if (nullptr != node->previous_) { 53 | notify = true; 54 | node->previous_->next_ = node->next_; 55 | } 56 | 57 | if (nullptr != node->next_) { 58 | notify = true; 59 | node->next_->previous_ = node->previous_; 60 | } 61 | 62 | node->previous_ = nullptr; 63 | node->next_ = nullptr; 64 | 65 | if (notify) node->OnUnlinked(); 66 | } 67 | 68 | } // namespace sigcxx 69 | -------------------------------------------------------------------------------- /src/sigcxx.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2018 The WizTK Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sigcxx/sigcxx.hpp" 18 | 19 | namespace sigcxx { 20 | 21 | namespace internal { 22 | 23 | TrackableBindingNode::~TrackableBindingNode() { 24 | if (nullptr != token) { 25 | _ASSERT(token->binding == this); 26 | token->binding = nullptr; 27 | delete token; 28 | } 29 | } 30 | 31 | SignalTokenNode::~SignalTokenNode() { 32 | _ASSERT(nullptr == slot_mark_head.previous()); 33 | Slot::Mark *mark = nullptr; 34 | while (nullptr != slot_mark_head.next()) { 35 | mark = static_cast(slot_mark_head.next()); 36 | ++mark->slot()->it_; 37 | ++mark->slot()->ref_count_; 38 | mark->unlink(); 39 | } 40 | 41 | if (nullptr != binding) { 42 | _ASSERT(binding->token == this); 43 | binding->token = nullptr; 44 | delete binding; 45 | } 46 | } 47 | 48 | } // namespace internal 49 | 50 | Trackable::Trackable(const Trackable &) 51 | : Trackable() {} 52 | 53 | Trackable::~Trackable() { 54 | UnbindAllSignals(); 55 | } 56 | 57 | void Trackable::UnbindSignal(SLOT slot) { 58 | using internal::SignalTokenNode; 59 | 60 | if (slot->it_.get()->binding->trackable == this) { 61 | SignalTokenNode *tmp = slot->it_.get(); 62 | delete tmp; 63 | } 64 | } 65 | 66 | void Trackable::UnbindAllSignals() { 67 | internal::TrackableBindingNode *tmp = nullptr; 68 | 69 | internal::InterRelatedDeque::ReverseIterator it = bindings_.rbegin(); 70 | while (it) { 71 | tmp = it.get(); 72 | delete tmp; 73 | it = bindings_.rbegin(); 74 | } 75 | } 76 | 77 | size_t Trackable::CountSignalBindings() const { 78 | size_t count = 0; 79 | for (auto it = bindings_.cbegin(); it != bindings_.cend(); ++it) { 80 | count++; 81 | } 82 | return count; 83 | } 84 | 85 | // ------ 86 | 87 | } // namespace sigcxx 88 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # CMake file for libCppEvent project 3 | # 4 | 5 | include_directories(${PROJECT_SOURCE_DIR}/test/gtest/include) 6 | include_directories(${PROJECT_SOURCE_DIR}/test/common) 7 | 8 | add_subdirectory(gtest) 9 | add_subdirectory(common) 10 | add_subdirectory(unit) 11 | -------------------------------------------------------------------------------- /test/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB Source_Files "*.cpp") 2 | file(GLOB Header_Files "*.hpp") 3 | 4 | add_library (common ${Header_Files} ${Source_Files}) 5 | -------------------------------------------------------------------------------- /test/common/observer.cpp: -------------------------------------------------------------------------------- 1 | #include "observer.hpp" 2 | 3 | #include 4 | 5 | using sigcxx::Trackable; 6 | using sigcxx::SLOT; 7 | 8 | Observer::Observer() 9 | : Trackable(), test0_count_(0), test1_count_(0), test2_count_(0) { 10 | 11 | } 12 | 13 | Observer::~Observer() { 14 | 15 | } 16 | 17 | void Observer::OnTest0(SLOT /* slot */) { 18 | test0_count_++; 19 | } 20 | 21 | void Observer::OnTest1IntegerParam(int n, SLOT slot) { 22 | test1_count_++; 23 | } 24 | 25 | void Observer::OnTest2IntegerParams(int n1, int n2, SLOT) { 26 | test2_count_++; 27 | } 28 | 29 | void Observer::OnTestDestroy(SLOT slot) { 30 | delete this; 31 | } 32 | 33 | void Observer::OnTestUnbindOnceAt5(SLOT slot) { 34 | test0_count_++; 35 | if (test0_count_ >= 5) { 36 | UnbindSignal(slot); 37 | } 38 | } 39 | 40 | void Observer::OnTestUnbindAllAt5(SLOT slot) { 41 | test0_count_++; 42 | if (test0_count_ >= 5) { 43 | UnbindAllSignals(); 44 | } 45 | } 46 | 47 | void Observer::OnTestUnbindAllMethodAt5(SLOT slot) { 48 | test0_count_++; 49 | if (test0_count_ >= 5) { 50 | UnbindAllSignalsTo(&Observer::OnTestUnbindAllMethodAt5); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /test/common/observer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class Observer: public sigcxx::Trackable 6 | { 7 | public: 8 | 9 | Observer(); 10 | 11 | virtual ~Observer(); 12 | 13 | void OnTest0 (sigcxx::SLOT slot); 14 | 15 | void OnTest1IntegerParam(int n, sigcxx::SLOT slot = nullptr); 16 | 17 | void OnTest2IntegerParams(int n1, int n2, sigcxx::SLOT slot = nullptr); 18 | 19 | void OnTestDestroy (sigcxx::SLOT slot = nullptr); 20 | 21 | void OnTestUnbindOnceAt5 (sigcxx::SLOT slot = nullptr); 22 | 23 | void OnTestUnbindAllAt5 (sigcxx::SLOT slot = nullptr); 24 | 25 | void OnTestUnbindAllMethodAt5 (sigcxx::SLOT slot = nullptr); 26 | 27 | inline size_t test0_count () const 28 | { 29 | return test0_count_; 30 | } 31 | 32 | inline size_t test1_count () const 33 | { 34 | return test1_count_; 35 | } 36 | 37 | inline size_t test2_count () const 38 | { 39 | return test2_count_; 40 | } 41 | 42 | template 43 | void unbind_all(void (T::*method)(ParamTypes...)) { 44 | UnbindAllSignalsTo(method); 45 | }; 46 | 47 | void unbind_all() { 48 | UnbindAllSignals(); 49 | } 50 | 51 | private: 52 | 53 | size_t test0_count_; 54 | size_t test1_count_; 55 | size_t test2_count_; 56 | }; 57 | -------------------------------------------------------------------------------- /test/common/subject.cpp: -------------------------------------------------------------------------------- 1 | #include "subject.hpp" 2 | 3 | using sigcxx::Trackable; 4 | using sigcxx::SLOT; 5 | 6 | Subject::Subject() 7 | : Trackable(), 8 | test1_count_(0), test2_count_(0) { 9 | 10 | } 11 | 12 | Subject::~Subject() { 13 | 14 | } 15 | 16 | void Subject::OnTest1IntegerParam(int n, SLOT slot) { 17 | test1_count_++; 18 | } 19 | 20 | void Subject::OnTest2IntegerParams(int n1, int n2, SLOT slot) { 21 | test2_count_++; 22 | } -------------------------------------------------------------------------------- /test/common/subject.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class Subject: public sigcxx::Trackable 6 | { 7 | public: 8 | 9 | Subject(); 10 | 11 | virtual ~Subject(); 12 | 13 | inline void emit_signal0() 14 | { 15 | signal_0_.Emit(); 16 | } 17 | 18 | inline void emit_signal1(int n) 19 | { 20 | signal_1_int_.Emit(n); 21 | } 22 | 23 | inline void emit_signal2(int n1, int n2) 24 | { 25 | signal_2_int_.Emit(n1, n2); 26 | } 27 | 28 | void OnTest1IntegerParam(int n, sigcxx::SLOT slot = nullptr); 29 | 30 | void OnTest2IntegerParams(int n1, int n2, sigcxx::SLOT slot = nullptr); 31 | 32 | inline sigcxx::SignalRef<> signal0() 33 | { 34 | return signal_0_; 35 | } 36 | 37 | inline sigcxx::SignalRef signal1() 38 | { 39 | return signal_1_int_; 40 | } 41 | 42 | inline sigcxx::SignalRef signal2() 43 | { 44 | return signal_2_int_; 45 | } 46 | 47 | inline size_t test1_count () const 48 | { 49 | return test1_count_; 50 | } 51 | 52 | inline size_t test2_count () const 53 | { 54 | return test2_count_; 55 | } 56 | 57 | private: 58 | 59 | sigcxx::Signal<> signal_0_; 60 | sigcxx::Signal signal_1_int_; 61 | sigcxx::Signal signal_2_int_; 62 | size_t test1_count_; 63 | size_t test2_count_; 64 | 65 | }; 66 | -------------------------------------------------------------------------------- /test/gtest/CHANGES: -------------------------------------------------------------------------------- 1 | Changes for 1.7.0: 2 | 3 | * New feature: death tests are supported on OpenBSD and in iOS 4 | simulator now. 5 | * New feature: Google Test now implements a protocol to allow 6 | a test runner to detect that a test program has exited 7 | prematurely and report it as a failure (before it would be 8 | falsely reported as a success if the exit code is 0). 9 | * New feature: Test::RecordProperty() can now be used outside of the 10 | lifespan of a test method, in which case it will be attributed to 11 | the current test case or the test program in the XML report. 12 | * New feature (potentially breaking): --gtest_list_tests now prints 13 | the type parameters and value parameters for each test. 14 | * Improvement: char pointers and char arrays are now escaped properly 15 | in failure messages. 16 | * Improvement: failure summary in XML reports now includes file and 17 | line information. 18 | * Improvement: the XML element now has a timestamp attribute. 19 | * Improvement: When --gtest_filter is specified, XML report now doesn't 20 | contain information about tests that are filtered out. 21 | * Fixed the bug where long --gtest_filter flag values are truncated in 22 | death tests. 23 | * Potentially breaking change: RUN_ALL_TESTS() is now implemented as a 24 | function instead of a macro in order to work better with Clang. 25 | * Compatibility fixes with C++ 11 and various platforms. 26 | * Bug/warning fixes. 27 | 28 | Changes for 1.6.0: 29 | 30 | * New feature: ADD_FAILURE_AT() for reporting a test failure at the 31 | given source location -- useful for writing testing utilities. 32 | * New feature: the universal value printer is moved from Google Mock 33 | to Google Test. 34 | * New feature: type parameters and value parameters are reported in 35 | the XML report now. 36 | * A gtest_disable_pthreads CMake option. 37 | * Colored output works in GNU Screen sessions now. 38 | * Parameters of value-parameterized tests are now printed in the 39 | textual output. 40 | * Failures from ad hoc test assertions run before RUN_ALL_TESTS() are 41 | now correctly reported. 42 | * Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to 43 | ostream. 44 | * More complete handling of exceptions. 45 | * GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter 46 | name is already used by another library. 47 | * --gtest_catch_exceptions is now true by default, allowing a test 48 | program to continue after an exception is thrown. 49 | * Value-parameterized test fixtures can now derive from Test and 50 | WithParamInterface separately, easing conversion of legacy tests. 51 | * Death test messages are clearly marked to make them more 52 | distinguishable from other messages. 53 | * Compatibility fixes for Android, Google Native Client, MinGW, HP UX, 54 | PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear), 55 | IBM XL C++ (Visual Age C++), and C++0x. 56 | * Bug fixes and implementation clean-ups. 57 | * Potentially incompatible changes: disables the harmful 'make install' 58 | command in autotools. 59 | 60 | Changes for 1.5.0: 61 | 62 | * New feature: assertions can be safely called in multiple threads 63 | where the pthreads library is available. 64 | * New feature: predicates used inside EXPECT_TRUE() and friends 65 | can now generate custom failure messages. 66 | * New feature: Google Test can now be compiled as a DLL. 67 | * New feature: fused source files are included. 68 | * New feature: prints help when encountering unrecognized Google Test flags. 69 | * Experimental feature: CMake build script (requires CMake 2.6.4+). 70 | * Experimental feature: the Pump script for meta programming. 71 | * double values streamed to an assertion are printed with enough precision 72 | to differentiate any two different values. 73 | * Google Test now works on Solaris and AIX. 74 | * Build and test script improvements. 75 | * Bug fixes and implementation clean-ups. 76 | 77 | Potentially breaking changes: 78 | 79 | * Stopped supporting VC++ 7.1 with exceptions disabled. 80 | * Dropped support for 'make install'. 81 | 82 | Changes for 1.4.0: 83 | 84 | * New feature: the event listener API 85 | * New feature: test shuffling 86 | * New feature: the XML report format is closer to junitreport and can 87 | be parsed by Hudson now. 88 | * New feature: when a test runs under Visual Studio, its failures are 89 | integrated in the IDE. 90 | * New feature: /MD(d) versions of VC++ projects. 91 | * New feature: elapsed time for the tests is printed by default. 92 | * New feature: comes with a TR1 tuple implementation such that Boost 93 | is no longer needed for Combine(). 94 | * New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends. 95 | * New feature: the Xcode project can now produce static gtest 96 | libraries in addition to a framework. 97 | * Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile, 98 | Symbian, gcc, and C++Builder. 99 | * Bug fixes and implementation clean-ups. 100 | 101 | Changes for 1.3.0: 102 | 103 | * New feature: death tests on Windows, Cygwin, and Mac. 104 | * New feature: ability to use Google Test assertions in other testing 105 | frameworks. 106 | * New feature: ability to run disabled test via 107 | --gtest_also_run_disabled_tests. 108 | * New feature: the --help flag for printing the usage. 109 | * New feature: access to Google Test flag values in user code. 110 | * New feature: a script that packs Google Test into one .h and one 111 | .cc file for easy deployment. 112 | * New feature: support for distributing test functions to multiple 113 | machines (requires support from the test runner). 114 | * Bug fixes and implementation clean-ups. 115 | 116 | Changes for 1.2.1: 117 | 118 | * Compatibility fixes for Linux IA-64 and IBM z/OS. 119 | * Added support for using Boost and other TR1 implementations. 120 | * Changes to the build scripts to support upcoming release of Google C++ 121 | Mocking Framework. 122 | * Added Makefile to the distribution package. 123 | * Improved build instructions in README. 124 | 125 | Changes for 1.2.0: 126 | 127 | * New feature: value-parameterized tests. 128 | * New feature: the ASSERT/EXPECT_(NON)FATAL_FAILURE(_ON_ALL_THREADS) 129 | macros. 130 | * Changed the XML report format to match JUnit/Ant's. 131 | * Added tests to the Xcode project. 132 | * Added scons/SConscript for building with SCons. 133 | * Added src/gtest-all.cc for building Google Test from a single file. 134 | * Fixed compatibility with Solaris and z/OS. 135 | * Enabled running Python tests on systems with python 2.3 installed, 136 | e.g. Mac OS X 10.4. 137 | * Bug fixes. 138 | 139 | Changes for 1.1.0: 140 | 141 | * New feature: type-parameterized tests. 142 | * New feature: exception assertions. 143 | * New feature: printing elapsed time of tests. 144 | * Improved the robustness of death tests. 145 | * Added an Xcode project and samples. 146 | * Adjusted the output format on Windows to be understandable by Visual Studio. 147 | * Minor bug fixes. 148 | 149 | Changes for 1.0.1: 150 | 151 | * Added project files for Visual Studio 7.1. 152 | * Fixed issues with compiling on Mac OS X. 153 | * Fixed issues with compiling on Cygwin. 154 | 155 | Changes for 1.0.0: 156 | 157 | * Initial Open Source release of Google Test 158 | -------------------------------------------------------------------------------- /test/gtest/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This file contains a list of people who've made non-trivial 2 | # contribution to the Google C++ Testing Framework project. People 3 | # who commit code to the project are encouraged to add their names 4 | # here. Please keep the list sorted by first names. 5 | 6 | Ajay Joshi 7 | Balázs Dán 8 | Bharat Mediratta 9 | Chandler Carruth 10 | Chris Prince 11 | Chris Taylor 12 | Dan Egnor 13 | Eric Roman 14 | Hady Zalek 15 | Jeffrey Yasskin 16 | Jói Sigurðsson 17 | Keir Mierle 18 | Keith Ray 19 | Kenton Varda 20 | Manuel Klimek 21 | Markus Heule 22 | Mika Raento 23 | Miklós Fazekas 24 | Pasi Valminen 25 | Patrick Hanna 26 | Patrick Riley 27 | Peter Kaminski 28 | Preston Jackson 29 | Rainer Klaffenboeck 30 | Russ Cox 31 | Russ Rufer 32 | Sean Mcafee 33 | Sigurður Ásgeirsson 34 | Tracy Bialik 35 | Vadim Berman 36 | Vlad Losev 37 | Zhanyong Wan 38 | -------------------------------------------------------------------------------- /test/gtest/LICENSE: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /test/gtest/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 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // The Google C++ Testing Framework (Google Test) 33 | // 34 | // This header file defines the Message class. 35 | // 36 | // IMPORTANT NOTE: Due to limitation of the C++ language, we have to 37 | // leave some internal implementation details in this header file. 38 | // They are clearly marked by comments like this: 39 | // 40 | // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 41 | // 42 | // Such code is NOT meant to be used by a user directly, and is subject 43 | // to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user 44 | // program! 45 | 46 | #ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 47 | #define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 48 | 49 | #include 50 | 51 | #include "gtest/internal/gtest-port.h" 52 | 53 | // Ensures that there is at least one operator<< in the global namespace. 54 | // See Message& operator<<(...) below for why. 55 | void operator<<(const testing::internal::Secret&, int); 56 | 57 | namespace testing { 58 | 59 | // The Message class works like an ostream repeater. 60 | // 61 | // Typical usage: 62 | // 63 | // 1. You stream a bunch of values to a Message object. 64 | // It will remember the text in a stringstream. 65 | // 2. Then you stream the Message object to an ostream. 66 | // This causes the text in the Message to be streamed 67 | // to the ostream. 68 | // 69 | // For example; 70 | // 71 | // testing::Message foo; 72 | // foo << 1 << " != " << 2; 73 | // std::cout << foo; 74 | // 75 | // will print "1 != 2". 76 | // 77 | // Message is not intended to be inherited from. In particular, its 78 | // destructor is not virtual. 79 | // 80 | // Note that stringstream behaves differently in gcc and in MSVC. You 81 | // can stream a NULL char pointer to it in the former, but not in the 82 | // latter (it causes an access violation if you do). The Message 83 | // class hides this difference by treating a NULL char pointer as 84 | // "(null)". 85 | class GTEST_API_ Message { 86 | private: 87 | // The type of basic IO manipulators (endl, ends, and flush) for 88 | // narrow streams. 89 | typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); 90 | 91 | public: 92 | // Constructs an empty Message. 93 | Message(); 94 | 95 | // Copy constructor. 96 | Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT 97 | *ss_ << msg.GetString(); 98 | } 99 | 100 | // Constructs a Message from a C-string. 101 | explicit Message(const char* str) : ss_(new ::std::stringstream) { 102 | *ss_ << str; 103 | } 104 | 105 | #if GTEST_OS_SYMBIAN 106 | // Streams a value (either a pointer or not) to this object. 107 | template 108 | inline Message& operator <<(const T& value) { 109 | StreamHelper(typename internal::is_pointer::type(), value); 110 | return *this; 111 | } 112 | #else 113 | // Streams a non-pointer value to this object. 114 | template 115 | inline Message& operator <<(const T& val) { 116 | // Some libraries overload << for STL containers. These 117 | // overloads are defined in the global namespace instead of ::std. 118 | // 119 | // C++'s symbol lookup rule (i.e. Koenig lookup) says that these 120 | // overloads are visible in either the std namespace or the global 121 | // namespace, but not other namespaces, including the testing 122 | // namespace which Google Test's Message class is in. 123 | // 124 | // To allow STL containers (and other types that has a << operator 125 | // defined in the global namespace) to be used in Google Test 126 | // assertions, testing::Message must access the custom << operator 127 | // from the global namespace. With this using declaration, 128 | // overloads of << defined in the global namespace and those 129 | // visible via Koenig lookup are both exposed in this function. 130 | using ::operator <<; 131 | *ss_ << val; 132 | return *this; 133 | } 134 | 135 | // Streams a pointer value to this object. 136 | // 137 | // This function is an overload of the previous one. When you 138 | // stream a pointer to a Message, this definition will be used as it 139 | // is more specialized. (The C++ Standard, section 140 | // [temp.func.order].) If you stream a non-pointer, then the 141 | // previous definition will be used. 142 | // 143 | // The reason for this overload is that streaming a NULL pointer to 144 | // ostream is undefined behavior. Depending on the compiler, you 145 | // may get "0", "(nil)", "(null)", or an access violation. To 146 | // ensure consistent result across compilers, we always treat NULL 147 | // as "(null)". 148 | template 149 | inline Message& operator <<(T* const& pointer) { // NOLINT 150 | if (pointer == NULL) { 151 | *ss_ << "(null)"; 152 | } else { 153 | *ss_ << pointer; 154 | } 155 | return *this; 156 | } 157 | #endif // GTEST_OS_SYMBIAN 158 | 159 | // Since the basic IO manipulators are overloaded for both narrow 160 | // and wide streams, we have to provide this specialized definition 161 | // of operator <<, even though its body is the same as the 162 | // templatized version above. Without this definition, streaming 163 | // endl or other basic IO manipulators to Message will confuse the 164 | // compiler. 165 | Message& operator <<(BasicNarrowIoManip val) { 166 | *ss_ << val; 167 | return *this; 168 | } 169 | 170 | // Instead of 1/0, we want to see true/false for bool values. 171 | Message& operator <<(bool b) { 172 | return *this << (b ? "true" : "false"); 173 | } 174 | 175 | // These two overloads allow streaming a wide C string to a Message 176 | // using the UTF-8 encoding. 177 | Message& operator <<(const wchar_t* wide_c_str); 178 | Message& operator <<(wchar_t* wide_c_str); 179 | 180 | #if GTEST_HAS_STD_WSTRING 181 | // Converts the given wide string to a narrow string using the UTF-8 182 | // encoding, and streams the result to this Message object. 183 | Message& operator <<(const ::std::wstring& wstr); 184 | #endif // GTEST_HAS_STD_WSTRING 185 | 186 | #if GTEST_HAS_GLOBAL_WSTRING 187 | // Converts the given wide string to a narrow string using the UTF-8 188 | // encoding, and streams the result to this Message object. 189 | Message& operator <<(const ::wstring& wstr); 190 | #endif // GTEST_HAS_GLOBAL_WSTRING 191 | 192 | // Gets the text streamed to this object so far as an std::string. 193 | // Each '\0' character in the buffer is replaced with "\\0". 194 | // 195 | // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 196 | std::string GetString() const; 197 | 198 | private: 199 | 200 | #if GTEST_OS_SYMBIAN 201 | // These are needed as the Nokia Symbian Compiler cannot decide between 202 | // const T& and const T* in a function template. The Nokia compiler _can_ 203 | // decide between class template specializations for T and T*, so a 204 | // tr1::type_traits-like is_pointer works, and we can overload on that. 205 | template 206 | inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { 207 | if (pointer == NULL) { 208 | *ss_ << "(null)"; 209 | } else { 210 | *ss_ << pointer; 211 | } 212 | } 213 | template 214 | inline void StreamHelper(internal::false_type /*is_pointer*/, 215 | const T& value) { 216 | // See the comments in Message& operator <<(const T&) above for why 217 | // we need this using statement. 218 | using ::operator <<; 219 | *ss_ << value; 220 | } 221 | #endif // GTEST_OS_SYMBIAN 222 | 223 | // We'll hold the text streamed to this object here. 224 | const internal::scoped_ptr< ::std::stringstream> ss_; 225 | 226 | // We declare (but don't implement) this to prevent the compiler 227 | // from implementing the assignment operator. 228 | void operator=(const Message&); 229 | }; 230 | 231 | // Streams a Message to an ostream. 232 | inline std::ostream& operator <<(std::ostream& os, const Message& sb) { 233 | return os << sb.GetString(); 234 | } 235 | 236 | namespace internal { 237 | 238 | // Converts a streamable value to an std::string. A NULL pointer is 239 | // converted to "(null)". When the input value is a ::string, 240 | // ::std::string, ::wstring, or ::std::wstring object, each NUL 241 | // character in it is replaced with "\\0". 242 | template 243 | std::string StreamableToString(const T& streamable) { 244 | return (Message() << streamable).GetString(); 245 | } 246 | 247 | } // namespace internal 248 | } // namespace testing 249 | 250 | #endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 251 | -------------------------------------------------------------------------------- /test/gtest/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 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // Utilities for testing Google Test itself and code that uses Google Test 33 | // (e.g. frameworks built on top of Google Test). 34 | 35 | #ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ 36 | #define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ 37 | 38 | #include "gtest/gtest.h" 39 | 40 | namespace testing { 41 | 42 | // This helper class can be used to mock out Google Test failure reporting 43 | // so that we can test Google Test or code that builds on Google Test. 44 | // 45 | // An object of this class appends a TestPartResult object to the 46 | // TestPartResultArray object given in the constructor whenever a Google Test 47 | // failure is reported. It can either intercept only failures that are 48 | // generated in the same thread that created this object or it can intercept 49 | // all generated failures. The scope of this mock object can be controlled with 50 | // the second argument to the two arguments constructor. 51 | class GTEST_API_ ScopedFakeTestPartResultReporter 52 | : public TestPartResultReporterInterface { 53 | public: 54 | // The two possible mocking modes of this object. 55 | enum InterceptMode { 56 | INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. 57 | INTERCEPT_ALL_THREADS // Intercepts all failures. 58 | }; 59 | 60 | // The c'tor sets this object as the test part result reporter used 61 | // by Google Test. The 'result' parameter specifies where to report the 62 | // results. This reporter will only catch failures generated in the current 63 | // thread. DEPRECATED 64 | explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); 65 | 66 | // Same as above, but you can choose the interception scope of this object. 67 | ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, 68 | TestPartResultArray* result); 69 | 70 | // The d'tor restores the previous test part result reporter. 71 | virtual ~ScopedFakeTestPartResultReporter(); 72 | 73 | // Appends the TestPartResult object to the TestPartResultArray 74 | // received in the constructor. 75 | // 76 | // This method is from the TestPartResultReporterInterface 77 | // interface. 78 | virtual void ReportTestPartResult(const TestPartResult& result); 79 | private: 80 | void Init(); 81 | 82 | const InterceptMode intercept_mode_; 83 | TestPartResultReporterInterface* old_reporter_; 84 | TestPartResultArray* const result_; 85 | 86 | GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); 87 | }; 88 | 89 | namespace internal { 90 | 91 | // A helper class for implementing EXPECT_FATAL_FAILURE() and 92 | // EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given 93 | // TestPartResultArray contains exactly one failure that has the given 94 | // type and contains the given substring. If that's not the case, a 95 | // non-fatal failure will be generated. 96 | class GTEST_API_ SingleFailureChecker { 97 | public: 98 | // The constructor remembers the arguments. 99 | SingleFailureChecker(const TestPartResultArray* results, 100 | TestPartResult::Type type, 101 | const string& substr); 102 | ~SingleFailureChecker(); 103 | private: 104 | const TestPartResultArray* const results_; 105 | const TestPartResult::Type type_; 106 | const string substr_; 107 | 108 | GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); 109 | }; 110 | 111 | } // namespace internal 112 | 113 | } // namespace testing 114 | 115 | // A set of macros for testing Google Test assertions or code that's expected 116 | // to generate Google Test fatal failures. It verifies that the given 117 | // statement will cause exactly one fatal Google Test failure with 'substr' 118 | // being part of the failure message. 119 | // 120 | // There are two different versions of this macro. EXPECT_FATAL_FAILURE only 121 | // affects and considers failures generated in the current thread and 122 | // EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. 123 | // 124 | // The verification of the assertion is done correctly even when the statement 125 | // throws an exception or aborts the current function. 126 | // 127 | // Known restrictions: 128 | // - 'statement' cannot reference local non-static variables or 129 | // non-static members of the current object. 130 | // - 'statement' cannot return a value. 131 | // - You cannot stream a failure message to this macro. 132 | // 133 | // Note that even though the implementations of the following two 134 | // macros are much alike, we cannot refactor them to use a common 135 | // helper macro, due to some peculiarity in how the preprocessor 136 | // works. The AcceptsMacroThatExpandsToUnprotectedComma test in 137 | // gtest_unittest.cc will fail to compile if we do that. 138 | #define EXPECT_FATAL_FAILURE(statement, substr) \ 139 | do { \ 140 | class GTestExpectFatalFailureHelper {\ 141 | public:\ 142 | static void Execute() { statement; }\ 143 | };\ 144 | ::testing::TestPartResultArray gtest_failures;\ 145 | ::testing::internal::SingleFailureChecker gtest_checker(\ 146 | >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ 147 | {\ 148 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 149 | ::testing::ScopedFakeTestPartResultReporter:: \ 150 | INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ 151 | GTestExpectFatalFailureHelper::Execute();\ 152 | }\ 153 | } while (::testing::internal::AlwaysFalse()) 154 | 155 | #define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ 156 | do { \ 157 | class GTestExpectFatalFailureHelper {\ 158 | public:\ 159 | static void Execute() { statement; }\ 160 | };\ 161 | ::testing::TestPartResultArray gtest_failures;\ 162 | ::testing::internal::SingleFailureChecker gtest_checker(\ 163 | >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ 164 | {\ 165 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 166 | ::testing::ScopedFakeTestPartResultReporter:: \ 167 | INTERCEPT_ALL_THREADS, >est_failures);\ 168 | GTestExpectFatalFailureHelper::Execute();\ 169 | }\ 170 | } while (::testing::internal::AlwaysFalse()) 171 | 172 | // A macro for testing Google Test assertions or code that's expected to 173 | // generate Google Test non-fatal failures. It asserts that the given 174 | // statement will cause exactly one non-fatal Google Test failure with 'substr' 175 | // being part of the failure message. 176 | // 177 | // There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only 178 | // affects and considers failures generated in the current thread and 179 | // EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. 180 | // 181 | // 'statement' is allowed to reference local variables and members of 182 | // the current object. 183 | // 184 | // The verification of the assertion is done correctly even when the statement 185 | // throws an exception or aborts the current function. 186 | // 187 | // Known restrictions: 188 | // - You cannot stream a failure message to this macro. 189 | // 190 | // Note that even though the implementations of the following two 191 | // macros are much alike, we cannot refactor them to use a common 192 | // helper macro, due to some peculiarity in how the preprocessor 193 | // works. If we do that, the code won't compile when the user gives 194 | // EXPECT_NONFATAL_FAILURE() a statement that contains a macro that 195 | // expands to code containing an unprotected comma. The 196 | // AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc 197 | // catches that. 198 | // 199 | // For the same reason, we have to write 200 | // if (::testing::internal::AlwaysTrue()) { statement; } 201 | // instead of 202 | // GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) 203 | // to avoid an MSVC warning on unreachable code. 204 | #define EXPECT_NONFATAL_FAILURE(statement, substr) \ 205 | do {\ 206 | ::testing::TestPartResultArray gtest_failures;\ 207 | ::testing::internal::SingleFailureChecker gtest_checker(\ 208 | >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ 209 | (substr));\ 210 | {\ 211 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 212 | ::testing::ScopedFakeTestPartResultReporter:: \ 213 | INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ 214 | if (::testing::internal::AlwaysTrue()) { statement; }\ 215 | }\ 216 | } while (::testing::internal::AlwaysFalse()) 217 | 218 | #define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ 219 | do {\ 220 | ::testing::TestPartResultArray gtest_failures;\ 221 | ::testing::internal::SingleFailureChecker gtest_checker(\ 222 | >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ 223 | (substr));\ 224 | {\ 225 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 226 | ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ 227 | >est_failures);\ 228 | if (::testing::internal::AlwaysTrue()) { statement; }\ 229 | }\ 230 | } while (::testing::internal::AlwaysFalse()) 231 | 232 | #endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ 233 | -------------------------------------------------------------------------------- /test/gtest/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 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | 33 | #ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 34 | #define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 35 | 36 | #include 37 | #include 38 | #include "gtest/internal/gtest-internal.h" 39 | #include "gtest/internal/gtest-string.h" 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 | }; 56 | 57 | // C'tor. TestPartResult does NOT have a default constructor. 58 | // Always use this constructor (with parameters) to create a 59 | // TestPartResult object. 60 | TestPartResult(Type a_type, 61 | const char* a_file_name, 62 | int a_line_number, 63 | const char* a_message) 64 | : type_(a_type), 65 | file_name_(a_file_name == NULL ? "" : a_file_name), 66 | line_number_(a_line_number), 67 | summary_(ExtractSummary(a_message)), 68 | message_(a_message) { 69 | } 70 | 71 | // Gets the outcome of the test part. 72 | Type type() const { return type_; } 73 | 74 | // Gets the name of the source file where the test part took place, or 75 | // NULL if it's unknown. 76 | const char* file_name() const { 77 | return file_name_.empty() ? NULL : file_name_.c_str(); 78 | } 79 | 80 | // Gets the line in the source file where the test part took place, 81 | // or -1 if it's unknown. 82 | int line_number() const { return line_number_; } 83 | 84 | // Gets the summary of the failure message. 85 | const char* summary() const { return summary_.c_str(); } 86 | 87 | // Gets the message associated with the test part. 88 | const char* message() const { return message_.c_str(); } 89 | 90 | // Returns true iff the test part passed. 91 | bool passed() const { return type_ == kSuccess; } 92 | 93 | // Returns true iff the test part failed. 94 | bool failed() const { return type_ != kSuccess; } 95 | 96 | // Returns true iff the test part non-fatally failed. 97 | bool nonfatally_failed() const { return type_ == kNonFatalFailure; } 98 | 99 | // Returns true iff the test part fatally failed. 100 | bool fatally_failed() const { return type_ == kFatalFailure; } 101 | 102 | private: 103 | Type type_; 104 | 105 | // Gets the summary of the failure message by omitting the stack 106 | // trace in it. 107 | static std::string ExtractSummary(const char* message); 108 | 109 | // The name of the source file where the test part took place, or 110 | // "" if the source file is unknown. 111 | std::string file_name_; 112 | // The line in the source file where the test part took place, or -1 113 | // if the line number is unknown. 114 | int line_number_; 115 | std::string summary_; // The test failure summary. 116 | std::string message_; // The test failure message. 117 | }; 118 | 119 | // Prints a TestPartResult object. 120 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result); 121 | 122 | // An array of TestPartResult objects. 123 | // 124 | // Don't inherit from TestPartResultArray as its destructor is not 125 | // virtual. 126 | class GTEST_API_ TestPartResultArray { 127 | public: 128 | TestPartResultArray() {} 129 | 130 | // Appends the given TestPartResult to the array. 131 | void Append(const TestPartResult& result); 132 | 133 | // Returns the TestPartResult at the given index (0-based). 134 | const TestPartResult& GetTestPartResult(int index) const; 135 | 136 | // Returns the number of TestPartResult objects in the array. 137 | int size() const; 138 | 139 | private: 140 | std::vector array_; 141 | 142 | GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); 143 | }; 144 | 145 | // This interface knows how to report a test part result. 146 | class TestPartResultReporterInterface { 147 | public: 148 | virtual ~TestPartResultReporterInterface() {} 149 | 150 | virtual void ReportTestPartResult(const TestPartResult& result) = 0; 151 | }; 152 | 153 | namespace internal { 154 | 155 | // This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a 156 | // statement generates new fatal failures. To do so it registers itself as the 157 | // current test part result reporter. Besides checking if fatal failures were 158 | // reported, it only delegates the reporting to the former result reporter. 159 | // The original result reporter is restored in the destructor. 160 | // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 161 | class GTEST_API_ HasNewFatalFailureHelper 162 | : public TestPartResultReporterInterface { 163 | public: 164 | HasNewFatalFailureHelper(); 165 | virtual ~HasNewFatalFailureHelper(); 166 | virtual void ReportTestPartResult(const TestPartResult& result); 167 | bool has_new_fatal_failure() const { return has_new_fatal_failure_; } 168 | private: 169 | bool has_new_fatal_failure_; 170 | TestPartResultReporterInterface* original_reporter_; 171 | 172 | GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); 173 | }; 174 | 175 | } // namespace internal 176 | 177 | } // namespace testing 178 | 179 | #endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 180 | -------------------------------------------------------------------------------- /test/gtest/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 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // Google C++ Testing Framework definitions useful in production code. 33 | 34 | #ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 35 | #define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 36 | 37 | // When you need to test the private or protected members of a class, 38 | // use the FRIEND_TEST macro to declare your tests as friends of the 39 | // class. For example: 40 | // 41 | // class MyClass { 42 | // private: 43 | // void MyMethod(); 44 | // FRIEND_TEST(MyClassTest, MyMethod); 45 | // }; 46 | // 47 | // class MyClassTest : public testing::Test { 48 | // // ... 49 | // }; 50 | // 51 | // TEST_F(MyClassTest, MyMethod) { 52 | // // Can call MyClass::MyMethod() here. 53 | // } 54 | 55 | #define FRIEND_TEST(test_case_name, test_name)\ 56 | friend class test_case_name##_##test_name##_Test 57 | 58 | #endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 59 | -------------------------------------------------------------------------------- /test/gtest/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. 31 | // The following macros can be defined: 32 | // 33 | // Flag related macros: 34 | // GTEST_FLAG(flag_name) 35 | // GTEST_USE_OWN_FLAGFILE_FLAG_ - Define to 0 when the system provides its 36 | // own flagfile flag parsing. 37 | // GTEST_DECLARE_bool_(name) 38 | // GTEST_DECLARE_int32_(name) 39 | // GTEST_DECLARE_string_(name) 40 | // GTEST_DEFINE_bool_(name, default_val, doc) 41 | // GTEST_DEFINE_int32_(name, default_val, doc) 42 | // GTEST_DEFINE_string_(name, default_val, doc) 43 | // 44 | // Test filtering: 45 | // GTEST_TEST_FILTER_ENV_VAR_ - The name of an environment variable that 46 | // will be used if --GTEST_FLAG(test_filter) 47 | // is not provided. 48 | // 49 | // Logging: 50 | // GTEST_LOG_(severity) 51 | // GTEST_CHECK_(condition) 52 | // Functions LogToStderr() and FlushInfoLog() have to be provided too. 53 | // 54 | // Threading: 55 | // GTEST_HAS_NOTIFICATION_ - Enabled if Notification is already provided. 56 | // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ - Enabled if Mutex and ThreadLocal are 57 | // already provided. 58 | // Must also provide GTEST_DECLARE_STATIC_MUTEX_(mutex) and 59 | // GTEST_DEFINE_STATIC_MUTEX_(mutex) 60 | // 61 | // GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) 62 | // GTEST_LOCK_EXCLUDED_(locks) 63 | // 64 | // ** Custom implementation starts here ** 65 | 66 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 67 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 68 | 69 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 70 | -------------------------------------------------------------------------------- /test/gtest/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 | // See documentation at gtest/gtest-printers.h for details on how to define a 35 | // custom printer. 36 | // 37 | // ** Custom implementation starts here ** 38 | 39 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 40 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 41 | 42 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 43 | -------------------------------------------------------------------------------- /test/gtest/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. 31 | // The following macros can be defined: 32 | // 33 | // GTEST_OS_STACK_TRACE_GETTER_ - The name of an implementation of 34 | // OsStackTraceGetterInterface. 35 | // 36 | // ** Custom implementation starts here ** 37 | 38 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 39 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 40 | 41 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 42 | -------------------------------------------------------------------------------- /test/gtest/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 | // Author: keith.ray@gmail.com (Keith Ray) 31 | // 32 | // Google Test filepath utilities 33 | // 34 | // This header file declares classes and functions used internally by 35 | // Google Test. They are subject to change without notice. 36 | // 37 | // This file is #included in . 38 | // Do not include this header file separately! 39 | 40 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 41 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 42 | 43 | #include "gtest/internal/gtest-string.h" 44 | 45 | namespace testing { 46 | namespace internal { 47 | 48 | // FilePath - a class for file and directory pathname manipulation which 49 | // handles platform-specific conventions (like the pathname separator). 50 | // Used for helper functions for naming files in a directory for xml output. 51 | // Except for Set methods, all methods are const or static, which provides an 52 | // "immutable value object" -- useful for peace of mind. 53 | // A FilePath with a value ending in a path separator ("like/this/") represents 54 | // a directory, otherwise it is assumed to represent a file. In either case, 55 | // it may or may not represent an actual file or directory in the file system. 56 | // Names are NOT checked for syntax correctness -- no checking for illegal 57 | // characters, malformed paths, etc. 58 | 59 | class GTEST_API_ FilePath { 60 | public: 61 | FilePath() : pathname_("") { } 62 | FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } 63 | 64 | explicit FilePath(const std::string& pathname) : pathname_(pathname) { 65 | Normalize(); 66 | } 67 | 68 | FilePath& operator=(const FilePath& rhs) { 69 | Set(rhs); 70 | return *this; 71 | } 72 | 73 | void Set(const FilePath& rhs) { 74 | pathname_ = rhs.pathname_; 75 | } 76 | 77 | const std::string& string() const { return pathname_; } 78 | const char* c_str() const { return pathname_.c_str(); } 79 | 80 | // Returns the current working directory, or "" if unsuccessful. 81 | static FilePath GetCurrentDir(); 82 | 83 | // Given directory = "dir", base_name = "test", number = 0, 84 | // extension = "xml", returns "dir/test.xml". If number is greater 85 | // than zero (e.g., 12), returns "dir/test_12.xml". 86 | // On Windows platform, uses \ as the separator rather than /. 87 | static FilePath MakeFileName(const FilePath& directory, 88 | const FilePath& base_name, 89 | int number, 90 | const char* extension); 91 | 92 | // Given directory = "dir", relative_path = "test.xml", 93 | // returns "dir/test.xml". 94 | // On Windows, uses \ as the separator rather than /. 95 | static FilePath ConcatPaths(const FilePath& directory, 96 | const FilePath& relative_path); 97 | 98 | // Returns a pathname for a file that does not currently exist. The pathname 99 | // will be directory/base_name.extension or 100 | // directory/base_name_.extension if directory/base_name.extension 101 | // already exists. The number will be incremented until a pathname is found 102 | // that does not already exist. 103 | // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. 104 | // There could be a race condition if two or more processes are calling this 105 | // function at the same time -- they could both pick the same filename. 106 | static FilePath GenerateUniqueFileName(const FilePath& directory, 107 | const FilePath& base_name, 108 | const char* extension); 109 | 110 | // Returns true iff the path is "". 111 | bool IsEmpty() const { return pathname_.empty(); } 112 | 113 | // If input name has a trailing separator character, removes it and returns 114 | // the name, otherwise return the name string unmodified. 115 | // On Windows platform, uses \ as the separator, other platforms use /. 116 | FilePath RemoveTrailingPathSeparator() const; 117 | 118 | // Returns a copy of the FilePath with the directory part removed. 119 | // Example: FilePath("path/to/file").RemoveDirectoryName() returns 120 | // FilePath("file"). If there is no directory part ("just_a_file"), it returns 121 | // the FilePath unmodified. If there is no file part ("just_a_dir/") it 122 | // returns an empty FilePath (""). 123 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 124 | FilePath RemoveDirectoryName() const; 125 | 126 | // RemoveFileName returns the directory path with the filename removed. 127 | // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". 128 | // If the FilePath is "a_file" or "/a_file", RemoveFileName returns 129 | // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does 130 | // not have a file, like "just/a/dir/", it returns the FilePath unmodified. 131 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 132 | FilePath RemoveFileName() const; 133 | 134 | // Returns a copy of the FilePath with the case-insensitive extension removed. 135 | // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns 136 | // FilePath("dir/file"). If a case-insensitive extension is not 137 | // found, returns a copy of the original FilePath. 138 | FilePath RemoveExtension(const char* extension) const; 139 | 140 | // Creates directories so that path exists. Returns true if successful or if 141 | // the directories already exist; returns false if unable to create 142 | // directories for any reason. Will also return false if the FilePath does 143 | // not represent a directory (that is, it doesn't end with a path separator). 144 | bool CreateDirectoriesRecursively() const; 145 | 146 | // Create the directory so that path exists. Returns true if successful or 147 | // if the directory already exists; returns false if unable to create the 148 | // directory for any reason, including if the parent directory does not 149 | // exist. Not named "CreateDirectory" because that's a macro on Windows. 150 | bool CreateFolder() const; 151 | 152 | // Returns true if FilePath describes something in the file-system, 153 | // either a file, directory, or whatever, and that something exists. 154 | bool FileOrDirectoryExists() const; 155 | 156 | // Returns true if pathname describes a directory in the file-system 157 | // that exists. 158 | bool DirectoryExists() const; 159 | 160 | // Returns true if FilePath ends with a path separator, which indicates that 161 | // it is intended to represent a directory. Returns false otherwise. 162 | // This does NOT check that a directory (or file) actually exists. 163 | bool IsDirectory() const; 164 | 165 | // Returns true if pathname describes a root directory. (Windows has one 166 | // root directory per disk drive.) 167 | bool IsRootDirectory() const; 168 | 169 | // Returns true if pathname describes an absolute path. 170 | bool IsAbsolutePath() const; 171 | 172 | private: 173 | // Replaces multiple consecutive separators with a single separator. 174 | // For example, "bar///foo" becomes "bar/foo". Does not eliminate other 175 | // redundancies that might be in a pathname involving "." or "..". 176 | // 177 | // A pathname with multiple consecutive separators may occur either through 178 | // user error or as a result of some scripts or APIs that generate a pathname 179 | // with a trailing separator. On other platforms the same API or script 180 | // may NOT generate a pathname with a trailing "/". Then elsewhere that 181 | // pathname may have another "/" and pathname components added to it, 182 | // without checking for the separator already being there. 183 | // The script language and operating system may allow paths like "foo//bar" 184 | // but some of the functions in FilePath will not handle that correctly. In 185 | // particular, RemoveTrailingPathSeparator() only removes one separator, and 186 | // it is called in CreateDirectoriesRecursively() assuming that it will change 187 | // a pathname from directory syntax (trailing separator) to filename syntax. 188 | // 189 | // On Windows this method also replaces the alternate path separator '/' with 190 | // the primary path separator '\\', so that for example "bar\\/\\foo" becomes 191 | // "bar\\foo". 192 | 193 | void Normalize(); 194 | 195 | // Returns a pointer to the last occurence of a valid path separator in 196 | // the FilePath. On Windows, for example, both '/' and '\' are valid path 197 | // separators. Returns NULL if no path separator was found. 198 | const char* FindLastPathSeparator() const; 199 | 200 | std::string pathname_; 201 | }; // class FilePath 202 | 203 | } // namespace internal 204 | } // namespace testing 205 | 206 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 207 | -------------------------------------------------------------------------------- /test/gtest/include/gtest/internal/gtest-linked_ptr.h: -------------------------------------------------------------------------------- 1 | // Copyright 2003 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 | // Authors: Dan Egnor (egnor@google.com) 31 | // 32 | // A "smart" pointer type with reference tracking. Every pointer to a 33 | // particular object is kept on a circular linked list. When the last pointer 34 | // to an object is destroyed or reassigned, the object is deleted. 35 | // 36 | // Used properly, this deletes the object when the last reference goes away. 37 | // There are several caveats: 38 | // - Like all reference counting schemes, cycles lead to leaks. 39 | // - Each smart pointer is actually two pointers (8 bytes instead of 4). 40 | // - Every time a pointer is assigned, the entire list of pointers to that 41 | // object is traversed. This class is therefore NOT SUITABLE when there 42 | // will often be more than two or three pointers to a particular object. 43 | // - References are only tracked as long as linked_ptr<> objects are copied. 44 | // If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS 45 | // will happen (double deletion). 46 | // 47 | // A good use of this class is storing object references in STL containers. 48 | // You can safely put linked_ptr<> in a vector<>. 49 | // Other uses may not be as good. 50 | // 51 | // Note: If you use an incomplete type with linked_ptr<>, the class 52 | // *containing* linked_ptr<> must have a constructor and destructor (even 53 | // if they do nothing!). 54 | // 55 | // Bill Gibbons suggested we use something like this. 56 | // 57 | // Thread Safety: 58 | // Unlike other linked_ptr implementations, in this implementation 59 | // a linked_ptr object is thread-safe in the sense that: 60 | // - it's safe to copy linked_ptr objects concurrently, 61 | // - it's safe to copy *from* a linked_ptr and read its underlying 62 | // raw pointer (e.g. via get()) concurrently, and 63 | // - it's safe to write to two linked_ptrs that point to the same 64 | // shared object concurrently. 65 | // TODO(wan@google.com): rename this to safe_linked_ptr to avoid 66 | // confusion with normal linked_ptr. 67 | 68 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 69 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 70 | 71 | #include 72 | #include 73 | 74 | #include "gtest/internal/gtest-port.h" 75 | 76 | namespace testing { 77 | namespace internal { 78 | 79 | // Protects copying of all linked_ptr objects. 80 | GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); 81 | 82 | // This is used internally by all instances of linked_ptr<>. It needs to be 83 | // a non-template class because different types of linked_ptr<> can refer to 84 | // the same object (linked_ptr(obj) vs linked_ptr(obj)). 85 | // So, it needs to be possible for different types of linked_ptr to participate 86 | // in the same circular linked list, so we need a single class type here. 87 | // 88 | // DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. 89 | class linked_ptr_internal { 90 | public: 91 | // Create a new circle that includes only this instance. 92 | void join_new() { 93 | next_ = this; 94 | } 95 | 96 | // Many linked_ptr operations may change p.link_ for some linked_ptr 97 | // variable p in the same circle as this object. Therefore we need 98 | // to prevent two such operations from occurring concurrently. 99 | // 100 | // Note that different types of linked_ptr objects can coexist in a 101 | // circle (e.g. linked_ptr, linked_ptr, and 102 | // linked_ptr). Therefore we must use a single mutex to 103 | // protect all linked_ptr objects. This can create serious 104 | // contention in production code, but is acceptable in a testing 105 | // framework. 106 | 107 | // Join an existing circle. 108 | void join(linked_ptr_internal const* ptr) 109 | GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { 110 | MutexLock lock(&g_linked_ptr_mutex); 111 | 112 | linked_ptr_internal const* p = ptr; 113 | while (p->next_ != ptr) { 114 | assert(p->next_ != this && 115 | "Trying to join() a linked ring we are already in. " 116 | "Is GMock thread safety enabled?"); 117 | p = p->next_; 118 | } 119 | p->next_ = this; 120 | next_ = ptr; 121 | } 122 | 123 | // Leave whatever circle we're part of. Returns true if we were the 124 | // last member of the circle. Once this is done, you can join() another. 125 | bool depart() 126 | GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { 127 | MutexLock lock(&g_linked_ptr_mutex); 128 | 129 | if (next_ == this) return true; 130 | linked_ptr_internal const* p = next_; 131 | while (p->next_ != this) { 132 | assert(p->next_ != next_ && 133 | "Trying to depart() a linked ring we are not in. " 134 | "Is GMock thread safety enabled?"); 135 | p = p->next_; 136 | } 137 | p->next_ = next_; 138 | return false; 139 | } 140 | 141 | private: 142 | mutable linked_ptr_internal const* next_; 143 | }; 144 | 145 | template 146 | class linked_ptr { 147 | public: 148 | typedef T element_type; 149 | 150 | // Take over ownership of a raw pointer. This should happen as soon as 151 | // possible after the object is created. 152 | explicit linked_ptr(T* ptr = NULL) { capture(ptr); } 153 | ~linked_ptr() { depart(); } 154 | 155 | // Copy an existing linked_ptr<>, adding ourselves to the list of references. 156 | template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } 157 | linked_ptr(linked_ptr const& ptr) { // NOLINT 158 | assert(&ptr != this); 159 | copy(&ptr); 160 | } 161 | 162 | // Assignment releases the old value and acquires the new. 163 | template linked_ptr& operator=(linked_ptr const& ptr) { 164 | depart(); 165 | copy(&ptr); 166 | return *this; 167 | } 168 | 169 | linked_ptr& operator=(linked_ptr const& ptr) { 170 | if (&ptr != this) { 171 | depart(); 172 | copy(&ptr); 173 | } 174 | return *this; 175 | } 176 | 177 | // Smart pointer members. 178 | void reset(T* ptr = NULL) { 179 | depart(); 180 | capture(ptr); 181 | } 182 | T* get() const { return value_; } 183 | T* operator->() const { return value_; } 184 | T& operator*() const { return *value_; } 185 | 186 | bool operator==(T* p) const { return value_ == p; } 187 | bool operator!=(T* p) const { return value_ != p; } 188 | template 189 | bool operator==(linked_ptr const& ptr) const { 190 | return value_ == ptr.get(); 191 | } 192 | template 193 | bool operator!=(linked_ptr const& ptr) const { 194 | return value_ != ptr.get(); 195 | } 196 | 197 | private: 198 | template 199 | friend class linked_ptr; 200 | 201 | T* value_; 202 | linked_ptr_internal link_; 203 | 204 | void depart() { 205 | if (link_.depart()) delete value_; 206 | } 207 | 208 | void capture(T* ptr) { 209 | value_ = ptr; 210 | link_.join_new(); 211 | } 212 | 213 | template void copy(linked_ptr const* ptr) { 214 | value_ = ptr->get(); 215 | if (value_) 216 | link_.join(&ptr->link_); 217 | else 218 | link_.join_new(); 219 | } 220 | }; 221 | 222 | template inline 223 | bool operator==(T* ptr, const linked_ptr& x) { 224 | return ptr == x.get(); 225 | } 226 | 227 | template inline 228 | bool operator!=(T* ptr, const linked_ptr& x) { 229 | return ptr != x.get(); 230 | } 231 | 232 | // A function to convert T* into linked_ptr 233 | // Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation 234 | // for linked_ptr >(new FooBarBaz(arg)) 235 | template 236 | linked_ptr make_linked_ptr(T* ptr) { 237 | return linked_ptr(ptr); 238 | } 239 | 240 | } // namespace internal 241 | } // namespace testing 242 | 243 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 244 | -------------------------------------------------------------------------------- /test/gtest/include/gtest/internal/gtest-param-util-generated.h.pump: -------------------------------------------------------------------------------- 1 | $$ -*- mode: c++; -*- 2 | $var n = 50 $$ Maximum length of Values arguments we want to support. 3 | $var maxtuple = 10 $$ Maximum number of Combine arguments we want to support. 4 | // Copyright 2008 Google Inc. 5 | // All Rights Reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are 9 | // met: 10 | // 11 | // * Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // * Redistributions in binary form must reproduce the above 14 | // copyright notice, this list of conditions and the following disclaimer 15 | // in the documentation and/or other materials provided with the 16 | // distribution. 17 | // * Neither the name of Google Inc. nor the names of its 18 | // contributors may be used to endorse or promote products derived from 19 | // this software without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | // Author: vladl@google.com (Vlad Losev) 34 | 35 | // Type and function utilities for implementing parameterized tests. 36 | // This file is generated by a SCRIPT. DO NOT EDIT BY HAND! 37 | // 38 | // Currently Google Test supports at most $n arguments in Values, 39 | // and at most $maxtuple arguments in Combine. Please contact 40 | // googletestframework@googlegroups.com if you need more. 41 | // Please note that the number of arguments to Combine is limited 42 | // by the maximum arity of the implementation of tuple which is 43 | // currently set at $maxtuple. 44 | 45 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 46 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 47 | 48 | // scripts/fuse_gtest.py depends on gtest's own header being #included 49 | // *unconditionally*. Therefore these #includes cannot be moved 50 | // inside #if GTEST_HAS_PARAM_TEST. 51 | #include "gtest/internal/gtest-param-util.h" 52 | #include "gtest/internal/gtest-port.h" 53 | 54 | #if GTEST_HAS_PARAM_TEST 55 | 56 | namespace testing { 57 | 58 | // Forward declarations of ValuesIn(), which is implemented in 59 | // include/gtest/gtest-param-test.h. 60 | template 61 | internal::ParamGenerator< 62 | typename ::testing::internal::IteratorTraits::value_type> 63 | ValuesIn(ForwardIterator begin, ForwardIterator end); 64 | 65 | template 66 | internal::ParamGenerator ValuesIn(const T (&array)[N]); 67 | 68 | template 69 | internal::ParamGenerator ValuesIn( 70 | const Container& container); 71 | 72 | namespace internal { 73 | 74 | // Used in the Values() function to provide polymorphic capabilities. 75 | $range i 1..n 76 | $for i [[ 77 | $range j 1..i 78 | 79 | template <$for j, [[typename T$j]]> 80 | class ValueArray$i { 81 | public: 82 | $if i==1 [[explicit ]]ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {} 83 | 84 | template 85 | operator ParamGenerator() const { 86 | const T array[] = {$for j, [[static_cast(v$(j)_)]]}; 87 | return ValuesIn(array); 88 | } 89 | 90 | private: 91 | // No implementation - assignment is unsupported. 92 | void operator=(const ValueArray$i& other); 93 | 94 | $for j [[ 95 | 96 | const T$j v$(j)_; 97 | ]] 98 | 99 | }; 100 | 101 | ]] 102 | 103 | # if GTEST_HAS_COMBINE 104 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 105 | // 106 | // Generates values from the Cartesian product of values produced 107 | // by the argument generators. 108 | // 109 | $range i 2..maxtuple 110 | $for i [[ 111 | $range j 1..i 112 | $range k 2..i 113 | 114 | template <$for j, [[typename T$j]]> 115 | class CartesianProductGenerator$i 116 | : public ParamGeneratorInterface< ::testing::tuple<$for j, [[T$j]]> > { 117 | public: 118 | typedef ::testing::tuple<$for j, [[T$j]]> ParamType; 119 | 120 | CartesianProductGenerator$i($for j, [[const ParamGenerator& g$j]]) 121 | : $for j, [[g$(j)_(g$j)]] {} 122 | virtual ~CartesianProductGenerator$i() {} 123 | 124 | virtual ParamIteratorInterface* Begin() const { 125 | return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]); 126 | } 127 | virtual ParamIteratorInterface* End() const { 128 | return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]); 129 | } 130 | 131 | private: 132 | class Iterator : public ParamIteratorInterface { 133 | public: 134 | Iterator(const ParamGeneratorInterface* base, $for j, [[ 135 | 136 | const ParamGenerator& g$j, 137 | const typename ParamGenerator::iterator& current$(j)]]) 138 | : base_(base), 139 | $for j, [[ 140 | 141 | begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j) 142 | ]] { 143 | ComputeCurrentValue(); 144 | } 145 | virtual ~Iterator() {} 146 | 147 | virtual const ParamGeneratorInterface* BaseGenerator() const { 148 | return base_; 149 | } 150 | // Advance should not be called on beyond-of-range iterators 151 | // so no component iterators must be beyond end of range, either. 152 | virtual void Advance() { 153 | assert(!AtEnd()); 154 | ++current$(i)_; 155 | 156 | $for k [[ 157 | if (current$(i+2-k)_ == end$(i+2-k)_) { 158 | current$(i+2-k)_ = begin$(i+2-k)_; 159 | ++current$(i+2-k-1)_; 160 | } 161 | 162 | ]] 163 | ComputeCurrentValue(); 164 | } 165 | virtual ParamIteratorInterface* Clone() const { 166 | return new Iterator(*this); 167 | } 168 | virtual const ParamType* Current() const { return ¤t_value_; } 169 | virtual bool Equals(const ParamIteratorInterface& other) const { 170 | // Having the same base generator guarantees that the other 171 | // iterator is of the same type and we can downcast. 172 | GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) 173 | << "The program attempted to compare iterators " 174 | << "from different generators." << std::endl; 175 | const Iterator* typed_other = 176 | CheckedDowncastToActualType(&other); 177 | // We must report iterators equal if they both point beyond their 178 | // respective ranges. That can happen in a variety of fashions, 179 | // so we have to consult AtEnd(). 180 | return (AtEnd() && typed_other->AtEnd()) || 181 | ($for j && [[ 182 | 183 | current$(j)_ == typed_other->current$(j)_ 184 | ]]); 185 | } 186 | 187 | private: 188 | Iterator(const Iterator& other) 189 | : base_(other.base_), $for j, [[ 190 | 191 | begin$(j)_(other.begin$(j)_), 192 | end$(j)_(other.end$(j)_), 193 | current$(j)_(other.current$(j)_) 194 | ]] { 195 | ComputeCurrentValue(); 196 | } 197 | 198 | void ComputeCurrentValue() { 199 | if (!AtEnd()) 200 | current_value_ = ParamType($for j, [[*current$(j)_]]); 201 | } 202 | bool AtEnd() const { 203 | // We must report iterator past the end of the range when either of the 204 | // component iterators has reached the end of its range. 205 | return 206 | $for j || [[ 207 | 208 | current$(j)_ == end$(j)_ 209 | ]]; 210 | } 211 | 212 | // No implementation - assignment is unsupported. 213 | void operator=(const Iterator& other); 214 | 215 | const ParamGeneratorInterface* const base_; 216 | // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. 217 | // current[i]_ is the actual traversing iterator. 218 | $for j [[ 219 | 220 | const typename ParamGenerator::iterator begin$(j)_; 221 | const typename ParamGenerator::iterator end$(j)_; 222 | typename ParamGenerator::iterator current$(j)_; 223 | ]] 224 | 225 | ParamType current_value_; 226 | }; // class CartesianProductGenerator$i::Iterator 227 | 228 | // No implementation - assignment is unsupported. 229 | void operator=(const CartesianProductGenerator$i& other); 230 | 231 | 232 | $for j [[ 233 | const ParamGenerator g$(j)_; 234 | 235 | ]] 236 | }; // class CartesianProductGenerator$i 237 | 238 | 239 | ]] 240 | 241 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 242 | // 243 | // Helper classes providing Combine() with polymorphic features. They allow 244 | // casting CartesianProductGeneratorN to ParamGenerator if T is 245 | // convertible to U. 246 | // 247 | $range i 2..maxtuple 248 | $for i [[ 249 | $range j 1..i 250 | 251 | template <$for j, [[class Generator$j]]> 252 | class CartesianProductHolder$i { 253 | public: 254 | CartesianProductHolder$i($for j, [[const Generator$j& g$j]]) 255 | : $for j, [[g$(j)_(g$j)]] {} 256 | template <$for j, [[typename T$j]]> 257 | operator ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >() const { 258 | return ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >( 259 | new CartesianProductGenerator$i<$for j, [[T$j]]>( 260 | $for j,[[ 261 | 262 | static_cast >(g$(j)_) 263 | ]])); 264 | } 265 | 266 | private: 267 | // No implementation - assignment is unsupported. 268 | void operator=(const CartesianProductHolder$i& other); 269 | 270 | 271 | $for j [[ 272 | const Generator$j g$(j)_; 273 | 274 | ]] 275 | }; // class CartesianProductHolder$i 276 | 277 | ]] 278 | 279 | # endif // GTEST_HAS_COMBINE 280 | 281 | } // namespace internal 282 | } // namespace testing 283 | 284 | #endif // GTEST_HAS_PARAM_TEST 285 | 286 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 287 | -------------------------------------------------------------------------------- /test/gtest/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 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 GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 36 | #define GTEST_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 __SYMBIAN32__ 42 | # define GTEST_OS_SYMBIAN 1 43 | #elif defined _WIN32 44 | # define GTEST_OS_WINDOWS 1 45 | # ifdef _WIN32_WCE 46 | # define GTEST_OS_WINDOWS_MOBILE 1 47 | # elif defined(__MINGW__) || defined(__MINGW32__) 48 | # define GTEST_OS_WINDOWS_MINGW 1 49 | # elif defined(WINAPI_FAMILY) 50 | # include 51 | # if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 52 | # define GTEST_OS_WINDOWS_DESKTOP 1 53 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) 54 | # define GTEST_OS_WINDOWS_PHONE 1 55 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 56 | # define GTEST_OS_WINDOWS_RT 1 57 | # else 58 | // WINAPI_FAMILY defined but no known partition matched. 59 | // Default to desktop. 60 | # define GTEST_OS_WINDOWS_DESKTOP 1 61 | # endif 62 | # else 63 | # define GTEST_OS_WINDOWS_DESKTOP 1 64 | # endif // _WIN32_WCE 65 | #elif defined __APPLE__ 66 | # define GTEST_OS_MAC 1 67 | # if TARGET_OS_IPHONE 68 | # define GTEST_OS_IOS 1 69 | # endif 70 | #elif defined __FreeBSD__ 71 | # define GTEST_OS_FREEBSD 1 72 | #elif defined __linux__ 73 | # define GTEST_OS_LINUX 1 74 | # if defined __ANDROID__ 75 | # define GTEST_OS_LINUX_ANDROID 1 76 | # endif 77 | #elif defined __MVS__ 78 | # define GTEST_OS_ZOS 1 79 | #elif defined(__sun) && defined(__SVR4) 80 | # define GTEST_OS_SOLARIS 1 81 | #elif defined(_AIX) 82 | # define GTEST_OS_AIX 1 83 | #elif defined(__hpux) 84 | # define GTEST_OS_HPUX 1 85 | #elif defined __native_client__ 86 | # define GTEST_OS_NACL 1 87 | #elif defined __OpenBSD__ 88 | # define GTEST_OS_OPENBSD 1 89 | #elif defined __QNX__ 90 | # define GTEST_OS_QNX 1 91 | #endif // __CYGWIN__ 92 | 93 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 94 | -------------------------------------------------------------------------------- /test/gtest/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 | // Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) 31 | // 32 | // The Google C++ Testing Framework (Google Test) 33 | // 34 | // This header file declares the String class and functions used internally by 35 | // Google Test. They are subject to change without notice. They should not used 36 | // by code external to Google Test. 37 | // 38 | // This header file is #included by . 39 | // It should not be #included by other files. 40 | 41 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 42 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 43 | 44 | #ifdef __BORLANDC__ 45 | // string.h is not guaranteed to provide strcpy on C++ Builder. 46 | # include 47 | #endif 48 | 49 | #include 50 | #include 51 | 52 | #include "gtest/internal/gtest-port.h" 53 | 54 | namespace testing { 55 | namespace internal { 56 | 57 | // String - an abstract class holding static string utilities. 58 | class GTEST_API_ String { 59 | public: 60 | // Static utility methods 61 | 62 | // Clones a 0-terminated C string, allocating memory using new. The 63 | // caller is responsible for deleting the return value using 64 | // delete[]. Returns the cloned string, or NULL if the input is 65 | // NULL. 66 | // 67 | // This is different from strdup() in string.h, which allocates 68 | // memory using malloc(). 69 | static const char* CloneCString(const char* c_str); 70 | 71 | #if GTEST_OS_WINDOWS_MOBILE 72 | // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be 73 | // able to pass strings to Win32 APIs on CE we need to convert them 74 | // to 'Unicode', UTF-16. 75 | 76 | // Creates a UTF-16 wide string from the given ANSI string, allocating 77 | // memory using new. The caller is responsible for deleting the return 78 | // value using delete[]. Returns the wide string, or NULL if the 79 | // input is NULL. 80 | // 81 | // The wide string is created using the ANSI codepage (CP_ACP) to 82 | // match the behaviour of the ANSI versions of Win32 calls and the 83 | // C runtime. 84 | static LPCWSTR AnsiToUtf16(const char* c_str); 85 | 86 | // Creates an ANSI string from the given wide string, allocating 87 | // memory using new. The caller is responsible for deleting the return 88 | // value using delete[]. Returns the ANSI string, or NULL if the 89 | // input is NULL. 90 | // 91 | // The returned string is created using the ANSI codepage (CP_ACP) to 92 | // match the behaviour of the ANSI versions of Win32 calls and the 93 | // C runtime. 94 | static const char* Utf16ToAnsi(LPCWSTR utf16_str); 95 | #endif 96 | 97 | // Compares two C strings. Returns true iff they have the same 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 iff they have the same 111 | // 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 iff they 119 | // 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 iff they 128 | // 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 iff the given string ends with the given suffix, ignoring 143 | // 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 as "%X". 151 | static std::string FormatHexInt(int value); 152 | 153 | // Formats a byte as "%02X". 154 | static std::string FormatByte(unsigned char value); 155 | 156 | private: 157 | String(); // Not meant to be instantiated. 158 | }; // class String 159 | 160 | // Gets the content of the stringstream's buffer as an std::string. Each '\0' 161 | // character in the buffer is replaced with "\\0". 162 | GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); 163 | 164 | } // namespace internal 165 | } // namespace testing 166 | 167 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 168 | -------------------------------------------------------------------------------- /test/gtest/include/gtest/internal/gtest-type-util.h.pump: -------------------------------------------------------------------------------- 1 | $$ -*- mode: c++; -*- 2 | $var n = 50 $$ Maximum length of type lists we want to support. 3 | // Copyright 2008 Google Inc. 4 | // All Rights Reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are 8 | // met: 9 | // 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above 13 | // copyright notice, this list of conditions and the following disclaimer 14 | // in the documentation and/or other materials provided with the 15 | // distribution. 16 | // * Neither the name of Google Inc. nor the names of its 17 | // contributors may be used to endorse or promote products derived from 18 | // this software without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | // 32 | // Author: wan@google.com (Zhanyong Wan) 33 | 34 | // Type utilities needed for implementing typed and type-parameterized 35 | // tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! 36 | // 37 | // Currently we support at most $n types in a list, and at most $n 38 | // type-parameterized tests in one type-parameterized test case. 39 | // Please contact googletestframework@googlegroups.com if you need 40 | // more. 41 | 42 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 43 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 44 | 45 | #include "gtest/internal/gtest-port.h" 46 | 47 | // #ifdef __GNUC__ is too general here. It is possible to use gcc without using 48 | // libstdc++ (which is where cxxabi.h comes from). 49 | # if GTEST_HAS_CXXABI_H_ 50 | # include 51 | # elif defined(__HP_aCC) 52 | # include 53 | # endif // GTEST_HASH_CXXABI_H_ 54 | 55 | namespace testing { 56 | namespace internal { 57 | 58 | // GetTypeName() returns a human-readable name of type T. 59 | // NB: This function is also used in Google Mock, so don't move it inside of 60 | // the typed-test-only section below. 61 | template 62 | std::string GetTypeName() { 63 | # if GTEST_HAS_RTTI 64 | 65 | const char* const name = typeid(T).name(); 66 | # if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) 67 | int status = 0; 68 | // gcc's implementation of typeid(T).name() mangles the type name, 69 | // so we have to demangle it. 70 | # if GTEST_HAS_CXXABI_H_ 71 | using abi::__cxa_demangle; 72 | # endif // GTEST_HAS_CXXABI_H_ 73 | char* const readable_name = __cxa_demangle(name, 0, 0, &status); 74 | const std::string name_str(status == 0 ? readable_name : name); 75 | free(readable_name); 76 | return name_str; 77 | # else 78 | return name; 79 | # endif // GTEST_HAS_CXXABI_H_ || __HP_aCC 80 | 81 | # else 82 | 83 | return ""; 84 | 85 | # endif // GTEST_HAS_RTTI 86 | } 87 | 88 | #if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P 89 | 90 | // AssertyTypeEq::type is defined iff T1 and T2 are the same 91 | // type. This can be used as a compile-time assertion to ensure that 92 | // two types are equal. 93 | 94 | template 95 | struct AssertTypeEq; 96 | 97 | template 98 | struct AssertTypeEq { 99 | typedef bool type; 100 | }; 101 | 102 | // A unique type used as the default value for the arguments of class 103 | // template Types. This allows us to simulate variadic templates 104 | // (e.g. Types, Type, and etc), which C++ doesn't 105 | // support directly. 106 | struct None {}; 107 | 108 | // The following family of struct and struct templates are used to 109 | // represent type lists. In particular, TypesN 110 | // represents a type list with N types (T1, T2, ..., and TN) in it. 111 | // Except for Types0, every struct in the family has two member types: 112 | // Head for the first type in the list, and Tail for the rest of the 113 | // list. 114 | 115 | // The empty type list. 116 | struct Types0 {}; 117 | 118 | // Type lists of length 1, 2, 3, and so on. 119 | 120 | template 121 | struct Types1 { 122 | typedef T1 Head; 123 | typedef Types0 Tail; 124 | }; 125 | 126 | $range i 2..n 127 | 128 | $for i [[ 129 | $range j 1..i 130 | $range k 2..i 131 | template <$for j, [[typename T$j]]> 132 | struct Types$i { 133 | typedef T1 Head; 134 | typedef Types$(i-1)<$for k, [[T$k]]> Tail; 135 | }; 136 | 137 | 138 | ]] 139 | 140 | } // namespace internal 141 | 142 | // We don't want to require the users to write TypesN<...> directly, 143 | // as that would require them to count the length. Types<...> is much 144 | // easier to write, but generates horrible messages when there is a 145 | // compiler error, as gcc insists on printing out each template 146 | // argument, even if it has the default value (this means Types 147 | // will appear as Types in the compiler 148 | // errors). 149 | // 150 | // Our solution is to combine the best part of the two approaches: a 151 | // user would write Types, and Google Test will translate 152 | // that to TypesN internally to make error messages 153 | // readable. The translation is done by the 'type' member of the 154 | // Types template. 155 | 156 | $range i 1..n 157 | template <$for i, [[typename T$i = internal::None]]> 158 | struct Types { 159 | typedef internal::Types$n<$for i, [[T$i]]> type; 160 | }; 161 | 162 | template <> 163 | struct Types<$for i, [[internal::None]]> { 164 | typedef internal::Types0 type; 165 | }; 166 | 167 | $range i 1..n-1 168 | $for i [[ 169 | $range j 1..i 170 | $range k i+1..n 171 | template <$for j, [[typename T$j]]> 172 | struct Types<$for j, [[T$j]]$for k[[, internal::None]]> { 173 | typedef internal::Types$i<$for j, [[T$j]]> type; 174 | }; 175 | 176 | ]] 177 | 178 | namespace internal { 179 | 180 | # define GTEST_TEMPLATE_ template class 181 | 182 | // The template "selector" struct TemplateSel is used to 183 | // represent Tmpl, which must be a class template with one type 184 | // parameter, as a type. TemplateSel::Bind::type is defined 185 | // as the type Tmpl. This allows us to actually instantiate the 186 | // template "selected" by TemplateSel. 187 | // 188 | // This trick is necessary for simulating typedef for class templates, 189 | // which C++ doesn't support directly. 190 | template 191 | struct TemplateSel { 192 | template 193 | struct Bind { 194 | typedef Tmpl type; 195 | }; 196 | }; 197 | 198 | # define GTEST_BIND_(TmplSel, T) \ 199 | TmplSel::template Bind::type 200 | 201 | // A unique struct template used as the default value for the 202 | // arguments of class template Templates. This allows us to simulate 203 | // variadic templates (e.g. Templates, Templates, 204 | // and etc), which C++ doesn't support directly. 205 | template 206 | struct NoneT {}; 207 | 208 | // The following family of struct and struct templates are used to 209 | // represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except 211 | // for Templates0, every struct in the family has two member types: 212 | // Head for the selector of the first template in the list, and Tail 213 | // for the rest of the list. 214 | 215 | // The empty template list. 216 | struct Templates0 {}; 217 | 218 | // Template lists of length 1, 2, 3, and so on. 219 | 220 | template 221 | struct Templates1 { 222 | typedef TemplateSel Head; 223 | typedef Templates0 Tail; 224 | }; 225 | 226 | $range i 2..n 227 | 228 | $for i [[ 229 | $range j 1..i 230 | $range k 2..i 231 | template <$for j, [[GTEST_TEMPLATE_ T$j]]> 232 | struct Templates$i { 233 | typedef TemplateSel Head; 234 | typedef Templates$(i-1)<$for k, [[T$k]]> Tail; 235 | }; 236 | 237 | 238 | ]] 239 | 240 | // We don't want to require the users to write TemplatesN<...> directly, 241 | // as that would require them to count the length. Templates<...> is much 242 | // easier to write, but generates horrible messages when there is a 243 | // compiler error, as gcc insists on printing out each template 244 | // argument, even if it has the default value (this means Templates 245 | // will appear as Templates in the compiler 246 | // errors). 247 | // 248 | // Our solution is to combine the best part of the two approaches: a 249 | // user would write Templates, and Google Test will translate 250 | // that to TemplatesN internally to make error messages 251 | // readable. The translation is done by the 'type' member of the 252 | // Templates template. 253 | 254 | $range i 1..n 255 | template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]> 256 | struct Templates { 257 | typedef Templates$n<$for i, [[T$i]]> type; 258 | }; 259 | 260 | template <> 261 | struct Templates<$for i, [[NoneT]]> { 262 | typedef Templates0 type; 263 | }; 264 | 265 | $range i 1..n-1 266 | $for i [[ 267 | $range j 1..i 268 | $range k i+1..n 269 | template <$for j, [[GTEST_TEMPLATE_ T$j]]> 270 | struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> { 271 | typedef Templates$i<$for j, [[T$j]]> type; 272 | }; 273 | 274 | ]] 275 | 276 | // The TypeList template makes it possible to use either a single type 277 | // or a Types<...> list in TYPED_TEST_CASE() and 278 | // INSTANTIATE_TYPED_TEST_CASE_P(). 279 | 280 | template 281 | struct TypeList { 282 | typedef Types1 type; 283 | }; 284 | 285 | 286 | $range i 1..n 287 | template <$for i, [[typename T$i]]> 288 | struct TypeList > { 289 | typedef typename Types<$for i, [[T$i]]>::type type; 290 | }; 291 | 292 | #endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P 293 | 294 | } // namespace internal 295 | } // namespace testing 296 | 297 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 298 | -------------------------------------------------------------------------------- /test/gtest/src/gtest-all.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 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | // Google C++ Testing Framework (Google Test) 33 | // 34 | // Sometimes it's desirable to build Google Test by compiling a single file. 35 | // This file serves this purpose. 36 | 37 | // This line ensures that gtest.h can be compiled on its own, even 38 | // when it's fused. 39 | #include "gtest/gtest.h" 40 | 41 | // The following lines pull in the real gtest *.cc files. 42 | #include "src/gtest.cc" 43 | #include "src/gtest-death-test.cc" 44 | #include "src/gtest-filepath.cc" 45 | #include "src/gtest-port.cc" 46 | #include "src/gtest-printers.cc" 47 | #include "src/gtest-test-part.cc" 48 | #include "src/gtest-typed-test.cc" 49 | -------------------------------------------------------------------------------- /test/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 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | // The Google C++ Testing Framework (Google Test) 33 | 34 | #include "gtest/gtest-test-part.h" 35 | 36 | // Indicates that this translation unit is part of Google Test's 37 | // implementation. It must come before gtest-internal-inl.h is 38 | // included, or there will be a compiler error. This trick exists to 39 | // prevent the accidental inclusion of gtest-internal-inl.h in the 40 | // user's code. 41 | #define GTEST_IMPLEMENTATION_ 1 42 | #include "src/gtest-internal-inl.h" 43 | #undef GTEST_IMPLEMENTATION_ 44 | 45 | namespace testing { 46 | 47 | using internal::GetUnitTestImpl; 48 | 49 | // Gets the summary of the failure message by omitting the stack trace 50 | // in it. 51 | std::string TestPartResult::ExtractSummary(const char* message) { 52 | const char* const stack_trace = strstr(message, internal::kStackTraceMarker); 53 | return stack_trace == NULL ? message : 54 | std::string(message, stack_trace); 55 | } 56 | 57 | // Prints a TestPartResult object. 58 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { 59 | return os 60 | << result.file_name() << ":" << result.line_number() << ": " 61 | << (result.type() == TestPartResult::kSuccess ? "Success" : 62 | result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : 63 | "Non-fatal failure") << ":\n" 64 | << result.message() << std::endl; 65 | } 66 | 67 | // Appends a TestPartResult to the array. 68 | void TestPartResultArray::Append(const TestPartResult& result) { 69 | array_.push_back(result); 70 | } 71 | 72 | // Returns the TestPartResult at the given index (0-based). 73 | const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { 74 | if (index < 0 || index >= size()) { 75 | printf("\nInvalid index (%d) into TestPartResultArray.\n", index); 76 | internal::posix::Abort(); 77 | } 78 | 79 | return array_[index]; 80 | } 81 | 82 | // Returns the number of TestPartResult objects in the array. 83 | int TestPartResultArray::size() const { 84 | return static_cast(array_.size()); 85 | } 86 | 87 | namespace internal { 88 | 89 | HasNewFatalFailureHelper::HasNewFatalFailureHelper() 90 | : has_new_fatal_failure_(false), 91 | original_reporter_(GetUnitTestImpl()-> 92 | GetTestPartResultReporterForCurrentThread()) { 93 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); 94 | } 95 | 96 | HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { 97 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( 98 | original_reporter_); 99 | } 100 | 101 | void HasNewFatalFailureHelper::ReportTestPartResult( 102 | const TestPartResult& result) { 103 | if (result.fatally_failed()) 104 | has_new_fatal_failure_ = true; 105 | original_reporter_->ReportTestPartResult(result); 106 | } 107 | 108 | } // namespace internal 109 | 110 | } // namespace testing 111 | -------------------------------------------------------------------------------- /test/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 | // Author: wan@google.com (Zhanyong Wan) 31 | 32 | #include "gtest/gtest-typed-test.h" 33 | #include "gtest/gtest.h" 34 | 35 | namespace testing { 36 | namespace internal { 37 | 38 | #if GTEST_HAS_TYPED_TEST_P 39 | 40 | // Skips to the first non-space char in str. Returns an empty string if str 41 | // contains only whitespace characters. 42 | static const char* SkipSpaces(const char* str) { 43 | while (IsSpace(*str)) 44 | str++; 45 | return str; 46 | } 47 | 48 | static std::vector SplitIntoTestNames(const char* src) { 49 | std::vector name_vec; 50 | src = SkipSpaces(src); 51 | for (; src != NULL; src = SkipComma(src)) { 52 | name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src))); 53 | } 54 | return name_vec; 55 | } 56 | 57 | // Verifies that registered_tests match the test names in 58 | // registered_tests_; returns registered_tests if successful, or 59 | // aborts the program otherwise. 60 | const char* TypedTestCasePState::VerifyRegisteredTestNames( 61 | const char* file, int line, const char* registered_tests) { 62 | typedef RegisteredTestsMap::const_iterator RegisteredTestIter; 63 | registered_ = true; 64 | 65 | std::vector name_vec = SplitIntoTestNames(registered_tests); 66 | 67 | Message errors; 68 | 69 | std::set tests; 70 | for (std::vector::const_iterator name_it = name_vec.begin(); 71 | name_it != name_vec.end(); ++name_it) { 72 | const std::string& name = *name_it; 73 | if (tests.count(name) != 0) { 74 | errors << "Test " << name << " is listed more than once.\n"; 75 | continue; 76 | } 77 | 78 | bool found = false; 79 | for (RegisteredTestIter it = registered_tests_.begin(); 80 | it != registered_tests_.end(); 81 | ++it) { 82 | if (name == it->first) { 83 | found = true; 84 | break; 85 | } 86 | } 87 | 88 | if (found) { 89 | tests.insert(name); 90 | } else { 91 | errors << "No test named " << name 92 | << " can be found in this test case.\n"; 93 | } 94 | } 95 | 96 | for (RegisteredTestIter it = registered_tests_.begin(); 97 | it != registered_tests_.end(); 98 | ++it) { 99 | if (tests.count(it->first) == 0) { 100 | errors << "You forgot to list test " << it->first << ".\n"; 101 | } 102 | } 103 | 104 | const std::string& errors_str = errors.GetString(); 105 | if (errors_str != "") { 106 | fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), 107 | errors_str.c_str()); 108 | fflush(stderr); 109 | posix::Abort(); 110 | } 111 | 112 | return registered_tests; 113 | } 114 | 115 | #endif // GTEST_HAS_TYPED_TEST_P 116 | 117 | } // namespace internal 118 | } // namespace testing 119 | -------------------------------------------------------------------------------- /test/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 | 32 | #include "gtest/gtest.h" 33 | 34 | GTEST_API_ int main(int argc, char **argv) { 35 | printf("Running main() from gtest_main.cc\n"); 36 | testing::InitGoogleTest(&argc, argv); 37 | return RUN_ALL_TESTS(); 38 | } 39 | -------------------------------------------------------------------------------- /test/unit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # CMake file for sigcxx project 3 | # 4 | 5 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 6 | 7 | add_subdirectory(delegate) 8 | add_subdirectory(trackable_unbind) 9 | add_subdirectory(signal_base) 10 | add_subdirectory(signal_connect) 11 | add_subdirectory(signal_check_connection) 12 | add_subdirectory(signal_disconnect) 13 | add_subdirectory(signal_delete_this) 14 | add_subdirectory(signal_virtual) 15 | add_subdirectory(disconnect_on_fire) 16 | add_subdirectory(disconnect_with_slot) 17 | add_subdirectory(compare_boost_signal2) 18 | add_subdirectory(thread_safe) 19 | 20 | if (WITH_QT5) 21 | add_subdirectory(compare_qt5) 22 | endif () 23 | -------------------------------------------------------------------------------- /test/unit/compare_boost_signal2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | find_package(Boost COMPONENTS signals) 5 | if(Boost_FOUND) 6 | include_directories(${Boost_INCLUDE_DIRS}) 7 | set(LIBS ${LIBS} ${Boost_LIBRARIES}) 8 | add_definitions(-DUSE_BOOST_SIGNALS) 9 | message(STATUS "boost lib dir: ${Boost_LIBRARY_DIRS}") 10 | endif() 11 | 12 | add_executable(test_compare_boost_signal2 ${sources} ${headers}) 13 | target_link_libraries(test_compare_boost_signal2 sigcxx gtest common ${LIBS}) 14 | -------------------------------------------------------------------------------- /test/unit/compare_boost_signal2/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/compare_boost_signal2/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | 5 | #include 6 | 7 | #ifdef USE_BOOST_SIGNALS 8 | #include 9 | #endif 10 | 11 | #define TEST_CYCLE_NUM 10000000 12 | 13 | Test::Test() 14 | : testing::Test() 15 | { 16 | } 17 | 18 | Test::~Test() 19 | { 20 | 21 | } 22 | 23 | TEST_F(Test, fire_many_times) 24 | { 25 | Observer consumer; 26 | sigcxx::Signal<> event; 27 | 28 | event.Connect(&consumer, &Observer::OnTest0); 29 | 30 | for(int i = 0; i < TEST_CYCLE_NUM; i++) 31 | { 32 | event(); 33 | } 34 | 35 | ASSERT_TRUE(consumer.test0_count() == TEST_CYCLE_NUM); 36 | } 37 | 38 | TEST_F(Test, connect_many_events) 39 | { 40 | Observer consumer; 41 | sigcxx::Signal<> event; 42 | 43 | for(int i = 0; i < TEST_CYCLE_NUM; i++) 44 | { 45 | event.Connect(&consumer, &Observer::OnTest0); 46 | } 47 | 48 | //signal_base(); 49 | 50 | ASSERT_TRUE(consumer.test0_count() == 0); 51 | } 52 | 53 | #ifdef USE_BOOST_SIGNALS 54 | 55 | struct Simple 56 | { 57 | public: 58 | 59 | Simple () 60 | : value(0) {} 61 | 62 | void operator()() 63 | { 64 | value++; 65 | } 66 | 67 | size_t value; 68 | }; 69 | 70 | TEST_F(Test, boost_signals2_fire_many_times) 71 | { 72 | // Signal with no arguments and a void return value 73 | boost::signals2::signal sig; 74 | 75 | // Connect a slot 76 | Simple c; 77 | 78 | sig.connect(c); 79 | 80 | // Call all of the slots 81 | for(int i = 0; i < TEST_CYCLE_NUM; i++) 82 | { 83 | sig(); 84 | } 85 | 86 | ASSERT_TRUE(true); 87 | } 88 | 89 | TEST_F(Test, boost_signals2_connect_many_times) 90 | { 91 | // Signal with no arguments and a void return value 92 | boost::signals2::signal sig; 93 | 94 | // Connect a slot 95 | Simple c; 96 | 97 | for(int i = 0; i < TEST_CYCLE_NUM; i++) 98 | { 99 | sig.connect(c); 100 | } 101 | 102 | // Call all of the slots 103 | // sig(); 104 | 105 | ASSERT_TRUE(true); 106 | } 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /test/unit/compare_boost_signal2/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | using sigcxx::Slot; 10 | 11 | class Test: public testing::Test 12 | { 13 | public: 14 | Test (); 15 | virtual ~Test(); 16 | 17 | protected: 18 | virtual void SetUp() { } 19 | virtual void TearDown() { } 20 | }; 21 | -------------------------------------------------------------------------------- /test/unit/compare_qt5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Find includes in corresponding build directories 2 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 3 | # Instruct CMake to run moc automatically when needed. 4 | set(CMAKE_AUTOMOC ON) 5 | 6 | # Find the QtWidgets library 7 | find_package(Qt5Core) 8 | 9 | file(GLOB sources "*.cpp") 10 | file(GLOB headers "*.hpp") 11 | 12 | add_executable(test_compare_qt5 ${sources} ${headers}) 13 | target_link_libraries(test_compare_qt5 sigcxx gtest common Qt5::Core) 14 | -------------------------------------------------------------------------------- /test/unit/compare_qt5/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/compare_qt5/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | #include 5 | #include 6 | #include 7 | 8 | #define TEST_CYCLE_NUM 10000000 9 | 10 | using namespace std; 11 | 12 | Test::Test() 13 | : testing::Test() 14 | { 15 | } 16 | 17 | Test::~Test() 18 | { 19 | 20 | } 21 | 22 | TEST_F(Test, qt_emit) 23 | { 24 | QtSource s; 25 | QtConsumer c; 26 | 27 | QObject::connect(&s, &QtSource::valueChanged, &c, &QtConsumer::setValue); 28 | 29 | for(int i = 0; i < TEST_CYCLE_NUM; i++) { 30 | s.emit_signal(i); 31 | } 32 | ASSERT_TRUE(true); 33 | } 34 | 35 | /* 36 | * 37 | */ 38 | TEST_F(Test, sigcxx_emit) 39 | { 40 | Subject s; 41 | Observer c; 42 | 43 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 44 | 45 | for(int i = 0; i < TEST_CYCLE_NUM; i++) { 46 | s.emit_signal1(i); 47 | } 48 | ASSERT_TRUE(true); 49 | } 50 | 51 | TEST_F(Test, qt_connect) 52 | { 53 | QtSource s; 54 | QtConsumer c; 55 | 56 | for(int i = 0; i < TEST_CYCLE_NUM; i++) { 57 | QObject::connect(&s, &QtSource::valueChanged, &c, &QtConsumer::setValue); 58 | } 59 | s.emit_signal(1); 60 | ASSERT_TRUE(true); 61 | } 62 | 63 | TEST_F(Test, sigcxx_connect) 64 | { 65 | Subject s; 66 | Observer c; 67 | 68 | for(int i = 0; i < TEST_CYCLE_NUM; i++) { 69 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 70 | } 71 | s.emit_signal1(1); 72 | ASSERT_TRUE(true); 73 | } 74 | -------------------------------------------------------------------------------- /test/unit/compare_qt5/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | using sigcxx::Slot; 11 | 12 | class Test: public testing::Test 13 | { 14 | public: 15 | Test (); 16 | virtual ~Test(); 17 | 18 | protected: 19 | virtual void SetUp() { } 20 | virtual void TearDown() { } 21 | }; 22 | 23 | class QtSource: public QObject 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | QtSource() {} 29 | virtual ~QtSource() {} 30 | 31 | inline void emit_signal(int n) 32 | { 33 | emit valueChanged(n); 34 | } 35 | 36 | signals: 37 | 38 | void valueChanged (int); 39 | }; 40 | 41 | class QtConsumer: public QObject 42 | { 43 | Q_OBJECT 44 | 45 | public: 46 | QtConsumer() 47 | : QObject(), count_(0) 48 | {} 49 | 50 | virtual ~QtConsumer () {} 51 | 52 | public slots: 53 | 54 | void setValue (int n) 55 | { 56 | count_++; 57 | } 58 | 59 | private: 60 | size_t count_; 61 | }; 62 | -------------------------------------------------------------------------------- /test/unit/delegate/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_delegate ${sources} ${headers}) 5 | target_link_libraries(test_delegate sigcxx gtest) 6 | -------------------------------------------------------------------------------- /test/unit/delegate/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/delegate/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | 5 | #include 6 | 7 | using namespace sigcxx; 8 | 9 | Test::Test() 10 | : testing::Test() { 11 | } 12 | 13 | Test::~Test() { 14 | 15 | } 16 | 17 | TEST_F(Test, rtti) { 18 | TestClassBase obj; 19 | 20 | ASSERT_TRUE(typeid(&obj) == typeid(TestClassBase *)); 21 | } 22 | 23 | /* 24 | * 25 | */ 26 | TEST_F(Test, delegate1) { 27 | TestClassBase obj1; 28 | 29 | Delegate d3; 30 | 31 | Delegate d = Delegate::FromMethod(&obj1, &TestClassBase::ConstMethod1); 32 | 33 | bool result = d.Equal(&obj1, &TestClassBase::Method1); 34 | 35 | if (!result) { 36 | std::cout << "const not equal to non-const" << std::endl; 37 | } 38 | 39 | d(1); 40 | 41 | // And test delegate to private method: 42 | 43 | // uncomment this line should not work: 44 | // DelegateT dp = DelegateT::FromMethod(&obj1, &TestClassBase::MethodInPrivate); 45 | 46 | // can only create delegate to private method in class methods, just what we want. 47 | obj1.TestPrivateMethod(); 48 | 49 | ASSERT_TRUE(!result); 50 | } 51 | 52 | TEST_F(Test, delegate2) { 53 | TestClassBase obj1; 54 | Delegate d1 = Delegate::FromMethod(&obj1, &TestClassBase::ConstMethod1); 55 | Delegate d2 = Delegate::FromMethod(&obj1, &TestClassBase::Method1); 56 | 57 | if (d1 == d2) { 58 | std::cout << "2 delegates equal" << std::endl; 59 | } 60 | 61 | if (d1 != d2) { 62 | std::cout << " not equal" << std::endl; 63 | } 64 | 65 | if (d1 < d2) { 66 | std::cout << " less then " << std::endl; 67 | } 68 | 69 | if (d1 > d2) { 70 | std::cout << " great then " << std::endl; 71 | } 72 | 73 | d1(1); 74 | ASSERT_TRUE(true); 75 | } 76 | 77 | /* 78 | * 79 | */ 80 | TEST_F(Test, delegate3) { 81 | TestClassBase obj1; 82 | 83 | Delegate d = Delegate::FromMethod(&obj1, &TestClassBase::MethodWithReturn); 84 | 85 | ASSERT_TRUE(d(1) == 1); 86 | } 87 | 88 | /* 89 | * 90 | */ 91 | TEST_F(Test, delegate4) { 92 | TestClassBase obj1; 93 | 94 | Delegate d; 95 | ASSERT_FALSE(d); 96 | 97 | d = Delegate::FromMethod(&obj1, &TestClassBase::MethodWithReturn); 98 | 99 | ASSERT_TRUE(d(1) == 1); 100 | } 101 | 102 | /* 103 | * 104 | */ 105 | TEST_F(Test, delegate5) { 106 | TestClassBase obj1; 107 | 108 | Delegate d1(&obj1, &TestClassBase::ConstMethod1); 109 | Delegate d2(&obj1, &TestClassBase::Method1); 110 | 111 | d2 = d1; 112 | 113 | d2(1); // check the stdout print 114 | 115 | ASSERT_TRUE(d1 && d2); 116 | } 117 | 118 | TEST_F(Test, delegate_ref_1) { 119 | TestClassBase obj1; 120 | 121 | Delegate d1(&obj1, &TestClassBase::Method1); 122 | Delegate d2(&obj1, &TestClassBase::ConstMethod1); 123 | 124 | DelegateRef r1(d1); 125 | DelegateRef r2(d2); 126 | 127 | r1.Bind(&obj1, &TestClassBase::Method1); 128 | r2.Bind(&obj1, &TestClassBase::ConstMethod1); 129 | 130 | ASSERT_TRUE(r1 && r2); 131 | 132 | bool result1 = r1.IsBoundTo(&obj1, &TestClassBase::Method1); 133 | bool result2 = r2.IsBoundTo(&obj1, &TestClassBase::ConstMethod1); 134 | 135 | ASSERT_TRUE(result1 && result2); 136 | 137 | r1.Reset(); 138 | r2.Reset(); 139 | 140 | ASSERT_TRUE((!r1) && (!r2)); 141 | } 142 | -------------------------------------------------------------------------------- /test/unit/delegate/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class Test : public testing::Test { 10 | public: 11 | Test(); 12 | virtual ~Test(); 13 | 14 | protected: 15 | virtual void SetUp() {} 16 | virtual void TearDown() {} 17 | }; 18 | 19 | class TestClassBase { 20 | public: 21 | 22 | TestClassBase() { 23 | } 24 | 25 | virtual ~TestClassBase() { 26 | } 27 | 28 | void TestPrivateMethod() { 29 | // delegate to private method only within class method 30 | sigcxx::Delegate dp = sigcxx::Delegate::FromMethod(this, &TestClassBase::MethodInPrivate); 31 | } 32 | 33 | int MethodWithReturn(int n) { 34 | return n; 35 | } 36 | 37 | virtual void Method0() { 38 | std::cout << "Method0 in base class" << std::endl; 39 | } 40 | 41 | virtual void Method1(int p0) { 42 | std::cout << "Method1 in base class, param0: " << p0 << std::endl; 43 | } 44 | 45 | virtual void ConstMethod1(int p0) const { 46 | std::cout << "ConstMethod1 in base class, param0: " << p0 << std::endl; 47 | } 48 | 49 | virtual void Method2(int p0, int p1) const { 50 | std::cout << "const Method2 in base class, param0: " << p0 << " param1: " 51 | << p1 << std::endl; 52 | } 53 | 54 | private: 55 | void MethodInPrivate() { 56 | std::cout << "Cannot build delegate outside" << std::endl; 57 | } 58 | }; 59 | 60 | class TestClassDerived : public TestClassBase { 61 | public: 62 | 63 | TestClassDerived() 64 | : TestClassBase() { 65 | } 66 | 67 | virtual ~TestClassDerived() { 68 | 69 | } 70 | 71 | virtual void Method0() override { 72 | std::cout << "Method0 in sub class" << std::endl; 73 | } 74 | 75 | virtual void Method1(int p0) override { 76 | std::cout << "Method1 in sub class, param0: " << p0 << std::endl; 77 | } 78 | 79 | }; 80 | -------------------------------------------------------------------------------- /test/unit/disconnect_on_fire/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_disconnect_on_fire ${sources} ${headers}) 5 | target_link_libraries(test_disconnect_on_fire sigcxx gtest common) 6 | -------------------------------------------------------------------------------- /test/unit/disconnect_on_fire/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/disconnect_on_fire/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | using namespace sigcxx; 11 | 12 | Test::Test() 13 | : testing::Test() { 14 | } 15 | 16 | Test::~Test() { 17 | 18 | } 19 | 20 | class Source { 21 | public: 22 | 23 | Source() {} 24 | ~Source() {} 25 | 26 | void DoTest(int n = 0) { 27 | event_.Emit(n); 28 | } 29 | 30 | inline sigcxx::Signal &event() { 31 | return event_; 32 | } 33 | 34 | private: 35 | 36 | sigcxx::Signal event_; 37 | }; 38 | 39 | class Consumer : public sigcxx::Trackable { 40 | public: 41 | 42 | Consumer() {} 43 | 44 | virtual ~Consumer() {} 45 | 46 | void OnTestNothing(int /* n */, SLOT /* slot */) { 47 | // do nothing... 48 | } 49 | 50 | void OnTestDisconnectFirst(int n, SLOT slot) { 51 | UnbindSignal(slot); 52 | // sender->signal_base().DisconnectOnce(this, &Consumer::OnTestDisconnectFirst, 0); 53 | } 54 | 55 | void OnTestDisconnectLast(int n, SLOT slot) { 56 | UnbindSignal(slot); 57 | // sender->signal_base().DisconnectOnce(this, &Consumer::OnTestDisconnectLast, -1); 58 | } 59 | 60 | void OnTestDisconnectAll(int n, SLOT slot) { 61 | // RemoveAllInConnections(sender); 62 | // sender->signal_base().DisconnectAll(this, &Consumer::OnTestDisconnectAll); 63 | UnbindAllSignalsTo(&Consumer::OnTestDisconnectAll); 64 | } 65 | 66 | }; 67 | 68 | /* 69 | * 70 | */ 71 | TEST_F(Test, disconnect_first_on_fire1) { 72 | Source s; 73 | Consumer c; 74 | 75 | s.event().Connect(&c, &Consumer::OnTestDisconnectFirst); 76 | s.event().Connect(&c, &Consumer::OnTestNothing); 77 | s.event().Connect(&c, &Consumer::OnTestNothing); 78 | 79 | s.DoTest(); 80 | ASSERT_TRUE(c.CountSignalBindings() == 2); 81 | } 82 | 83 | /* 84 | * 85 | */ 86 | TEST_F(Test, disconnect_first_on_fire2) { 87 | Source s; 88 | Consumer c; 89 | 90 | s.event().Connect(&c, &Consumer::OnTestNothing); 91 | s.event().Connect(&c, &Consumer::OnTestDisconnectFirst); 92 | s.event().Connect(&c, &Consumer::OnTestNothing); 93 | 94 | s.DoTest(); 95 | ASSERT_TRUE(c.CountSignalBindings() == 2); 96 | } 97 | 98 | /* 99 | * 100 | */ 101 | TEST_F(Test, disconnect_last_on_fire1) { 102 | Source s; 103 | Consumer c; 104 | 105 | s.event().Connect(&c, &Consumer::OnTestNothing); 106 | s.event().Connect(&c, &Consumer::OnTestNothing); 107 | s.event().Connect(&c, &Consumer::OnTestDisconnectLast); 108 | 109 | s.DoTest(); 110 | ASSERT_TRUE(c.CountSignalBindings() == 2); 111 | } 112 | 113 | /* 114 | * 115 | */ 116 | TEST_F(Test, disconnect_last_on_fire2) { 117 | Source s; 118 | Consumer c; 119 | 120 | s.event().Connect(&c, &Consumer::OnTestDisconnectLast); 121 | s.event().Connect(&c, &Consumer::OnTestNothing); 122 | s.event().Connect(&c, &Consumer::OnTestNothing); 123 | 124 | s.DoTest(); 125 | ASSERT_TRUE(c.CountSignalBindings() == 2); 126 | } 127 | 128 | /* 129 | * 130 | */ 131 | TEST_F(Test, disconnect_all_on_fire1) { 132 | Source s; 133 | Consumer c; 134 | 135 | s.event().Connect(&c, &Consumer::OnTestDisconnectAll); 136 | s.event().Connect(&c, &Consumer::OnTestDisconnectAll); 137 | s.event().Connect(&c, &Consumer::OnTestNothing); 138 | s.event().Connect(&c, &Consumer::OnTestDisconnectAll); 139 | s.event().Connect(&c, &Consumer::OnTestDisconnectAll); 140 | 141 | s.DoTest(); 142 | ASSERT_TRUE(c.CountSignalBindings() == 1); 143 | } 144 | -------------------------------------------------------------------------------- /test/unit/disconnect_on_fire/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class Test: public testing::Test 10 | { 11 | public: 12 | Test (); 13 | virtual ~Test(); 14 | 15 | protected: 16 | virtual void SetUp() { } 17 | virtual void TearDown() { } 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /test/unit/disconnect_with_slot/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_disconnect_with_slot ${sources} ${headers}) 5 | target_link_libraries(test_disconnect_with_slot sigcxx gtest common) 6 | -------------------------------------------------------------------------------- /test/unit/disconnect_with_slot/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/disconnect_with_slot/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | 5 | using namespace sigcxx; 6 | 7 | Test::Test() 8 | : testing::Test() { 9 | } 10 | 11 | Test::~Test() { 12 | 13 | } 14 | 15 | class Consumer : public Trackable { 16 | public: 17 | 18 | enum Test { 19 | Undefined = 0, 20 | TestDisconnectMethod_End_1, 21 | TestDisconnectMethod_Start_1, 22 | TestDisconnectMethod_End_Count_5, 23 | TestDisconnectMethod_2_5, 24 | TestDisconnectMethod_Complex_1_2, 25 | TestDisconnectAllTest1 26 | }; 27 | 28 | Consumer() 29 | : test(0), done(false) {} 30 | 31 | virtual ~Consumer() {} 32 | 33 | void OnTestDisconnect1(SLOT slot); 34 | 35 | void OnTestDisconnect2(SLOT slot); 36 | 37 | template 38 | void unbind_all(void (T::*method)(ParamTypes...)) { 39 | UnbindAllSignalsTo(method); 40 | }; 41 | 42 | void unbind_all() { 43 | UnbindAllSignals(); 44 | } 45 | 46 | int test; 47 | 48 | bool done; 49 | 50 | }; 51 | 52 | Signal<> sig1; 53 | Consumer consumer; 54 | 55 | void Consumer::OnTestDisconnect1(SLOT slot) { 56 | switch (test) { 57 | case TestDisconnectMethod_End_1: { 58 | if (!done) { 59 | sig1.Disconnect(&consumer, &Consumer::OnTestDisconnect1); 60 | done = true; 61 | } 62 | break; 63 | } 64 | case TestDisconnectMethod_Start_1: { 65 | if (!done) { 66 | sig1.Disconnect(&consumer, &Consumer::OnTestDisconnect1, 0); 67 | done = true; 68 | } 69 | break; 70 | } 71 | case TestDisconnectMethod_End_Count_5: { 72 | if (!done) { 73 | sig1.Disconnect(&consumer, &Consumer::OnTestDisconnect1, -1, 5); 74 | done = true; 75 | } 76 | break; 77 | } 78 | case TestDisconnectMethod_2_5: { 79 | if (!done) { 80 | sig1.Disconnect(&consumer, &Consumer::OnTestDisconnect1, 2, 5); 81 | done = true; 82 | } 83 | break; 84 | } 85 | case TestDisconnectMethod_Complex_1_2: { 86 | if (!done) { 87 | sig1.Disconnect(&consumer, &Consumer::OnTestDisconnect1, 1, 2); 88 | done = true; 89 | } 90 | break; 91 | } 92 | case TestDisconnectAllTest1: { 93 | if (!done) { 94 | sig1.DisconnectAll(&consumer, &Consumer::OnTestDisconnect1); 95 | done = true; 96 | } 97 | break; 98 | } 99 | default: 100 | break; 101 | } 102 | } 103 | 104 | void Consumer::OnTestDisconnect2(SLOT slot) { 105 | // nothing 106 | } 107 | 108 | /* 109 | * 110 | */ 111 | TEST_F(Test, disconnect_1) { 112 | 113 | // 5 connection 114 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 115 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 116 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 117 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 118 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 119 | 120 | consumer.test = Consumer::Test::TestDisconnectMethod_End_1; 121 | 122 | sig1.Emit(); 123 | 124 | ASSERT_TRUE(sig1.CountConnections() == 4 && consumer.CountSignalBindings() == 4); 125 | } 126 | 127 | TEST_F(Test, disconnect_2) { 128 | 129 | sig1.DisconnectAll(); 130 | consumer.unbind_all(); 131 | consumer.done = false; 132 | 133 | // 5 connection 134 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 135 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 136 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 137 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 138 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 139 | 140 | consumer.test = Consumer::Test::TestDisconnectMethod_Start_1; 141 | 142 | sig1.Emit(); 143 | 144 | ASSERT_TRUE(sig1.CountConnections() == 4 && consumer.CountSignalBindings() == 4); 145 | } 146 | 147 | TEST_F(Test, disconnect_3) { 148 | 149 | sig1.DisconnectAll(); 150 | consumer.unbind_all(); 151 | consumer.done = false; 152 | 153 | // 5 connection 154 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 155 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 156 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 157 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 158 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 159 | 160 | consumer.test = Consumer::Test::TestDisconnectMethod_End_Count_5; 161 | 162 | sig1.Emit(); 163 | 164 | ASSERT_TRUE(sig1.CountConnections() == 0 && consumer.CountSignalBindings() == 0); 165 | } 166 | 167 | TEST_F(Test, disconnect_4) { 168 | 169 | sig1.DisconnectAll(); 170 | consumer.unbind_all(); 171 | consumer.done = false; 172 | 173 | // 5 connection 174 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 175 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 176 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 177 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 178 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 179 | 180 | consumer.test = Consumer::Test::TestDisconnectMethod_2_5; 181 | 182 | sig1.Emit(); 183 | 184 | ASSERT_TRUE(sig1.CountConnections() == 2 && consumer.CountSignalBindings() == 2); 185 | } 186 | 187 | TEST_F(Test, disconnect_5) { 188 | 189 | sig1.DisconnectAll(); 190 | consumer.unbind_all(); 191 | consumer.done = false; 192 | 193 | // 5 connection 194 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 195 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 196 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect2); 197 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 198 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect2); 199 | 200 | consumer.test = Consumer::Test::TestDisconnectMethod_Complex_1_2; 201 | 202 | sig1.Emit(); 203 | 204 | ASSERT_TRUE(sig1.CountConnections() == 3 && consumer.CountSignalBindings() == 3); 205 | } 206 | 207 | TEST_F(Test, disconnect_6) { 208 | 209 | sig1.DisconnectAll(); 210 | consumer.unbind_all(); 211 | consumer.done = false; 212 | 213 | // 5 connection 214 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 215 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 216 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect2); 217 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect1); 218 | sig1.Connect(&consumer, &Consumer::OnTestDisconnect2); 219 | 220 | consumer.test = Consumer::Test::TestDisconnectAllTest1; 221 | 222 | sig1.Emit(); 223 | 224 | ASSERT_TRUE(sig1.CountConnections() == 2 && consumer.CountSignalBindings() == 2); 225 | } 226 | -------------------------------------------------------------------------------- /test/unit/disconnect_with_slot/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class Test: public testing::Test 10 | { 11 | public: 12 | Test (); 13 | virtual ~Test(); 14 | 15 | protected: 16 | virtual void SetUp() { } 17 | virtual void TearDown() { } 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /test/unit/signal_base/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_signal_base ${sources} ${headers}) 5 | target_link_libraries(test_signal_base sigcxx gtest common) 6 | -------------------------------------------------------------------------------- /test/unit/signal_base/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/signal_base/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | using namespace sigcxx; 9 | 10 | Test::Test() 11 | : testing::Test() { 12 | } 13 | 14 | Test::~Test() { 15 | 16 | } 17 | 18 | class Source { 19 | public: 20 | 21 | Source() {} 22 | ~Source() {} 23 | 24 | void DoTest() { 25 | event_.Emit(this); 26 | } 27 | 28 | inline sigcxx::Signal &event() { 29 | return event_; 30 | } 31 | 32 | private: 33 | 34 | sigcxx::Signal event_; 35 | }; 36 | 37 | class Consumer : public sigcxx::Trackable { 38 | public: 39 | 40 | Consumer() {} 41 | 42 | virtual ~Consumer() {} 43 | 44 | void OnTestNothing(Source *sender, __SLOT__) { 45 | // do nothing... 46 | } 47 | 48 | }; 49 | 50 | TEST_F(Test, push_back1) { 51 | Consumer consumer; 52 | Signal signal; 53 | 54 | signal.Connect(&consumer, &Consumer::OnTestNothing); 55 | signal.Connect(&consumer, &Consumer::OnTestNothing); 56 | signal.Connect(&consumer, &Consumer::OnTestNothing); 57 | 58 | ASSERT_TRUE(consumer.CountSignalBindings() == 3 && signal.CountConnections() == 3); 59 | } 60 | 61 | //TEST_F(Test, copy_observer) 62 | //{ 63 | // Source s; 64 | // Consumer c1; 65 | // Consumer c2; 66 | // 67 | // s.signal_base().Connect(&c1, &Consumer::OnTestNothing); 68 | // 69 | // c2 = c1; 70 | // 71 | // ASSERT_TRUE(c1.CountConnections() == 1 && c2.CountConnections() == 0); 72 | //} 73 | -------------------------------------------------------------------------------- /test/unit/signal_base/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | class Test: public testing::Test 8 | { 9 | public: 10 | Test (); 11 | virtual ~Test(); 12 | 13 | protected: 14 | virtual void SetUp() { } 15 | virtual void TearDown() { } 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /test/unit/signal_check_connection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_signal_check_connection ${sources} ${headers}) 5 | target_link_libraries(test_signal_check_connection sigcxx gtest common) 6 | -------------------------------------------------------------------------------- /test/unit/signal_check_connection/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/signal_check_connection/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | using sigcxx::Slot; 11 | 12 | Test::Test() 13 | : testing::Test() { 14 | } 15 | 16 | Test::~Test() { 17 | 18 | } 19 | 20 | /* 21 | * 22 | */ 23 | TEST_F(Test, count_connections1) { 24 | Subject s; 25 | Observer o; 26 | 27 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 28 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 29 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 30 | 31 | ASSERT_TRUE(s.signal1().CountConnections() == 3); 32 | } 33 | 34 | /* 35 | * 36 | */ 37 | TEST_F(Test, IsConnectedTo1) { 38 | Subject s; 39 | Observer o; 40 | 41 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 42 | 43 | ASSERT_TRUE(s.signal1().IsConnectedTo(&o, &Observer::OnTest1IntegerParam)); 44 | } 45 | 46 | /* 47 | * 48 | */ 49 | TEST_F(Test, IsConnectedTo2) { 50 | Subject s1; 51 | sigcxx::Signal s2; 52 | 53 | s1.signal1().Connect(s2); 54 | 55 | ASSERT_TRUE(s1.signal1().IsConnectedTo(s2)); 56 | } 57 | 58 | /* 59 | * 60 | */ 61 | TEST_F(Test, IsConnectedTo3) { 62 | Subject s1; 63 | Subject s2; 64 | Subject s3; 65 | Subject s4; 66 | Subject s5; 67 | 68 | Observer o1; 69 | Observer o2; 70 | Observer o3; 71 | 72 | s1.signal1().Connect(&o1, &Observer::OnTest1IntegerParam); 73 | s2.signal1().Connect(&o1, &Observer::OnTest1IntegerParam); 74 | s3.signal1().Connect(&o1, &Observer::OnTest1IntegerParam); 75 | s4.signal1().Connect(&o1, &Observer::OnTest1IntegerParam); 76 | s5.signal1().Connect(&o1, &Observer::OnTest1IntegerParam); 77 | 78 | s1.signal1().Connect(&o2, &Observer::OnTest1IntegerParam); 79 | s2.signal1().Connect(&o2, &Observer::OnTest1IntegerParam); 80 | s3.signal1().Connect(&o2, &Observer::OnTest1IntegerParam); 81 | s4.signal1().Connect(&o2, &Observer::OnTest1IntegerParam); 82 | s5.signal1().Connect(&o2, &Observer::OnTest1IntegerParam); 83 | 84 | s1.signal1().Connect(&o3, &Observer::OnTest1IntegerParam); 85 | s2.signal1().Connect(&o3, &Observer::OnTest1IntegerParam); 86 | s3.signal1().Connect(&o3, &Observer::OnTest1IntegerParam); 87 | s4.signal1().Connect(&o3, &Observer::OnTest1IntegerParam); 88 | s5.signal1().Connect(&o3, &Observer::OnTest1IntegerParam); 89 | 90 | ASSERT_TRUE(s1.signal1().IsConnectedTo(&o1) && 91 | s2.signal1().IsConnectedTo(&o2) && 92 | s3.signal1().IsConnectedTo(&o3)); 93 | } 94 | -------------------------------------------------------------------------------- /test/unit/signal_check_connection/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class Test: public testing::Test 10 | { 11 | public: 12 | Test (); 13 | virtual ~Test(); 14 | 15 | protected: 16 | virtual void SetUp() { } 17 | virtual void TearDown() { } 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /test/unit/signal_connect/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_signal_connect ${sources} ${headers}) 5 | target_link_libraries(test_signal_connect sigcxx gtest common) 6 | -------------------------------------------------------------------------------- /test/unit/signal_connect/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/signal_connect/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | using sigcxx::Slot; 11 | 12 | Test::Test() 13 | : testing::Test() { 14 | } 15 | 16 | Test::~Test() { 17 | 18 | } 19 | 20 | /* 21 | * 22 | */ 23 | TEST_F(Test, connect_method_once) { 24 | Subject s; 25 | Observer o; 26 | 27 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 28 | 29 | ASSERT_TRUE((s.CountSignalBindings() == 0) && (s.signal1().CountConnections() == 1) && (o.CountSignalBindings() == 1)); 30 | } 31 | 32 | /* 33 | * 34 | */ 35 | TEST_F(Test, connect_method_4_times) { 36 | using namespace sigcxx; 37 | 38 | Subject s; 39 | Observer o; 40 | 41 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 42 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 43 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 44 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 45 | 46 | s.emit_signal1(1); // this should call 4 times 47 | 48 | ASSERT_TRUE(o.test1_count() == 4 && 49 | s.signal1().CountConnections() == 4 && 50 | o.CountSignalBindings() == 4); 51 | } 52 | 53 | /* 54 | * This testcase test the connectiong between events -- chain load 55 | */ 56 | TEST_F(Test, connect_event_once) { 57 | Subject s1; 58 | sigcxx::Signal s2; 59 | Observer o; 60 | 61 | s2.Connect(&o, &Observer::OnTest1IntegerParam); 62 | s1.signal1().Connect(s2); 63 | 64 | s1.emit_signal1(1); // cause chain signal_base 65 | 66 | ASSERT_TRUE((o.test1_count() == 1) && (s1.signal1().CountConnections() == 1) && (s2.CountSignalBindings() == 1) 67 | && (s2.CountConnections() == 1) && (o.CountSignalBindings() == 1)); 68 | } 69 | 70 | /* 71 | * Disconnect 1 72 | */ 73 | TEST_F(Test, disconnect_once) { 74 | Subject s; 75 | Observer c; 76 | 77 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 78 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 79 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 80 | 81 | s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, 0); 82 | s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, -1); 83 | 84 | s.emit_signal1(1); 85 | 86 | ASSERT_TRUE(c.test1_count() == 1); 87 | } 88 | 89 | TEST_F(Test, selfconsumer) { 90 | Subject s; 91 | 92 | s.signal1().Connect(&s, &Subject::OnTest1IntegerParam); 93 | 94 | s.emit_signal1(1); 95 | s.emit_signal1(2); 96 | 97 | ASSERT_TRUE(s.test1_count() == 2); 98 | } 99 | 100 | TEST_F(Test, event_chaining) { 101 | Subject s1; 102 | sigcxx::Signal s2; 103 | Observer c; 104 | 105 | s1.signal1().Connect(s2); 106 | s2.Connect(&c, &Observer::OnTest1IntegerParam); 107 | 108 | s1.emit_signal1(1); 109 | 110 | ASSERT_TRUE(c.CountSignalBindings() == 1 && c.test1_count() == 1); 111 | } 112 | 113 | TEST_F(Test, delete_when_called) { 114 | Subject s; 115 | Observer c1; 116 | Observer c2; 117 | Observer c3; 118 | Observer *obj = new Observer; 119 | 120 | s.signal0().Connect(&c1, &Observer::OnTest0); 121 | s.signal0().Connect(obj, &Observer::OnTestDestroy); 122 | s.signal0().Connect(&c2, &Observer::OnTest0); 123 | s.signal0().Connect(&c3, &Observer::OnTest0); 124 | 125 | s.emit_signal0(); 126 | 127 | ASSERT_TRUE((c1.test0_count() == 1) && 128 | (c2.test0_count() == 1) && 129 | (c3.test0_count() == 1) && 130 | (s.signal0().CountConnections() == 3)); 131 | } 132 | 133 | TEST_F(Test, delete_more_when_called) { 134 | Subject s; 135 | Observer c1; 136 | Observer c2; 137 | Observer c3; 138 | Observer *obj1 = new Observer; 139 | Observer *obj2 = new Observer; 140 | Observer *obj3 = new Observer; 141 | 142 | s.signal0().Connect(&c1, &Observer::OnTest0); 143 | s.signal0().Connect(obj1, &Observer::OnTestDestroy); 144 | s.signal0().Connect(&c2, &Observer::OnTest0); 145 | s.signal0().Connect(&c3, &Observer::OnTest0); 146 | s.signal0().Connect(obj2, &Observer::OnTestDestroy); 147 | s.signal0().Connect(obj3, &Observer::OnTestDestroy); 148 | 149 | s.emit_signal0(); 150 | 151 | ASSERT_TRUE((c1.test0_count() == 1) && 152 | (c2.test0_count() == 1) && 153 | (c3.test0_count() == 1) && 154 | (s.signal0().CountConnections() == 3)); 155 | } 156 | 157 | TEST_F(Test, count_event_connections) { 158 | Subject s1; 159 | sigcxx::Signal<> s2; 160 | Observer c; 161 | 162 | s1.signal0().Connect(s2); 163 | s1.signal0().Connect(&c, &Observer::OnTest0); 164 | s1.signal0().Connect(s2); 165 | 166 | ASSERT_TRUE( 167 | (s1.signal0().CountConnections(s2) == 2) && 168 | (s1.signal0().CountConnections(&c, &Observer::OnTest0) == 1) 169 | ); 170 | } 171 | -------------------------------------------------------------------------------- /test/unit/signal_connect/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class Test: public testing::Test 10 | { 11 | public: 12 | Test (); 13 | virtual ~Test(); 14 | 15 | protected: 16 | virtual void SetUp() { } 17 | virtual void TearDown() { } 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /test/unit/signal_delete_this/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_signal_delete_this ${sources} ${headers}) 5 | target_link_libraries(test_signal_delete_this sigcxx gtest common) 6 | -------------------------------------------------------------------------------- /test/unit/signal_delete_this/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/signal_delete_this/test.cpp: -------------------------------------------------------------------------------- 1 | #include "test.hpp" 2 | #include 3 | #include 4 | 5 | using namespace sigcxx; 6 | 7 | class Button { 8 | public: 9 | 10 | Button() {} 11 | 12 | ~Button() {} 13 | 14 | SignalRef<> clicked() { 15 | return clicked_; 16 | } 17 | 18 | Signal<> clicked_; 19 | }; 20 | 21 | class TitleBar : public Trackable { 22 | public: 23 | 24 | TitleBar() { 25 | button_.clicked().Connect(this, &TitleBar::OnClicked); 26 | } 27 | 28 | virtual ~TitleBar() {} 29 | 30 | void OnClicked(__SLOT__) { 31 | action_(1); 32 | } 33 | 34 | SignalRef action() { 35 | return action_; 36 | } 37 | 38 | Signal action_; 39 | 40 | Button button_; 41 | }; 42 | 43 | class Window : public Trackable { 44 | public: 45 | 46 | Window() { 47 | titlebar_.action().Connect(this, &Window::OnClose); 48 | } 49 | 50 | virtual ~Window() {} 51 | 52 | void OnClose(int i, __SLOT__) { 53 | // std::cout << "This object is deleted" << std::endl; 54 | delete this; 55 | } 56 | 57 | TitleBar titlebar_; 58 | }; 59 | 60 | Test::Test() 61 | : testing::Test() { 62 | } 63 | 64 | Test::~Test() { 65 | 66 | } 67 | 68 | /** 69 | * @brief This test case simulate a window with a title bar and close button 70 | */ 71 | TEST_F(Test, push_back1) { 72 | for (int i = 0; i < 10000; i++) { 73 | Window *win = new Window; 74 | win->titlebar_.button_.clicked_(); 75 | } 76 | 77 | // check the stdout and no segment fault 78 | ASSERT_TRUE(true); 79 | } 80 | -------------------------------------------------------------------------------- /test/unit/signal_delete_this/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | class Test: public testing::Test 8 | { 9 | public: 10 | Test (); 11 | virtual ~Test(); 12 | 13 | protected: 14 | virtual void SetUp() { } 15 | virtual void TearDown() { } 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /test/unit/signal_disconnect/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_signal_disconnect ${sources} ${headers}) 5 | target_link_libraries(test_signal_disconnect sigcxx gtest common) 6 | -------------------------------------------------------------------------------- /test/unit/signal_disconnect/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/signal_disconnect/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #include "test.hpp" 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | using sigcxx::Slot; 11 | 12 | Test::Test() 13 | : testing::Test() { 14 | } 15 | 16 | Test::~Test() { 17 | 18 | } 19 | 20 | /* 21 | * 22 | */ 23 | TEST_F(Test, Disconnect1) { 24 | Subject s1; 25 | Subject s2; 26 | Subject s3; 27 | Observer o; 28 | 29 | s1.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 30 | s2.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 31 | s3.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 32 | 33 | int count1 = s2.signal1().Disconnect(&o, &Observer::OnTest1IntegerParam); 34 | 35 | ASSERT_TRUE((o.CountSignalBindings() == 2) && 36 | (s1.signal1().CountConnections() == 1) && 37 | (s2.signal1().CountConnections() == 0) && 38 | (s3.signal1().CountConnections() == 1) && (count1 == 1)); 39 | } 40 | 41 | /* 42 | * Disconnect 2 43 | */ 44 | TEST_F(Test, Disconnect2) { 45 | Subject s; 46 | Observer c; 47 | 48 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 49 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 50 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 51 | 52 | int count1 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, 0); 53 | int count2 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, -1); 54 | 55 | s.emit_signal1(1); 56 | 57 | ASSERT_TRUE(c.test1_count() == 1 && count1 == 1 && count2 == 1); 58 | } 59 | 60 | /* 61 | * Disconnect 3 62 | */ 63 | TEST_F(Test, Disconnect3) { 64 | Subject s; 65 | Observer c; 66 | 67 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 68 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 69 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 70 | 71 | int count1 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, -1, 2); 72 | 73 | ASSERT_TRUE(c.CountSignalBindings() == 1 && count1 == 2); 74 | } 75 | 76 | /* 77 | * Disconnect 4 78 | */ 79 | TEST_F(Test, Disconnect4) { 80 | Subject s; 81 | Observer c; 82 | 83 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 84 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 85 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 86 | 87 | int count1 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, -1, 4); 88 | 89 | ASSERT_TRUE(c.CountSignalBindings() == 0 && count1 == 3); 90 | } 91 | 92 | /* 93 | * Disconnect 5 94 | */ 95 | TEST_F(Test, Disconnect5) { 96 | Subject s; 97 | Observer c; 98 | 99 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 100 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 101 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 102 | 103 | int count1 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, -1, -1); 104 | 105 | ASSERT_TRUE(c.CountSignalBindings() == 0 && count1 == 3); 106 | } 107 | 108 | /* 109 | * Disconnect 6 110 | */ 111 | TEST_F(Test, Disconnect6) { 112 | Subject s; 113 | Observer c; 114 | 115 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 116 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 117 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 118 | 119 | int count1 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, 0, 2); 120 | 121 | ASSERT_TRUE(c.CountSignalBindings() == 1 && count1 == 2); 122 | } 123 | 124 | /* 125 | * Disconnect 7 126 | */ 127 | TEST_F(Test, Disconnect7) { 128 | Subject s; 129 | Observer c; 130 | 131 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 132 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 133 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 134 | 135 | int count1 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, 2, 2); 136 | 137 | ASSERT_TRUE(c.CountSignalBindings() == 2 && count1 == 1); 138 | } 139 | 140 | /* 141 | * Disconnect 7 142 | */ 143 | TEST_F(Test, Disconnect8) { 144 | Subject s; 145 | Observer c; 146 | 147 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 148 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 149 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 150 | 151 | int count1 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, 0, 4); 152 | 153 | ASSERT_TRUE(c.CountSignalBindings() == 0 && count1 == 3); 154 | } 155 | 156 | /* 157 | * Disconnect 9 158 | */ 159 | TEST_F(Test, Disconnect9) { 160 | Subject s; 161 | Observer c; 162 | 163 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 164 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 165 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 166 | 167 | int count1 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, 0, -1); 168 | 169 | ASSERT_TRUE(c.CountSignalBindings() == 0 && count1 == 3); 170 | } 171 | 172 | /* 173 | * Disconnect 10 174 | */ 175 | TEST_F(Test, Disconnect10) { 176 | Subject s; 177 | Observer c; 178 | 179 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 180 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 181 | s.signal1().Connect(&c, &Observer::OnTest1IntegerParam); 182 | 183 | int count1 = s.signal1().Disconnect(&c, &Observer::OnTest1IntegerParam, -2, 2); 184 | 185 | ASSERT_TRUE(c.CountSignalBindings() == 1 && count1 == 2); 186 | } 187 | 188 | /* 189 | * 190 | */ 191 | TEST_F(Test, disconnect_all) { 192 | Subject s; 193 | Observer o; 194 | 195 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 196 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 197 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 198 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 199 | 200 | s.signal1().DisconnectAll(&o, &Observer::OnTest1IntegerParam); 201 | 202 | s.emit_signal1(1); 203 | 204 | ASSERT_TRUE(o.test1_count() == 0 && s.signal1().CountConnections() == 0 && o.CountSignalBindings() == 0); 205 | } 206 | 207 | /* 208 | * 209 | */ 210 | TEST_F(Test, disconnect_no_check_1) { 211 | Subject s; 212 | Observer o; 213 | 214 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 215 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 216 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 217 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 218 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 219 | 220 | s.signal1().Disconnect(-1, 2); 221 | 222 | ASSERT_TRUE(s.signal1().CountConnections() == 3 && o.CountSignalBindings() == 3); 223 | } 224 | 225 | /* 226 | * 227 | */ 228 | TEST_F(Test, disconnect_no_check_2) { 229 | Subject s; 230 | Observer o; 231 | 232 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 233 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 234 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 235 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 236 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 237 | 238 | s.signal1().Disconnect(0, 2); 239 | 240 | ASSERT_TRUE(s.signal1().CountConnections() == 3 && o.CountSignalBindings() == 3); 241 | } 242 | 243 | /* 244 | * 245 | */ 246 | TEST_F(Test, disconnect_no_check_3) { 247 | Subject s; 248 | Observer o; 249 | 250 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 251 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 252 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 253 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 254 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 255 | 256 | s.signal1().Disconnect(-1, 6); // by giving a very big counts, this is the same as DisconnectAll() 257 | 258 | ASSERT_TRUE(s.signal1().CountConnections() == 0 && o.CountSignalBindings() == 0); 259 | } 260 | 261 | /* 262 | * 263 | */ 264 | TEST_F(Test, disconnect_no_check_4) { 265 | Subject s; 266 | Observer o; 267 | 268 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 269 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 270 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 271 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 272 | s.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 273 | 274 | s.signal1().Disconnect(-1, -2); // by giving a negative of last parameter, this is the same as DisconnectAll() 275 | 276 | ASSERT_TRUE(s.signal1().CountConnections() == 0 && o.CountSignalBindings() == 0); 277 | } 278 | -------------------------------------------------------------------------------- /test/unit/signal_disconnect/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class Test: public testing::Test 10 | { 11 | public: 12 | Test (); 13 | virtual ~Test(); 14 | 15 | protected: 16 | virtual void SetUp() { } 17 | virtual void TearDown() { } 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /test/unit/signal_virtual/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_signal_virtual ${sources} ${headers}) 5 | target_link_libraries(test_signal_virtual sigcxx gtest) 6 | -------------------------------------------------------------------------------- /test/unit/signal_virtual/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/signal_virtual/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | 5 | Test::Test() 6 | : testing::Test() {} 7 | 8 | Test::~Test() {} 9 | 10 | /* 11 | * 12 | */ 13 | TEST_F(Test, connect_method_once) { 14 | Consumer *obj1 = new Consumer; 15 | SubConsumer *obj2 = new SubConsumer; 16 | 17 | sigcxx::Signal signal1; 18 | signal1.Connect(obj1, &Consumer::OnVirtualTest); 19 | 20 | sigcxx::Signal signal2; 21 | signal2.Connect(obj2, &SubConsumer::OnVirtualTest); // this signal_connect to the method in sub class 22 | 23 | sigcxx::Signal signal3; 24 | signal3.Connect(dynamic_cast(obj2), 25 | &Consumer::OnVirtualTest); // this still signal_connect to the method in sub class 26 | 27 | signal1.Emit(1); 28 | signal2.Emit(2); 29 | signal3.Emit(3); 30 | 31 | bool result = (obj1->virtualtest_count() == 1) && (obj2->virtualtest_count() == 2); 32 | 33 | delete obj1; 34 | delete obj2; 35 | 36 | ASSERT_TRUE(result); 37 | } 38 | 39 | TEST_F(Test, connect_to_pure_virtual_function) { 40 | sigcxx::Signal signal1; 41 | AbstractConsumer *obj1 = new Consumer; 42 | 43 | signal1.Connect(obj1, &AbstractConsumer::OnVirtualTest); 44 | 45 | signal1.Emit(1); 46 | 47 | size_t result = dynamic_cast(obj1)->virtualtest_count(); 48 | 49 | delete obj1; 50 | 51 | ASSERT_TRUE(result == 1); 52 | } 53 | -------------------------------------------------------------------------------- /test/unit/signal_virtual/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class Test: public testing::Test 10 | { 11 | public: 12 | Test (); 13 | virtual ~Test(); 14 | 15 | protected: 16 | virtual void SetUp() { } 17 | virtual void TearDown() { } 18 | }; 19 | 20 | class Source 21 | { 22 | public: 23 | 24 | Source () { } 25 | 26 | ~Source () { } 27 | 28 | void DoTest1 (int n) 29 | { 30 | event1_.Emit(n); 31 | } 32 | 33 | void DoTest2 (int n1, int n2) 34 | { 35 | event2_.Emit(n1, n2); 36 | } 37 | 38 | inline sigcxx::Signal& event1 () 39 | { 40 | return event1_; 41 | } 42 | 43 | inline sigcxx::Signal& event2 () 44 | { 45 | return event2_; 46 | } 47 | 48 | private: 49 | 50 | sigcxx::Signal event1_; 51 | sigcxx::Signal event2_; 52 | }; 53 | 54 | class AbstractConsumer: public sigcxx::Trackable 55 | { 56 | public: 57 | AbstractConsumer() {} 58 | virtual ~AbstractConsumer() {} 59 | 60 | virtual void OnVirtualTest (int, sigcxx::SLOT slot = nullptr) = 0; 61 | }; 62 | 63 | class Consumer: public AbstractConsumer 64 | { 65 | public: 66 | 67 | Consumer () 68 | : test1_count_(0), test2_count_(0), virtualtest_count_(0) 69 | { } 70 | 71 | virtual ~Consumer () { } 72 | 73 | void OnTest1 (int n, sigcxx::SLOT /* slot */) 74 | { 75 | test1_count_++; 76 | std::cout << "SignalT received in OnTest1, n " << n << ", " << test1_count_ << " times." << std::endl; 77 | } 78 | 79 | void OnTest2 (int n1, int n2, sigcxx::SLOT /* slot */) 80 | { 81 | test2_count_++; 82 | std::cout << "SignalT received in OnTest2, n1: " << n1 << " n2: " << n2 << ", " << test2_count_ << " times." 83 | << std::endl; 84 | } 85 | 86 | virtual void OnVirtualTest (int n, sigcxx::SLOT /* slot */) override 87 | { 88 | virtualtest_count_++; 89 | std::cout << "Virtual test in base class, param: " << n << ", " << virtualtest_count_ << " times." 90 | << std::endl; 91 | } 92 | 93 | inline size_t test1_count() const 94 | { 95 | return test1_count_; 96 | } 97 | 98 | inline size_t test2_count() const 99 | { 100 | return test2_count_; 101 | } 102 | 103 | inline size_t virtualtest_count() const 104 | { 105 | return virtualtest_count_; 106 | } 107 | 108 | protected: 109 | 110 | inline void set_virtualtest_count(size_t num) 111 | { 112 | virtualtest_count_ = num; 113 | } 114 | 115 | private: 116 | size_t test1_count_; 117 | size_t test2_count_; 118 | size_t virtualtest_count_; 119 | }; 120 | 121 | class SubConsumer: public Consumer 122 | { 123 | public: 124 | 125 | SubConsumer() {} 126 | 127 | virtual ~SubConsumer() {} 128 | 129 | virtual void OnVirtualTest (int n, sigcxx::SLOT /* slot */) override 130 | { 131 | set_virtualtest_count(virtualtest_count() + 1); 132 | std::cout << "Virtual test in sub class, param: " << n << ", " << virtualtest_count() << " times." 133 | << std::endl; 134 | } 135 | }; 136 | -------------------------------------------------------------------------------- /test/unit/thread_safe/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_thread_safe ${sources} ${headers}) 5 | target_link_libraries(test_thread_safe sigcxx gtest) 6 | -------------------------------------------------------------------------------- /test/unit/thread_safe/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/thread_safe/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | using sigcxx::SLOT; 9 | 10 | static std::mutex m; 11 | 12 | void Source::DoTest1(int n) 13 | { 14 | lock_guard lock(m); 15 | event1_.Emit(n); 16 | } 17 | 18 | void Source::DoTest2 (int n1, int n2) 19 | { 20 | lock_guard lock(m); 21 | event2_.Emit(n1, n2); 22 | } 23 | 24 | void Consumer::DisconnectAll() 25 | { 26 | lock_guard lock(m); 27 | UnbindAllSignals(); 28 | } 29 | 30 | Test::Test() 31 | : testing::Test() 32 | { 33 | } 34 | 35 | Test::~Test() 36 | { 37 | 38 | } 39 | 40 | Source s; 41 | Consumer c; 42 | 43 | void thread1 () { 44 | 45 | std::unique_lock lock(m, std::defer_lock); 46 | 47 | for(int i = 0; i < 100; i++) { 48 | 49 | lock.lock(); 50 | s.event1().Connect(&c, static_cast(&Consumer::OnTest1)); 51 | lock.unlock(); 52 | 53 | s.DoTest1(1); 54 | 55 | lock.lock(); 56 | s.event1().DisconnectAll(&c, static_cast(&Consumer::OnTest1)); 57 | lock.unlock(); 58 | 59 | //std::this_thread::sleep_for(std::chrono::milliseconds(100)); 60 | } 61 | } 62 | 63 | void thread2 () { 64 | 65 | std::unique_lock lock(m, std::defer_lock); 66 | 67 | for(int i = 0; i < 100; i++) { 68 | lock.lock(); 69 | s.event1().Connect(&c, static_cast(&Consumer::OnTest1)); 70 | lock.unlock(); 71 | 72 | s.DoTest1(1); 73 | 74 | lock.lock(); 75 | s.event1().DisconnectAll(&c, static_cast(&Consumer::OnTest1)); 76 | lock.unlock(); 77 | //std::this_thread::sleep_for(std::chrono::milliseconds(100)); 78 | } 79 | } 80 | 81 | void thread3 () { 82 | Consumer* lc = 0; 83 | 84 | std::unique_lock lock(m, std::defer_lock); 85 | 86 | for(int i = 0; i < 500; i++) { 87 | lc = new Consumer(); 88 | 89 | lock.lock(); 90 | s.event1().Connect(lc, static_cast(&Consumer::OnTest1)); 91 | lock.unlock(); 92 | 93 | s.DoTest1(3); 94 | 95 | lock.lock(); 96 | delete lc; 97 | lock.unlock(); 98 | } 99 | } 100 | 101 | void thread4 () { 102 | Source* ls = 0; 103 | 104 | std::unique_lock lock(m, std::defer_lock); 105 | 106 | for(int i = 0; i < 500; i++) { 107 | ls = new Source(); 108 | 109 | lock.lock(); 110 | ls->event1().Connect(&c, static_cast(&Consumer::OnTest1)); 111 | lock.unlock(); 112 | 113 | ls->DoTest1(3); 114 | 115 | lock.lock(); 116 | delete ls; 117 | lock.unlock(); 118 | 119 | } 120 | } 121 | 122 | /* 123 | * 124 | */ 125 | TEST_F(Test, connect_method_once) 126 | { 127 | thread t1 (thread1); 128 | thread t2 (thread2); 129 | 130 | t1.join(); 131 | t2.join(); 132 | 133 | ASSERT_TRUE(true); 134 | } 135 | 136 | TEST_F(Test, connect_consumer_in_threads) 137 | { 138 | thread t[100]; 139 | 140 | for(int i = 0; i < 100; i++) { 141 | t[i] = thread(thread3); 142 | } 143 | 144 | for(int i = 0; i < 100; i++) { 145 | t[i].join(); 146 | } 147 | 148 | ASSERT_TRUE(true); 149 | } 150 | 151 | /* 152 | * Test complex sinario in which there're a large mount connection and disconnection 153 | * 154 | * It will take a long time to complete, and the result is always true. 155 | * The purpose is to make sure there's no segment fault occurs. 156 | */ 157 | TEST_F(Test, complex) 158 | { 159 | thread ta[100]; 160 | thread tb[100]; 161 | thread tc[100]; 162 | thread td[100]; 163 | 164 | for(int i = 0; i < 100; i++) { 165 | ta[i] = thread(thread1); 166 | } 167 | for(int i = 0; i < 100; i++) { 168 | tb[i] = thread(thread2); 169 | } 170 | for(int i = 0; i < 100; i++) { 171 | tc[i] = thread(thread3); 172 | } 173 | for(int i = 0; i < 100; i++) { 174 | td[i] = thread(thread4); 175 | } 176 | 177 | for(int i = 0; i < 100; i++) { 178 | ta[i].join(); 179 | } 180 | for(int i = 0; i < 100; i++) { 181 | tb[i].join(); 182 | } 183 | for(int i = 0; i < 100; i++) { 184 | tc[i].join(); 185 | } 186 | for(int i = 0; i < 100; i++) { 187 | td[i].join(); 188 | } 189 | 190 | ASSERT_TRUE(true); 191 | } 192 | -------------------------------------------------------------------------------- /test/unit/thread_safe/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | using sigcxx::Slot; 10 | 11 | class Test: public testing::Test 12 | { 13 | public: 14 | Test (); 15 | virtual ~Test(); 16 | 17 | protected: 18 | virtual void SetUp() { } 19 | virtual void TearDown() { } 20 | }; 21 | 22 | class Source 23 | { 24 | public: 25 | 26 | Source () { } 27 | 28 | ~Source () { } 29 | 30 | void DoTest1 (int n); 31 | 32 | void DoTest2 (int n1, int n2); 33 | 34 | inline sigcxx::Signal& event1 () 35 | { 36 | return event1_; 37 | } 38 | 39 | inline sigcxx::Signal& event2 () 40 | { 41 | return event2_; 42 | } 43 | 44 | private: 45 | 46 | sigcxx::Signal event1_; 47 | sigcxx::Signal event2_; 48 | }; 49 | 50 | class Consumer: public sigcxx::Trackable 51 | { 52 | public: 53 | 54 | Consumer () 55 | : test1_count_(0), test2_count_(0) 56 | { } 57 | 58 | virtual ~Consumer () { } 59 | 60 | void DisconnectAll (); 61 | 62 | void OnTest1 (int n, Slot* slot = nullptr) 63 | { 64 | test1_count_++; 65 | //std::cout << "Signal received in OnTest1, n " << n << ", " << test1_count_ << " times." << std::endl; 66 | } 67 | 68 | void OnTest2 (int n1, int n2, Slot* slot = nullptr) 69 | { 70 | test2_count_++; 71 | //std::cout << "Signal received in OnTest2, n1: " << n1 << " n2: " << n2 << ", " << test2_count_ << " times." 72 | // << std::endl; 73 | } 74 | 75 | inline size_t test1_count() const 76 | { 77 | return test1_count_; 78 | } 79 | 80 | inline size_t test2_count() const 81 | { 82 | return test2_count_; 83 | } 84 | 85 | private: 86 | size_t test1_count_; 87 | size_t test2_count_; 88 | }; 89 | -------------------------------------------------------------------------------- /test/unit/trackable_unbind/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB sources "*.cpp") 2 | file(GLOB headers "*.hpp") 3 | 4 | add_executable(test_trackable_unbind ${sources} ${headers}) 5 | target_link_libraries(test_trackable_unbind sigcxx gtest common) 6 | -------------------------------------------------------------------------------- /test/unit/trackable_unbind/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | testing::InitGoogleTest(&argc, argv); 6 | 7 | return RUN_ALL_TESTS(); 8 | } 9 | -------------------------------------------------------------------------------- /test/unit/trackable_unbind/test.cpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::Connect 2 | 3 | #include "test.hpp" 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | using sigcxx::Slot; 11 | 12 | Test::Test() 13 | : testing::Test() { 14 | } 15 | 16 | Test::~Test() { 17 | 18 | } 19 | 20 | /* 21 | * 22 | */ 23 | TEST_F(Test, unbind_all1) { 24 | Subject s1; 25 | Subject s2; 26 | Observer o; 27 | 28 | s1.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 29 | s2.signal0().Connect(&o, &Observer::OnTest0); 30 | 31 | o.unbind_all(); 32 | 33 | ASSERT_TRUE((s1.signal1().CountConnections() == 0) && 34 | (s2.signal0().CountConnections() == 0) && 35 | (o.CountSignalBindings() == 0)); 36 | } 37 | 38 | /* 39 | * 40 | */ 41 | TEST_F(Test, unbind_all2) { 42 | Subject s1; 43 | Subject s2; 44 | Observer o; 45 | 46 | s1.signal1().Connect(&o, &Observer::OnTest1IntegerParam); 47 | s2.signal0().Connect(&o, &Observer::OnTest0); 48 | 49 | o.unbind_all(&Observer::OnTest1IntegerParam); 50 | 51 | ASSERT_TRUE((s1.signal1().CountConnections() == 0) && 52 | (s2.signal0().CountConnections() == 1) && 53 | (o.CountSignalBindings() == 1)); 54 | } 55 | 56 | TEST_F(Test, unbind_all3) { 57 | Subject s1; 58 | Subject s2; 59 | Observer o; 60 | 61 | s1.signal0().Connect(&o, &Observer::OnTest0); 62 | s1.signal0().Connect(&o, &Observer::OnTest0); 63 | s1.signal0().Connect(&o, &Observer::OnTest0); 64 | s1.signal0().Connect(&o, &Observer::OnTest0); 65 | 66 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 67 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 68 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 69 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 70 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 71 | 72 | o.unbind_all(&Observer::OnTestUnbindAllAt5); 73 | 74 | ASSERT_TRUE((o.CountSignalBindings() == 4) && 75 | (s1.signal0().CountConnections() == 4) && 76 | (s2.signal0().CountConnections() == 0)); 77 | } 78 | 79 | TEST_F(Test, unbind_all4) { 80 | Subject s1; 81 | Subject s2; 82 | Observer o; 83 | 84 | s1.signal0().Connect(&o, &Observer::OnTest0); 85 | s1.signal0().Connect(&o, &Observer::OnTest0); 86 | s1.signal0().Connect(&o, &Observer::OnTest0); 87 | s1.signal0().Connect(&o, &Observer::OnTest0); 88 | 89 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 90 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 91 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 92 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 93 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 94 | 95 | o.unbind_all(); 96 | 97 | ASSERT_TRUE((o.CountSignalBindings() == 0) && 98 | (s1.signal0().CountConnections() == 0) && 99 | (s2.signal0().CountConnections() == 0)); 100 | } 101 | 102 | TEST_F(Test, unbind_once) 103 | { 104 | Subject s; 105 | Observer o; 106 | 107 | s.signal0().Connect(&o, &Observer::OnTestUnbindOnceAt5); 108 | 109 | s.emit_signal0(); // 1 110 | ASSERT_TRUE((s.signal0().CountConnections() == 1) && (o.CountSignalBindings() == 1) && (o.test0_count() == 1)); 111 | 112 | s.emit_signal0(); // 2 113 | s.emit_signal0(); // 3 114 | s.emit_signal0(); // 4 115 | s.emit_signal0(); // 5 116 | 117 | ASSERT_TRUE((s.signal0().CountConnections() == 0) && (o.CountSignalBindings() == 0) && (o.test0_count() == 5)); 118 | 119 | s.emit_signal0(); // no connection 120 | 121 | ASSERT_TRUE((s.signal0().CountConnections() == 0) && (o.CountSignalBindings() == 0) && (o.test0_count() == 5)); 122 | } 123 | 124 | TEST_F(Test, unbind_all_in_callback1) { 125 | Subject s; 126 | Observer o; 127 | 128 | s.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 129 | s.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 130 | s.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 131 | s.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 132 | 133 | for (int i = 0; i < 6; i++) { 134 | s.emit_signal0(); 135 | } 136 | 137 | ASSERT_TRUE(o.CountSignalBindings() == 0); 138 | } 139 | 140 | TEST_F(Test, unbind_all_in_callback2) { 141 | Subject s1; 142 | Subject s2; 143 | Observer o; 144 | 145 | s1.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 146 | s1.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 147 | s1.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 148 | s1.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 149 | 150 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 151 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 152 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 153 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 154 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllAt5); 155 | 156 | for (int i = 0; i < 6; i++) { 157 | s1.emit_signal0(); 158 | } 159 | 160 | ASSERT_TRUE((o.CountSignalBindings() == 0) && 161 | (s1.signal0().CountConnections() == 0) && 162 | (s2.signal0().CountConnections() == 0)); 163 | } 164 | 165 | TEST_F(Test, unbind_all_method_in_callback) { 166 | Subject s1; 167 | Subject s2; 168 | Observer o; 169 | 170 | s1.signal0().Connect(&o, &Observer::OnTest0); 171 | s1.signal0().Connect(&o, &Observer::OnTest0); 172 | s1.signal0().Connect(&o, &Observer::OnTest0); 173 | s1.signal0().Connect(&o, &Observer::OnTest0); 174 | 175 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllMethodAt5); 176 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllMethodAt5); 177 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllMethodAt5); 178 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllMethodAt5); 179 | s2.signal0().Connect(&o, &Observer::OnTestUnbindAllMethodAt5); 180 | 181 | for (int i = 0; i < 6; i++) { 182 | s2.emit_signal0(); 183 | } 184 | 185 | ASSERT_TRUE((o.CountSignalBindings() == 4) && 186 | (s1.signal0().CountConnections() == 4) && 187 | (s2.signal0().CountConnections() == 0)); 188 | } 189 | -------------------------------------------------------------------------------- /test/unit/trackable_unbind/test.hpp: -------------------------------------------------------------------------------- 1 | // Unit test code for Event::connect 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class Test : public testing::Test { 10 | public: 11 | Test(); 12 | virtual ~Test(); 13 | 14 | protected: 15 | virtual void SetUp() {} 16 | virtual void TearDown() {} 17 | }; 18 | 19 | --------------------------------------------------------------------------------