mirror of
https://github.com/google/googletest.git
synced 2025-03-10 09:16:48 +00:00
Merge remote-tracking branch 'upstream/master' into primer_md_table_update
This commit is contained in:
commit
d64e4cf14e
@ -1,6 +1,6 @@
|
|||||||
## gMock Cheat Sheet
|
## gMock Cheat Sheet
|
||||||
|
|
||||||
<!-- GOOGLETEST_CM0018 DO NOT DELETE -->
|
<!-- GOOGLETEST_CM0019 DO NOT DELETE -->
|
||||||
|
|
||||||
### Defining a Mock Class
|
### Defining a Mock Class
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ and the default action will be taken each time.
|
|||||||
|
|
||||||
### Matchers {#MatcherList}
|
### Matchers {#MatcherList}
|
||||||
|
|
||||||
<!-- GOOGLETEST_CM0019 DO NOT DELETE -->
|
<!-- GOOGLETEST_CM0020 DO NOT DELETE -->
|
||||||
|
|
||||||
A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or
|
A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or
|
||||||
`EXPECT_CALL()`, or use it to validate a value directly:
|
`EXPECT_CALL()`, or use it to validate a value directly:
|
||||||
@ -341,65 +341,97 @@ write the elements in-line, match them more flexibly, or get more informative
|
|||||||
messages, you can use:
|
messages, you can use:
|
||||||
|
|
||||||
| Matcher | Description |
|
| Matcher | Description |
|
||||||
| :----------------------------------- | :----------------------------------- |
|
| :---------------------------------------- | :------------------------------- |
|
||||||
| `ContainerEq(container)` | The same as `Eq(container)` except |
|
| `BeginEndDistanceIs(m)` | `argument` is a container whose |
|
||||||
: : that the failure message also :
|
: : `begin()` and `end()` iterators :
|
||||||
: : includes which elements are in one :
|
: : are separated by a number of :
|
||||||
: : container but not the other. :
|
: : increments matching `m`. E.g. :
|
||||||
| `Contains(e)` | `argument` contains an element that |
|
: : `BeginEndDistanceIs(2)` or :
|
||||||
: : matches `e`, which can be either a :
|
: : `BeginEndDistanceIs(Lt(2))`. For :
|
||||||
: : value or a matcher. :
|
: : containers that define a :
|
||||||
|
: : `size()` method, `SizeIs(m)` may :
|
||||||
|
: : be more efficient. :
|
||||||
|
| `ContainerEq(container)` | The same as `Eq(container)` |
|
||||||
|
: : except that the failure message :
|
||||||
|
: : also includes which elements are :
|
||||||
|
: : in one container but not the :
|
||||||
|
: : other. :
|
||||||
|
| `Contains(e)` | `argument` contains an element |
|
||||||
|
: : that matches `e`, which can be :
|
||||||
|
: : either a value or a matcher. :
|
||||||
| `Each(e)` | `argument` is a container where |
|
| `Each(e)` | `argument` is a container where |
|
||||||
: : _every_ element matches `e`, which :
|
: : *every* element matches `e`, :
|
||||||
: : can be either a value or a matcher. :
|
: : which can be either a value or a :
|
||||||
|
: : matcher. :
|
||||||
| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, |
|
| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, |
|
||||||
: : where the i-th element matches `ei`, :
|
: : where the *i*-th element matches :
|
||||||
: : which can be a value or a matcher. 0 :
|
: : `ei`, which can be a value or a :
|
||||||
: : to 10 arguments are allowed. :
|
: : matcher. :
|
||||||
| `ElementsAreArray({ e0, e1, ..., en | The same as `ElementsAre()` except |
|
| `ElementsAreArray({e0, e1, ..., en})`, | The same as `ElementsAre()` |
|
||||||
: })`, `ElementsAreArray(array)`, or : that the expected element :
|
: `ElementsAreArray(a_container)`, : except that the expected element :
|
||||||
: `ElementsAreArray(array, count)` : values/matchers come from an :
|
: `ElementsAreArray(begin, end)`, : values/matchers come from an :
|
||||||
: : initializer list, STL-style :
|
: `ElementsAreArray(array)`, or : initializer list, STL-style :
|
||||||
: : container, or C-style array. :
|
: `ElementsAreArray(array, count)` : container, iterator range, or :
|
||||||
|
: : C-style array. :
|
||||||
| `IsEmpty()` | `argument` is an empty container |
|
| `IsEmpty()` | `argument` is an empty container |
|
||||||
: : (`container.empty()`). :
|
: : (`container.empty()`). :
|
||||||
| `Pointwise(m, container)` | `argument` contains the same number |
|
| `IsFalse()` | `argument` evaluates to `false` |
|
||||||
: : of elements as in `container`, and :
|
: : in a Boolean context. :
|
||||||
: : for all i, (the i-th element in :
|
| `IsSubsetOf({e0, e1, ..., en})`, | `argument` matches |
|
||||||
: : `argument`, the i-th element in :
|
: `IsSubsetOf(a_container)`, : `UnorderedElementsAre(x0, x1, :
|
||||||
: : `container`) match `m`, which is a :
|
: `IsSubsetOf(begin, end)`, : ..., xk)` for some subset `{x0, :
|
||||||
: : matcher on 2-tuples. E.g. :
|
: `IsSubsetOf(array)`, or : x1, ..., xk}` of the expected :
|
||||||
: : `Pointwise(Le(), upper_bounds)` :
|
: `IsSubsetOf(array, count)` : matchers. :
|
||||||
: : verifies that each element in :
|
| `IsSupersetOf({e0, e1, ..., en})`, | Some subset of `argument` |
|
||||||
: : `argument` doesn't exceed the :
|
: `IsSupersetOf(a_container)`, : matches :
|
||||||
: : corresponding element in :
|
: `IsSupersetOf(begin, end)`, : `UnorderedElementsAre(`expected :
|
||||||
: : `upper_bounds`. See more detail :
|
: `IsSupersetOf(array)`, or : matchers`)`. :
|
||||||
: : below. :
|
: `IsSupersetOf(array, count)` : :
|
||||||
| `SizeIs(m)` | `argument` is a container whose size |
|
| `IsTrue()` | `argument` evaluates to `true` |
|
||||||
: : matches `m`. E.g. `SizeIs(2)` or :
|
: : in a Boolean context. :
|
||||||
: : `SizeIs(Lt(2))`. :
|
| `Pointwise(m, container)`, `Pointwise(m, | `argument` contains the same |
|
||||||
| `UnorderedElementsAre(e0, e1, ..., | `argument` has `n + 1` elements, and |
|
: {e0, e1, ..., en})` : number of elements as in :
|
||||||
: en)` : under some permutation each element :
|
: : `container`, and for all i, (the :
|
||||||
|
: : i-th element in `argument`, the :
|
||||||
|
: : i-th element in `container`) :
|
||||||
|
: : match `m`, which is a matcher on :
|
||||||
|
: : 2-tuples. E.g. `Pointwise(Le(), :
|
||||||
|
: : upper_bounds)` verifies that :
|
||||||
|
: : each element in `argument` :
|
||||||
|
: : doesn't exceed the corresponding :
|
||||||
|
: : element in `upper_bounds`. See :
|
||||||
|
: : more detail below. :
|
||||||
|
| `SizeIs(m)` | `argument` is a container whose |
|
||||||
|
: : size matches `m`. E.g. :
|
||||||
|
: : `SizeIs(2)` or `SizeIs(Lt(2))`. :
|
||||||
|
| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, |
|
||||||
|
: : and under *some* permutation of :
|
||||||
|
: : the elements, each element :
|
||||||
: : matches an `ei` (for a different :
|
: : matches an `ei` (for a different :
|
||||||
: : `i`), which can be a value or a :
|
: : `i`), which can be a value or a :
|
||||||
: : matcher. 0 to 10 arguments are :
|
: : matcher. :
|
||||||
: : allowed. :
|
| `UnorderedElementsAreArray({e0, e1, ..., | The same as |
|
||||||
| `UnorderedElementsAreArray({ e0, e1, | The same as `UnorderedElementsAre()` |
|
: en})`, : `UnorderedElementsAre()` except :
|
||||||
: ..., en })`, : except that the expected element :
|
: `UnorderedElementsAreArray(a_container)`, : that the expected element :
|
||||||
: `UnorderedElementsAreArray(array)`, : values/matchers come from an :
|
: `UnorderedElementsAreArray(begin, end)`, : values/matchers come from an :
|
||||||
: or `UnorderedElementsAreArray(array, : initializer list, STL-style :
|
: `UnorderedElementsAreArray(array)`, or : initializer list, STL-style :
|
||||||
: count)` : container, or C-style array. :
|
: `UnorderedElementsAreArray(array, count)` : container, iterator range, or :
|
||||||
| `WhenSorted(m)` | When `argument` is sorted using the |
|
: : C-style array. :
|
||||||
: : `<` operator, it matches container :
|
| `UnorderedPointwise(m, container)`, | Like `Pointwise(m, container)`, |
|
||||||
: : matcher `m`. E.g. :
|
: `UnorderedPointwise(m, {e0, e1, ..., : but ignores the order of :
|
||||||
: : `WhenSorted(ElementsAre(1, 2, 3))` :
|
: en})` : elements. :
|
||||||
: : verifies that `argument` contains :
|
| `WhenSorted(m)` | When `argument` is sorted using |
|
||||||
: : elements `1`, `2`, and `3`, ignoring :
|
: : the `<` operator, it matches :
|
||||||
: : order. :
|
: : container matcher `m`. E.g. :
|
||||||
| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except |
|
: : `WhenSorted(ElementsAre(1, 2, :
|
||||||
: : that the given comparator instead of :
|
: : 3))` verifies that `argument` :
|
||||||
: : `<` is used to sort `argument`. E.g. :
|
: : contains elements 1, 2, and 3, :
|
||||||
: : `WhenSortedBy(std\:\:greater<int>(), :
|
: : ignoring order. :
|
||||||
|
| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, |
|
||||||
|
: : except that the given comparator :
|
||||||
|
: : instead of `<` is used to sort :
|
||||||
|
: : `argument`. E.g. :
|
||||||
|
: : `WhenSortedBy(std\:\:greater(), :
|
||||||
: : ElementsAre(3, 2, 1))`. :
|
: : ElementsAre(3, 2, 1))`. :
|
||||||
|
|
||||||
**Notes:**
|
**Notes:**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
## Googletest Mocking (gMock) Cookbook
|
## Googletest Mocking (gMock) Cookbook
|
||||||
|
|
||||||
<!-- GOOGLETEST_CM0011 DO NOT DELETE -->
|
<!-- GOOGLETEST_CM0012 DO NOT DELETE -->
|
||||||
|
|
||||||
You can find recipes for using gMock here. If you haven't yet, please read
|
You can find recipes for using gMock here. If you haven't yet, please read
|
||||||
[this](for_dummies.md) first to make sure you understand the basics.
|
[this](for_dummies.md) first to make sure you understand the basics.
|
||||||
@ -154,7 +154,7 @@ class MockStack : public StackInterface<Elem> {
|
|||||||
#### Mocking Non-virtual Methods {#MockingNonVirtualMethods}
|
#### Mocking Non-virtual Methods {#MockingNonVirtualMethods}
|
||||||
|
|
||||||
gMock can mock non-virtual functions to be used in Hi-perf dependency
|
gMock can mock non-virtual functions to be used in Hi-perf dependency
|
||||||
injection.<!-- GOOGLETEST_CM0016 DO NOT DELETE -->.
|
injection.<!-- GOOGLETEST_CM0017 DO NOT DELETE -->.
|
||||||
|
|
||||||
In this case, instead of sharing a common base class with the real class, your
|
In this case, instead of sharing a common base class with the real class, your
|
||||||
mock class will be *unrelated* to the real class, but contain methods with the
|
mock class will be *unrelated* to the real class, but contain methods with the
|
||||||
@ -1455,7 +1455,7 @@ mock object and gMock.
|
|||||||
|
|
||||||
#### Knowing When to Expect {#UseOnCall}
|
#### Knowing When to Expect {#UseOnCall}
|
||||||
|
|
||||||
<!-- GOOGLETEST_CM0017 DO NOT DELETE -->
|
<!-- GOOGLETEST_CM0018 DO NOT DELETE -->
|
||||||
|
|
||||||
**`ON_CALL`** is likely the *single most under-utilized construct* in gMock.
|
**`ON_CALL`** is likely the *single most under-utilized construct* in gMock.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
## Googletest Mocking (gMock) for Dummies {#GMockForDummies}
|
## Googletest Mocking (gMock) for Dummies {#GMockForDummies}
|
||||||
|
|
||||||
<!-- GOOGLETEST_CM0012 DO NOT DELETE -->
|
<!-- GOOGLETEST_CM0013 DO NOT DELETE -->
|
||||||
|
|
||||||
### What Is gMock?
|
### What Is gMock?
|
||||||
|
|
||||||
@ -499,7 +499,7 @@ always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)`
|
|||||||
will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will
|
will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will
|
||||||
return the same pointer every time. If you want the side effect to happen every
|
return the same pointer every time. If you want the side effect to happen every
|
||||||
time, you need to define a custom action, which we'll teach in the
|
time, you need to define a custom action, which we'll teach in the
|
||||||
[cook book](http://<!-- GOOGLETEST_CM0011 DO NOT DELETE -->).
|
[cook book](http://<!-- GOOGLETEST_CM0012 DO NOT DELETE -->).
|
||||||
|
|
||||||
Time for another quiz! What do you think the following means?
|
Time for another quiz! What do you think the following means?
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
## Legacy gMock FAQ {#GMockFaq}
|
## Legacy gMock FAQ {#GMockFaq}
|
||||||
|
|
||||||
<!-- GOOGLETEST_CM0020 DO NOT DELETE -->
|
<!-- GOOGLETEST_CM0021 DO NOT DELETE -->
|
||||||
|
|
||||||
### When I call a method on my mock object, the method for the real object is invoked instead. What's the problem?
|
### When I call a method on my mock object, the method for the real object is invoked instead. What's the problem?
|
||||||
|
|
||||||
|
@ -174,9 +174,9 @@ We list the most frequently used macros below. For a complete list, see file
|
|||||||
### Multi-threaded Tests
|
### Multi-threaded Tests
|
||||||
|
|
||||||
Google Test is thread-safe where the pthread library is available. After
|
Google Test is thread-safe where the pthread library is available. After
|
||||||
`#include "gtest/gtest.h"`, you can check the `GTEST_IS_THREADSAFE` macro to see
|
`#include "gtest/gtest.h"`, you can check the
|
||||||
whether this is the case (yes if the macro is `#defined` to 1, no if it's
|
`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
|
||||||
undefined.).
|
`#defined` to 1, no if it's undefined.).
|
||||||
|
|
||||||
If Google Test doesn't correctly detect whether pthread is available in your
|
If Google Test doesn't correctly detect whether pthread is available in your
|
||||||
environment, you can force it with
|
environment, you can force it with
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Advanced googletest Topics
|
# Advanced googletest Topics
|
||||||
|
|
||||||
<!-- GOOGLETEST_CM0015 DO NOT DELETE -->
|
<!-- GOOGLETEST_CM0016 DO NOT DELETE -->
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
@ -385,7 +385,7 @@ using ::testing::StartsWith;
|
|||||||
```
|
```
|
||||||
|
|
||||||
Read this
|
Read this
|
||||||
[recipe](https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#using-matchers-in-googletest-assertions)
|
[recipe](../../googlemock/docs/cook_book.md#using-matchers-in-googletest-assertions)
|
||||||
in the gMock Cookbook for more details.
|
in the gMock Cookbook for more details.
|
||||||
|
|
||||||
gMock has a rich set of matchers. You can do many things googletest cannot do
|
gMock has a rich set of matchers. You can do many things googletest cannot do
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Googletest FAQ
|
# Googletest FAQ
|
||||||
|
|
||||||
<!-- GOOGLETEST_CM0013 DO NOT DELETE -->
|
<!-- GOOGLETEST_CM0014 DO NOT DELETE -->
|
||||||
|
|
||||||
## Why should test suite names and test names not contain underscore?
|
## Why should test suite names and test names not contain underscore?
|
||||||
|
|
||||||
@ -332,7 +332,7 @@ You may still want to use `SetUp()/TearDown()` in the following cases:
|
|||||||
* In the body of a constructor (or destructor), it's not possible to use the
|
* In the body of a constructor (or destructor), it's not possible to use the
|
||||||
`ASSERT_xx` macros. Therefore, if the set-up operation could cause a fatal
|
`ASSERT_xx` macros. Therefore, if the set-up operation could cause a fatal
|
||||||
test failure that should prevent the test from running, it's necessary to
|
test failure that should prevent the test from running, it's necessary to
|
||||||
use `abort` <!-- GOOGLETEST_CM0014 DO NOT DELETE --> and abort the whole test executable,
|
use `abort` <!-- GOOGLETEST_CM0015 DO NOT DELETE --> and abort the whole test executable,
|
||||||
or to use `SetUp()` instead of a constructor.
|
or to use `SetUp()` instead of a constructor.
|
||||||
* If the tear-down operation could throw an exception, you must use
|
* If the tear-down operation could throw an exception, you must use
|
||||||
`TearDown()` as opposed to the destructor, as throwing in a destructor leads
|
`TearDown()` as opposed to the destructor, as throwing in a destructor leads
|
||||||
|
@ -1,25 +1,24 @@
|
|||||||
## Using GoogleTest from various build systems ##
|
## Using GoogleTest from various build systems
|
||||||
|
|
||||||
GoogleTest comes with pkg-config files that can be used to determine all
|
GoogleTest comes with pkg-config files that can be used to determine all
|
||||||
necessary flags for compiling and linking to GoogleTest (and GoogleMock).
|
necessary flags for compiling and linking to GoogleTest (and GoogleMock).
|
||||||
Pkg-config is a standardised plain-text format containing
|
Pkg-config is a standardised plain-text format containing
|
||||||
|
|
||||||
* the includedir (-I) path
|
* the includedir (-I) path
|
||||||
* necessary macro (-D) definitions
|
* necessary macro (-D) definitions
|
||||||
* further required flags (-pthread)
|
* further required flags (-pthread)
|
||||||
* the library (-L) path
|
* the library (-L) path
|
||||||
* the library (-l) to link to
|
* the library (-l) to link to
|
||||||
|
|
||||||
All current build systems support pkg-config in one way or another. For
|
All current build systems support pkg-config in one way or another. For all
|
||||||
all examples here we assume you want to compile the sample
|
examples here we assume you want to compile the sample
|
||||||
`samples/sample3_unittest.cc`.
|
`samples/sample3_unittest.cc`.
|
||||||
|
|
||||||
|
### CMake
|
||||||
### CMake ###
|
|
||||||
|
|
||||||
Using `pkg-config` in CMake is fairly easy:
|
Using `pkg-config` in CMake is fairly easy:
|
||||||
|
|
||||||
``` cmake
|
```cmake
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
cmake_policy(SET CMP0048 NEW)
|
cmake_policy(SET CMP0048 NEW)
|
||||||
@ -43,11 +42,10 @@ that all libraries have been compiled with threading enabled. In addition,
|
|||||||
GoogleTest might also require `-pthread` in the compiling step, and as such
|
GoogleTest might also require `-pthread` in the compiling step, and as such
|
||||||
splitting the pkg-config `Cflags` variable into include dirs and macros for
|
splitting the pkg-config `Cflags` variable into include dirs and macros for
|
||||||
`target_compile_definitions()` might still miss this). The same recommendation
|
`target_compile_definitions()` might still miss this). The same recommendation
|
||||||
goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which
|
goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which happens
|
||||||
happens to discard `-L` flags and `-pthread`.
|
to discard `-L` flags and `-pthread`.
|
||||||
|
|
||||||
|
### Autotools
|
||||||
### Autotools ###
|
|
||||||
|
|
||||||
Finding GoogleTest in Autoconf and using it from Automake is also fairly easy:
|
Finding GoogleTest in Autoconf and using it from Automake is also fairly easy:
|
||||||
|
|
||||||
@ -77,8 +75,7 @@ testapp_CXXFLAGS = $(GTEST_CFLAGS)
|
|||||||
testapp_LDADD = $(GTEST_LIBS)
|
testapp_LDADD = $(GTEST_LIBS)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Meson
|
||||||
### Meson ###
|
|
||||||
|
|
||||||
Meson natively uses pkgconfig to query dependencies:
|
Meson natively uses pkgconfig to query dependencies:
|
||||||
|
|
||||||
@ -96,13 +93,12 @@ testapp = executable(
|
|||||||
test('first_and_only_test', testapp)
|
test('first_and_only_test', testapp)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Plain Makefiles
|
||||||
|
|
||||||
### Plain Makefiles ###
|
Since `pkg-config` is a small Unix command-line utility, it can be used in
|
||||||
|
handwritten `Makefile`s too:
|
||||||
|
|
||||||
Since `pkg-config` is a small Unix command-line utility, it can be used
|
```Makefile
|
||||||
in handwritten `Makefile`s too:
|
|
||||||
|
|
||||||
``` Makefile
|
|
||||||
GTEST_CFLAGS = `pkg-config --cflags gtest_main`
|
GTEST_CFLAGS = `pkg-config --cflags gtest_main`
|
||||||
GTEST_LIBS = `pkg-config --libs gtest_main`
|
GTEST_LIBS = `pkg-config --libs gtest_main`
|
||||||
|
|
||||||
@ -120,12 +116,11 @@ testapp.o: samples/sample3_unittest.cc
|
|||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -c -o $@ $(GTEST_CFLAGS)
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -c -o $@ $(GTEST_CFLAGS)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Help! pkg-config can't find GoogleTest!
|
||||||
### Help! pkg-config can't find GoogleTest! ###
|
|
||||||
|
|
||||||
Let's say you have a `CMakeLists.txt` along the lines of the one in this
|
Let's say you have a `CMakeLists.txt` along the lines of the one in this
|
||||||
tutorial and you try to run `cmake`. It is very possible that you get a
|
tutorial and you try to run `cmake`. It is very possible that you get a failure
|
||||||
failure along the lines of:
|
along the lines of:
|
||||||
|
|
||||||
```
|
```
|
||||||
-- Checking for one of the modules 'gtest_main'
|
-- Checking for one of the modules 'gtest_main'
|
||||||
@ -135,9 +130,9 @@ CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:640 (message):
|
|||||||
|
|
||||||
These failures are common if you installed GoogleTest yourself and have not
|
These failures are common if you installed GoogleTest yourself and have not
|
||||||
sourced it from a distro or other package manager. If so, you need to tell
|
sourced it from a distro or other package manager. If so, you need to tell
|
||||||
pkg-config where it can find the `.pc` files containing the information.
|
pkg-config where it can find the `.pc` files containing the information. Say you
|
||||||
Say you installed GoogleTest to `/usr/local`, then it might be that the
|
installed GoogleTest to `/usr/local`, then it might be that the `.pc` files are
|
||||||
`.pc` files are installed under `/usr/local/lib64/pkgconfig`. If you set
|
installed under `/usr/local/lib64/pkgconfig`. If you set
|
||||||
|
|
||||||
```
|
```
|
||||||
export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig
|
export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig
|
||||||
|
@ -164,7 +164,7 @@ you'll get a compiler error. We used to require the arguments to support the
|
|||||||
`<<` is supported, it will be called to print the arguments when the assertion
|
`<<` is supported, it will be called to print the arguments when the assertion
|
||||||
fails; otherwise googletest will attempt to print them in the best way it can.
|
fails; otherwise googletest will attempt to print them in the best way it can.
|
||||||
For more details and how to customize the printing of the arguments, see
|
For more details and how to customize the printing of the arguments, see
|
||||||
[documentation](https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#teaching-gmock-how-to-print-your-values)
|
[documentation](../../googlemock/docs/cook_book.md#teaching-gmock-how-to-print-your-values)
|
||||||
|
|
||||||
These assertions can work with a user-defined type, but only if you define the
|
These assertions can work with a user-defined type, but only if you define the
|
||||||
corresponding comparison operator (e.g. `==`, `<`, etc). Since this is
|
corresponding comparison operator (e.g. `==`, `<`, etc). Since this is
|
||||||
|
@ -1,52 +1,51 @@
|
|||||||
|
|
||||||
|
|
||||||
<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
|
<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
|
||||||
|
|
||||||
# The Problem #
|
# The Problem
|
||||||
|
|
||||||
Template and macro libraries often need to define many classes,
|
Template and macro libraries often need to define many classes, functions, or
|
||||||
functions, or macros that vary only (or almost only) in the number of
|
macros that vary only (or almost only) in the number of arguments they take.
|
||||||
arguments they take. It's a lot of repetitive, mechanical, and
|
It's a lot of repetitive, mechanical, and error-prone work.
|
||||||
error-prone work.
|
|
||||||
|
|
||||||
Variadic templates and variadic macros can alleviate the problem.
|
Variadic templates and variadic macros can alleviate the problem. However, while
|
||||||
However, while both are being considered by the C++ committee, neither
|
both are being considered by the C++ committee, neither is in the standard yet
|
||||||
is in the standard yet or widely supported by compilers. Thus they
|
or widely supported by compilers. Thus they are often not a good choice,
|
||||||
are often not a good choice, especially when your code needs to be
|
especially when your code needs to be portable. And their capabilities are still
|
||||||
portable. And their capabilities are still limited.
|
limited.
|
||||||
|
|
||||||
As a result, authors of such libraries often have to write scripts to
|
As a result, authors of such libraries often have to write scripts to generate
|
||||||
generate their implementation. However, our experience is that it's
|
their implementation. However, our experience is that it's tedious to write such
|
||||||
tedious to write such scripts, which tend to reflect the structure of
|
scripts, which tend to reflect the structure of the generated code poorly and
|
||||||
the generated code poorly and are often hard to read and edit. For
|
are often hard to read and edit. For example, a small change needed in the
|
||||||
example, a small change needed in the generated code may require some
|
generated code may require some non-intuitive, non-trivial changes in the
|
||||||
non-intuitive, non-trivial changes in the script. This is especially
|
script. This is especially painful when experimenting with the code.
|
||||||
painful when experimenting with the code.
|
|
||||||
|
|
||||||
# Our Solution #
|
# Our Solution
|
||||||
|
|
||||||
Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
|
Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
|
||||||
Programming, or Practical Utility for Meta Programming, whichever you
|
Programming, or Practical Utility for Meta Programming, whichever you prefer) is
|
||||||
prefer) is a simple meta-programming tool for C++. The idea is that a
|
a simple meta-programming tool for C++. The idea is that a programmer writes a
|
||||||
programmer writes a `foo.pump` file which contains C++ code plus meta
|
`foo.pump` file which contains C++ code plus meta code that manipulates the C++
|
||||||
code that manipulates the C++ code. The meta code can handle
|
code. The meta code can handle iterations over a range, nested iterations, local
|
||||||
iterations over a range, nested iterations, local meta variable
|
meta variable definitions, simple arithmetic, and conditional expressions. You
|
||||||
definitions, simple arithmetic, and conditional expressions. You can
|
can view it as a small Domain-Specific Language. The meta language is designed
|
||||||
view it as a small Domain-Specific Language. The meta language is
|
to be non-intrusive (s.t. it won't confuse Emacs' C++ mode, for example) and
|
||||||
designed to be non-intrusive (s.t. it won't confuse Emacs' C++ mode,
|
concise, making Pump code intuitive and easy to maintain.
|
||||||
for example) and concise, making Pump code intuitive and easy to
|
|
||||||
maintain.
|
|
||||||
|
|
||||||
## Highlights ##
|
## Highlights
|
||||||
|
|
||||||
* The implementation is in a single Python script and thus ultra portable: no build or installation is needed and it works cross platforms.
|
* The implementation is in a single Python script and thus ultra portable: no
|
||||||
* Pump tries to be smart with respect to [Google's style guide](https://github.com/google/styleguide): it breaks long lines (easy to have when they are generated) at acceptable places to fit within 80 columns and indent the continuation lines correctly.
|
build or installation is needed and it works cross platforms.
|
||||||
* The format is human-readable and more concise than XML.
|
* Pump tries to be smart with respect to
|
||||||
* The format works relatively well with Emacs' C++ mode.
|
[Google's style guide](https://github.com/google/styleguide): it breaks long
|
||||||
|
lines (easy to have when they are generated) at acceptable places to fit
|
||||||
|
within 80 columns and indent the continuation lines correctly.
|
||||||
|
* The format is human-readable and more concise than XML.
|
||||||
|
* The format works relatively well with Emacs' C++ mode.
|
||||||
|
|
||||||
## Examples ##
|
## Examples
|
||||||
|
|
||||||
The following Pump code (where meta keywords start with `$`, `[[` and `]]` are meta brackets, and `$$` starts a meta comment that ends with the line):
|
The following Pump code (where meta keywords start with `$`, `[[` and `]]` are
|
||||||
|
meta brackets, and `$$` starts a meta comment that ends with the line):
|
||||||
|
|
||||||
```
|
```
|
||||||
$var n = 3 $$ Defines a meta variable n.
|
$var n = 3 $$ Defines a meta variable n.
|
||||||
@ -71,7 +70,7 @@ $if i == 0 [[
|
|||||||
|
|
||||||
will be translated by the Pump compiler to:
|
will be translated by the Pump compiler to:
|
||||||
|
|
||||||
``` cpp
|
```cpp
|
||||||
// Foo0 does blah for 0-ary predicates.
|
// Foo0 does blah for 0-ary predicates.
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
class Foo0 {
|
class Foo0 {
|
||||||
@ -105,9 +104,10 @@ Func($for i + [[a$i]]);
|
|||||||
$$ The text between i and [[ is the separator between iterations.
|
$$ The text between i and [[ is the separator between iterations.
|
||||||
```
|
```
|
||||||
|
|
||||||
will generate one of the following lines (without the comments), depending on the value of `n`:
|
will generate one of the following lines (without the comments), depending on
|
||||||
|
the value of `n`:
|
||||||
|
|
||||||
``` cpp
|
```cpp
|
||||||
Func(); // If n is 0.
|
Func(); // If n is 0.
|
||||||
Func(a1); // If n is 1.
|
Func(a1); // If n is 1.
|
||||||
Func(a1 + a2); // If n is 2.
|
Func(a1 + a2); // If n is 2.
|
||||||
@ -115,32 +115,38 @@ Func(a1 + a2 + a3); // If n is 3.
|
|||||||
// And so on...
|
// And so on...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Constructs ##
|
## Constructs
|
||||||
|
|
||||||
We support the following meta programming constructs:
|
We support the following meta programming constructs:
|
||||||
|
|
||||||
| `$var id = exp` | Defines a named constant value. `$id` is valid util the end of the current meta lexical block. |
|
| `$var id = exp` | Defines a named constant value. `$id` is |
|
||||||
|:----------------|:-----------------------------------------------------------------------------------------------|
|
: : valid util the end of the current meta :
|
||||||
| `$range id exp..exp` | Sets the range of an iteration variable, which can be reused in multiple loops later. |
|
: : lexical block. :
|
||||||
| `$for id sep [[ code ]]` | Iteration. The range of `id` must have been defined earlier. `$id` is valid in `code`. |
|
| :------------------------------- | :--------------------------------------- |
|
||||||
|
| `$range id exp..exp` | Sets the range of an iteration variable, |
|
||||||
|
: : which can be reused in multiple loops :
|
||||||
|
: : later. :
|
||||||
|
| `$for id sep [[ code ]]` | Iteration. The range of `id` must have |
|
||||||
|
: : been defined earlier. `$id` is valid in :
|
||||||
|
: : `code`. :
|
||||||
| `$($)` | Generates a single `$` character. |
|
| `$($)` | Generates a single `$` character. |
|
||||||
| `$id` | Value of the named constant or iteration variable. |
|
| `$id` | Value of the named constant or iteration |
|
||||||
|
: : variable. :
|
||||||
| `$(exp)` | Value of the expression. |
|
| `$(exp)` | Value of the expression. |
|
||||||
| `$if exp [[ code ]] else_branch` | Conditional. |
|
| `$if exp [[ code ]] else_branch` | Conditional. |
|
||||||
| `[[ code ]]` | Meta lexical block. |
|
| `[[ code ]]` | Meta lexical block. |
|
||||||
| `cpp_code` | Raw C++ code. |
|
| `cpp_code` | Raw C++ code. |
|
||||||
| `$$ comment` | Meta comment. |
|
| `$$ comment` | Meta comment. |
|
||||||
|
|
||||||
**Note:** To give the user some freedom in formatting the Pump source
|
**Note:** To give the user some freedom in formatting the Pump source code, Pump
|
||||||
code, Pump ignores a new-line character if it's right after `$for foo`
|
ignores a new-line character if it's right after `$for foo` or next to `[[` or
|
||||||
or next to `[[` or `]]`. Without this rule you'll often be forced to write
|
`]]`. Without this rule you'll often be forced to write very long lines to get
|
||||||
very long lines to get the desired output. Therefore sometimes you may
|
the desired output. Therefore sometimes you may need to insert an extra new-line
|
||||||
need to insert an extra new-line in such places for a new-line to show
|
in such places for a new-line to show up in your output.
|
||||||
up in your output.
|
|
||||||
|
|
||||||
## Grammar ##
|
## Grammar
|
||||||
|
|
||||||
``` ebnf
|
```ebnf
|
||||||
code ::= atomic_code*
|
code ::= atomic_code*
|
||||||
atomic_code ::= $var id = exp
|
atomic_code ::= $var id = exp
|
||||||
| $var id = [[ code ]]
|
| $var id = [[ code ]]
|
||||||
@ -159,19 +165,26 @@ else_branch ::= $else [[ code ]]
|
|||||||
exp ::= simple_expression_in_Python_syntax
|
exp ::= simple_expression_in_Python_syntax
|
||||||
```
|
```
|
||||||
|
|
||||||
## Code ##
|
## Code
|
||||||
|
|
||||||
You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py). It is still
|
You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py).
|
||||||
very unpolished and lacks automated tests, although it has been
|
It is still very unpolished and lacks automated tests, although it has been
|
||||||
successfully used many times. If you find a chance to use it in your
|
successfully used many times. If you find a chance to use it in your project,
|
||||||
project, please let us know what you think! We also welcome help on
|
please let us know what you think! We also welcome help on improving Pump.
|
||||||
improving Pump.
|
|
||||||
|
|
||||||
## Real Examples ##
|
## Real Examples
|
||||||
|
|
||||||
You can find real-world applications of Pump in [Google Test](https://github.com/google/googletest/tree/master/googletest) and [Google Mock](https://github.com/google/googletest/tree/master/googlemock). The source file `foo.h.pump` generates `foo.h`.
|
You can find real-world applications of Pump in
|
||||||
|
[Google Test](https://github.com/google/googletest/tree/master/googletest) and
|
||||||
|
[Google Mock](https://github.com/google/googletest/tree/master/googlemock). The
|
||||||
|
source file `foo.h.pump` generates `foo.h`.
|
||||||
|
|
||||||
## Tips ##
|
## Tips
|
||||||
|
|
||||||
* If a meta variable is followed by a letter or digit, you can separate them using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper` generate `Foo1Helper` when `j` is 1.
|
* If a meta variable is followed by a letter or digit, you can separate them
|
||||||
* To avoid extra-long Pump source lines, you can break a line anywhere you want by inserting `[[]]` followed by a new line. Since any new-line character next to `[[` or `]]` is ignored, the generated code won't contain this new line.
|
using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper`
|
||||||
|
generate `Foo1Helper` when `j` is 1.
|
||||||
|
* To avoid extra-long Pump source lines, you can break a line anywhere you
|
||||||
|
want by inserting `[[]]` followed by a new line. Since any new-line
|
||||||
|
character next to `[[` or `]]` is ignored, the generated code won't contain
|
||||||
|
this new line.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user