Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
yaml-cpp
Commits
9583d1ab
Commit
9583d1ab
authored
Mar 22, 2014
by
Jesse Beder
Browse files
Merge gtest from core
parents
d63ec48c
db82302e
Changes
113
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
5163 additions
and
0 deletions
+5163
-0
test/gtest-1.7.0/samples/sample2.cc
test/gtest-1.7.0/samples/sample2.cc
+56
-0
test/gtest-1.7.0/samples/sample2.h
test/gtest-1.7.0/samples/sample2.h
+85
-0
test/gtest-1.7.0/samples/sample2_unittest.cc
test/gtest-1.7.0/samples/sample2_unittest.cc
+109
-0
test/gtest-1.7.0/samples/sample3-inl.h
test/gtest-1.7.0/samples/sample3-inl.h
+172
-0
test/gtest-1.7.0/samples/sample3_unittest.cc
test/gtest-1.7.0/samples/sample3_unittest.cc
+151
-0
test/gtest-1.7.0/samples/sample4.cc
test/gtest-1.7.0/samples/sample4.cc
+46
-0
test/gtest-1.7.0/samples/sample4.h
test/gtest-1.7.0/samples/sample4.h
+53
-0
test/gtest-1.7.0/samples/sample4_unittest.cc
test/gtest-1.7.0/samples/sample4_unittest.cc
+45
-0
test/gtest-1.7.0/samples/sample5_unittest.cc
test/gtest-1.7.0/samples/sample5_unittest.cc
+199
-0
test/gtest-1.7.0/samples/sample6_unittest.cc
test/gtest-1.7.0/samples/sample6_unittest.cc
+224
-0
test/gtest-1.7.0/samples/sample7_unittest.cc
test/gtest-1.7.0/samples/sample7_unittest.cc
+130
-0
test/gtest-1.7.0/samples/sample8_unittest.cc
test/gtest-1.7.0/samples/sample8_unittest.cc
+173
-0
test/gtest-1.7.0/samples/sample9_unittest.cc
test/gtest-1.7.0/samples/sample9_unittest.cc
+160
-0
test/gtest-1.7.0/scripts/fuse_gtest_files.py
test/gtest-1.7.0/scripts/fuse_gtest_files.py
+250
-0
test/gtest-1.7.0/scripts/gen_gtest_pred_impl.py
test/gtest-1.7.0/scripts/gen_gtest_pred_impl.py
+730
-0
test/gtest-1.7.0/scripts/gtest-config.in
test/gtest-1.7.0/scripts/gtest-config.in
+274
-0
test/gtest-1.7.0/scripts/pump.py
test/gtest-1.7.0/scripts/pump.py
+855
-0
test/gtest-1.7.0/scripts/test/Makefile
test/gtest-1.7.0/scripts/test/Makefile
+59
-0
test/gtest-1.7.0/src/gtest-all.cc
test/gtest-1.7.0/src/gtest-all.cc
+48
-0
test/gtest-1.7.0/src/gtest-death-test.cc
test/gtest-1.7.0/src/gtest-death-test.cc
+1344
-0
No files found.
Too many changes to show.
To preserve performance only
113 of 113+
files are displayed.
Plain diff
Email patch
test/gtest-1.7.0/samples/sample2.cc
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A sample program demonstrating using Google C++ testing framework.
//
// Author: wan@google.com (Zhanyong Wan)
#include "sample2.h"
#include <string.h>
// Clones a 0-terminated C string, allocating memory using new.
const
char
*
MyString
::
CloneCString
(
const
char
*
a_c_string
)
{
if
(
a_c_string
==
NULL
)
return
NULL
;
const
size_t
len
=
strlen
(
a_c_string
);
char
*
const
clone
=
new
char
[
len
+
1
];
memcpy
(
clone
,
a_c_string
,
len
+
1
);
return
clone
;
}
// Sets the 0-terminated C string this MyString object
// represents.
void
MyString
::
Set
(
const
char
*
a_c_string
)
{
// Makes sure this works when c_string == c_string_
const
char
*
const
temp
=
MyString
::
CloneCString
(
a_c_string
);
delete
[]
c_string_
;
c_string_
=
temp
;
}
test/gtest-1.7.0/samples/sample2.h
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A sample program demonstrating using Google C++ testing framework.
//
// Author: wan@google.com (Zhanyong Wan)
#ifndef GTEST_SAMPLES_SAMPLE2_H_
#define GTEST_SAMPLES_SAMPLE2_H_
#include <string.h>
// A simple string class.
class
MyString
{
private:
const
char
*
c_string_
;
const
MyString
&
operator
=
(
const
MyString
&
rhs
);
public:
// Clones a 0-terminated C string, allocating memory using new.
static
const
char
*
CloneCString
(
const
char
*
a_c_string
);
////////////////////////////////////////////////////////////
//
// C'tors
// The default c'tor constructs a NULL string.
MyString
()
:
c_string_
(
NULL
)
{}
// Constructs a MyString by cloning a 0-terminated C string.
explicit
MyString
(
const
char
*
a_c_string
)
:
c_string_
(
NULL
)
{
Set
(
a_c_string
);
}
// Copy c'tor
MyString
(
const
MyString
&
string
)
:
c_string_
(
NULL
)
{
Set
(
string
.
c_string_
);
}
////////////////////////////////////////////////////////////
//
// D'tor. MyString is intended to be a final class, so the d'tor
// doesn't need to be virtual.
~
MyString
()
{
delete
[]
c_string_
;
}
// Gets the 0-terminated C string this MyString object represents.
const
char
*
c_string
()
const
{
return
c_string_
;
}
size_t
Length
()
const
{
return
c_string_
==
NULL
?
0
:
strlen
(
c_string_
);
}
// Sets the 0-terminated C string this MyString object represents.
void
Set
(
const
char
*
c_string
);
};
#endif // GTEST_SAMPLES_SAMPLE2_H_
test/gtest-1.7.0/samples/sample2_unittest.cc
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A sample program demonstrating using Google C++ testing framework.
//
// Author: wan@google.com (Zhanyong Wan)
// This sample shows how to write a more complex unit test for a class
// that has multiple member functions.
//
// Usually, it's a good idea to have one test for each method in your
// class. You don't have to do that exactly, but it helps to keep
// your tests organized. You may also throw in additional tests as
// needed.
#include "sample2.h"
#include "gtest/gtest.h"
// In this example, we test the MyString class (a simple string).
// Tests the default c'tor.
TEST
(
MyString
,
DefaultConstructor
)
{
const
MyString
s
;
// Asserts that s.c_string() returns NULL.
//
// <TechnicalDetails>
//
// If we write NULL instead of
//
// static_cast<const char *>(NULL)
//
// in this assertion, it will generate a warning on gcc 3.4. The
// reason is that EXPECT_EQ needs to know the types of its
// arguments in order to print them when it fails. Since NULL is
// #defined as 0, the compiler will use the formatter function for
// int to print it. However, gcc thinks that NULL should be used as
// a pointer, not an int, and therefore complains.
//
// The root of the problem is C++'s lack of distinction between the
// integer number 0 and the null pointer constant. Unfortunately,
// we have to live with this fact.
//
// </TechnicalDetails>
EXPECT_STREQ
(
NULL
,
s
.
c_string
());
EXPECT_EQ
(
0u
,
s
.
Length
());
}
const
char
kHelloString
[]
=
"Hello, world!"
;
// Tests the c'tor that accepts a C string.
TEST
(
MyString
,
ConstructorFromCString
)
{
const
MyString
s
(
kHelloString
);
EXPECT_EQ
(
0
,
strcmp
(
s
.
c_string
(),
kHelloString
));
EXPECT_EQ
(
sizeof
(
kHelloString
)
/
sizeof
(
kHelloString
[
0
])
-
1
,
s
.
Length
());
}
// Tests the copy c'tor.
TEST
(
MyString
,
CopyConstructor
)
{
const
MyString
s1
(
kHelloString
);
const
MyString
s2
=
s1
;
EXPECT_EQ
(
0
,
strcmp
(
s2
.
c_string
(),
kHelloString
));
}
// Tests the Set method.
TEST
(
MyString
,
Set
)
{
MyString
s
;
s
.
Set
(
kHelloString
);
EXPECT_EQ
(
0
,
strcmp
(
s
.
c_string
(),
kHelloString
));
// Set should work when the input pointer is the same as the one
// already in the MyString object.
s
.
Set
(
s
.
c_string
());
EXPECT_EQ
(
0
,
strcmp
(
s
.
c_string
(),
kHelloString
));
// Can we set the MyString to NULL?
s
.
Set
(
NULL
);
EXPECT_STREQ
(
NULL
,
s
.
c_string
());
}
test/gtest-1.7.0/samples/sample3-inl.h
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A sample program demonstrating using Google C++ testing framework.
//
// Author: wan@google.com (Zhanyong Wan)
#ifndef GTEST_SAMPLES_SAMPLE3_INL_H_
#define GTEST_SAMPLES_SAMPLE3_INL_H_
#include <stddef.h>
// Queue is a simple queue implemented as a singled-linked list.
//
// The element type must support copy constructor.
template
<
typename
E
>
// E is the element type
class
Queue
;
// QueueNode is a node in a Queue, which consists of an element of
// type E and a pointer to the next node.
template
<
typename
E
>
// E is the element type
class
QueueNode
{
friend
class
Queue
<
E
>
;
public:
// Gets the element in this node.
const
E
&
element
()
const
{
return
element_
;
}
// Gets the next node in the queue.
QueueNode
*
next
()
{
return
next_
;
}
const
QueueNode
*
next
()
const
{
return
next_
;
}
private:
// Creates a node with a given element value. The next pointer is
// set to NULL.
explicit
QueueNode
(
const
E
&
an_element
)
:
element_
(
an_element
),
next_
(
NULL
)
{}
// We disable the default assignment operator and copy c'tor.
const
QueueNode
&
operator
=
(
const
QueueNode
&
);
QueueNode
(
const
QueueNode
&
);
E
element_
;
QueueNode
*
next_
;
};
template
<
typename
E
>
// E is the element type.
class
Queue
{
public:
// Creates an empty queue.
Queue
()
:
head_
(
NULL
),
last_
(
NULL
),
size_
(
0
)
{}
// D'tor. Clears the queue.
~
Queue
()
{
Clear
();
}
// Clears the queue.
void
Clear
()
{
if
(
size_
>
0
)
{
// 1. Deletes every node.
QueueNode
<
E
>*
node
=
head_
;
QueueNode
<
E
>*
next
=
node
->
next
();
for
(;
;)
{
delete
node
;
node
=
next
;
if
(
node
==
NULL
)
break
;
next
=
node
->
next
();
}
// 2. Resets the member variables.
head_
=
last_
=
NULL
;
size_
=
0
;
}
}
// Gets the number of elements.
size_t
Size
()
const
{
return
size_
;
}
// Gets the first element of the queue, or NULL if the queue is empty.
QueueNode
<
E
>*
Head
()
{
return
head_
;
}
const
QueueNode
<
E
>*
Head
()
const
{
return
head_
;
}
// Gets the last element of the queue, or NULL if the queue is empty.
QueueNode
<
E
>*
Last
()
{
return
last_
;
}
const
QueueNode
<
E
>*
Last
()
const
{
return
last_
;
}
// Adds an element to the end of the queue. A copy of the element is
// created using the copy constructor, and then stored in the queue.
// Changes made to the element in the queue doesn't affect the source
// object, and vice versa.
void
Enqueue
(
const
E
&
element
)
{
QueueNode
<
E
>*
new_node
=
new
QueueNode
<
E
>
(
element
);
if
(
size_
==
0
)
{
head_
=
last_
=
new_node
;
size_
=
1
;
}
else
{
last_
->
next_
=
new_node
;
last_
=
new_node
;
size_
++
;
}
}
// Removes the head of the queue and returns it. Returns NULL if
// the queue is empty.
E
*
Dequeue
()
{
if
(
size_
==
0
)
{
return
NULL
;
}
const
QueueNode
<
E
>*
const
old_head
=
head_
;
head_
=
head_
->
next_
;
size_
--
;
if
(
size_
==
0
)
{
last_
=
NULL
;
}
E
*
element
=
new
E
(
old_head
->
element
());
delete
old_head
;
return
element
;
}
// Applies a function/functor on each element of the queue, and
// returns the result in a new queue. The original queue is not
// affected.
template
<
typename
F
>
Queue
*
Map
(
F
function
)
const
{
Queue
*
new_queue
=
new
Queue
();
for
(
const
QueueNode
<
E
>*
node
=
head_
;
node
!=
NULL
;
node
=
node
->
next_
)
{
new_queue
->
Enqueue
(
function
(
node
->
element
()));
}
return
new_queue
;
}
private:
QueueNode
<
E
>*
head_
;
// The first node of the queue.
QueueNode
<
E
>*
last_
;
// The last node of the queue.
size_t
size_
;
// The number of elements in the queue.
// We disallow copying a queue.
Queue
(
const
Queue
&
);
const
Queue
&
operator
=
(
const
Queue
&
);
};
#endif // GTEST_SAMPLES_SAMPLE3_INL_H_
test/gtest-1.7.0/samples/sample3_unittest.cc
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A sample program demonstrating using Google C++ testing framework.
//
// Author: wan@google.com (Zhanyong Wan)
// In this example, we use a more advanced feature of Google Test called
// test fixture.
//
// A test fixture is a place to hold objects and functions shared by
// all tests in a test case. Using a test fixture avoids duplicating
// the test code necessary to initialize and cleanup those common
// objects for each test. It is also useful for defining sub-routines
// that your tests need to invoke a lot.
//
// <TechnicalDetails>
//
// The tests share the test fixture in the sense of code sharing, not
// data sharing. Each test is given its own fresh copy of the
// fixture. You cannot expect the data modified by one test to be
// passed on to another test, which is a bad idea.
//
// The reason for this design is that tests should be independent and
// repeatable. In particular, a test should not fail as the result of
// another test's failure. If one test depends on info produced by
// another test, then the two tests should really be one big test.
//
// The macros for indicating the success/failure of a test
// (EXPECT_TRUE, FAIL, etc) need to know what the current test is
// (when Google Test prints the test result, it tells you which test
// each failure belongs to). Technically, these macros invoke a
// member function of the Test class. Therefore, you cannot use them
// in a global function. That's why you should put test sub-routines
// in a test fixture.
//
// </TechnicalDetails>
#include "sample3-inl.h"
#include "gtest/gtest.h"
// To use a test fixture, derive a class from testing::Test.
class
QueueTest
:
public
testing
::
Test
{
protected:
// You should make the members protected s.t. they can be
// accessed from sub-classes.
// virtual void SetUp() will be called before each test is run. You
// should define it if you need to initialize the varaibles.
// Otherwise, this can be skipped.
virtual
void
SetUp
()
{
q1_
.
Enqueue
(
1
);
q2_
.
Enqueue
(
2
);
q2_
.
Enqueue
(
3
);
}
// virtual void TearDown() will be called after each test is run.
// You should define it if there is cleanup work to do. Otherwise,
// you don't have to provide it.
//
// virtual void TearDown() {
// }
// A helper function that some test uses.
static
int
Double
(
int
n
)
{
return
2
*
n
;
}
// A helper function for testing Queue::Map().
void
MapTester
(
const
Queue
<
int
>
*
q
)
{
// Creates a new queue, where each element is twice as big as the
// corresponding one in q.
const
Queue
<
int
>
*
const
new_q
=
q
->
Map
(
Double
);
// Verifies that the new queue has the same size as q.
ASSERT_EQ
(
q
->
Size
(),
new_q
->
Size
());
// Verifies the relationship between the elements of the two queues.
for
(
const
QueueNode
<
int
>
*
n1
=
q
->
Head
(),
*
n2
=
new_q
->
Head
();
n1
!=
NULL
;
n1
=
n1
->
next
(),
n2
=
n2
->
next
()
)
{
EXPECT_EQ
(
2
*
n1
->
element
(),
n2
->
element
());
}
delete
new_q
;
}
// Declares the variables your tests want to use.
Queue
<
int
>
q0_
;
Queue
<
int
>
q1_
;
Queue
<
int
>
q2_
;
};
// When you have a test fixture, you define a test using TEST_F
// instead of TEST.
// Tests the default c'tor.
TEST_F
(
QueueTest
,
DefaultConstructor
)
{
// You can access data in the test fixture here.
EXPECT_EQ
(
0u
,
q0_
.
Size
());
}
// Tests Dequeue().
TEST_F
(
QueueTest
,
Dequeue
)
{
int
*
n
=
q0_
.
Dequeue
();
EXPECT_TRUE
(
n
==
NULL
);
n
=
q1_
.
Dequeue
();
ASSERT_TRUE
(
n
!=
NULL
);
EXPECT_EQ
(
1
,
*
n
);
EXPECT_EQ
(
0u
,
q1_
.
Size
());
delete
n
;
n
=
q2_
.
Dequeue
();
ASSERT_TRUE
(
n
!=
NULL
);
EXPECT_EQ
(
2
,
*
n
);
EXPECT_EQ
(
1u
,
q2_
.
Size
());
delete
n
;
}
// Tests the Queue::Map() function.
TEST_F
(
QueueTest
,
Map
)
{
MapTester
(
&
q0_
);
MapTester
(
&
q1_
);
MapTester
(
&
q2_
);
}
test/gtest-1.7.0/samples/sample4.cc
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A sample program demonstrating using Google C++ testing framework.
//
// Author: wan@google.com (Zhanyong Wan)
#include <stdio.h>
#include "sample4.h"
// Returns the current counter value, and increments it.
int
Counter
::
Increment
()
{
return
counter_
++
;
}
// Prints the current counter value to STDOUT.
void
Counter
::
Print
()
const
{
printf
(
"%d"
,
counter_
);
}
test/gtest-1.7.0/samples/sample4.h
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A sample program demonstrating using Google C++ testing framework.
//
// Author: wan@google.com (Zhanyong Wan)
#ifndef GTEST_SAMPLES_SAMPLE4_H_
#define GTEST_SAMPLES_SAMPLE4_H_
// A simple monotonic counter.
class
Counter
{
private:
int
counter_
;
public:
// Creates a counter that starts at 0.
Counter
()
:
counter_
(
0
)
{}
// Returns the current counter value, and increments it.
int
Increment
();
// Prints the current counter value to STDOUT.
void
Print
()
const
;
};
#endif // GTEST_SAMPLES_SAMPLE4_H_
test/gtest-1.7.0/samples/sample4_unittest.cc
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
#include "gtest/gtest.h"
#include "sample4.h"
// Tests the Increment() method.
TEST
(
Counter
,
Increment
)
{
Counter
c
;
// EXPECT_EQ() evaluates its arguments exactly once, so they
// can have side effects.
EXPECT_EQ
(
0
,
c
.
Increment
());
EXPECT_EQ
(
1
,
c
.
Increment
());
EXPECT_EQ
(
2
,
c
.
Increment
());
}
test/gtest-1.7.0/samples/sample5_unittest.cc
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// This sample teaches how to reuse a test fixture in multiple test
// cases by deriving sub-fixtures from it.
//
// When you define a test fixture, you specify the name of the test
// case that will use this fixture. Therefore, a test fixture can
// be used by only one test case.
//
// Sometimes, more than one test cases may want to use the same or
// slightly different test fixtures. For example, you may want to
// make sure that all tests for a GUI library don't leak important
// system resources like fonts and brushes. In Google Test, you do
// this by putting the shared logic in a super (as in "super class")
// test fixture, and then have each test case use a fixture derived
// from this super fixture.
#include <limits.h>
#include <time.h>
#include "sample3-inl.h"
#include "gtest/gtest.h"
#include "sample1.h"
// In this sample, we want to ensure that every test finishes within
// ~5 seconds. If a test takes longer to run, we consider it a
// failure.
//
// We put the code for timing a test in a test fixture called
// "QuickTest". QuickTest is intended to be the super fixture that
// other fixtures derive from, therefore there is no test case with
// the name "QuickTest". This is OK.
//
// Later, we will derive multiple test fixtures from QuickTest.
class
QuickTest
:
public
testing
::
Test
{
protected:
// Remember that SetUp() is run immediately before a test starts.
// This is a good place to record the start time.
virtual
void
SetUp
()
{
start_time_
=
time
(
NULL
);
}
// TearDown() is invoked immediately after a test finishes. Here we
// check if the test was too slow.
virtual
void
TearDown
()
{
// Gets the time when the test finishes
const
time_t
end_time
=
time
(
NULL
);
// Asserts that the test took no more than ~5 seconds. Did you
// know that you can use assertions in SetUp() and TearDown() as
// well?
EXPECT_TRUE
(
end_time
-
start_time_
<=
5
)
<<
"The test took too long."
;
}
// The UTC time (in seconds) when the test starts
time_t
start_time_
;
};
// We derive a fixture named IntegerFunctionTest from the QuickTest
// fixture. All tests using this fixture will be automatically
// required to be quick.
class
IntegerFunctionTest
:
public
QuickTest
{
// We don't need any more logic than already in the QuickTest fixture.
// Therefore the body is empty.
};
// Now we can write tests in the IntegerFunctionTest test case.
// Tests Factorial()
TEST_F
(
IntegerFunctionTest
,
Factorial
)
{
// Tests factorial of negative numbers.
EXPECT_EQ
(
1
,
Factorial
(
-
5
));
EXPECT_EQ
(
1
,
Factorial
(
-
1
));
EXPECT_GT
(
Factorial
(
-
10
),
0
);
// Tests factorial of 0.
EXPECT_EQ
(
1
,
Factorial
(
0
));
// Tests factorial of positive numbers.
EXPECT_EQ
(
1
,
Factorial
(
1
));
EXPECT_EQ
(
2
,
Factorial
(
2
));
EXPECT_EQ
(
6
,
Factorial
(
3
));
EXPECT_EQ
(
40320
,
Factorial
(
8
));
}
// Tests IsPrime()
TEST_F
(
IntegerFunctionTest
,
IsPrime
)
{
// Tests negative input.
EXPECT_FALSE
(
IsPrime
(
-
1
));
EXPECT_FALSE
(
IsPrime
(
-
2
));
EXPECT_FALSE
(
IsPrime
(
INT_MIN
));
// Tests some trivial cases.
EXPECT_FALSE
(
IsPrime
(
0
));
EXPECT_FALSE
(
IsPrime
(
1
));
EXPECT_TRUE
(
IsPrime
(
2
));
EXPECT_TRUE
(
IsPrime
(
3
));
// Tests positive input.
EXPECT_FALSE
(
IsPrime
(
4
));
EXPECT_TRUE
(
IsPrime
(
5
));
EXPECT_FALSE
(
IsPrime
(
6
));
EXPECT_TRUE
(
IsPrime
(
23
));
}
// The next test case (named "QueueTest") also needs to be quick, so
// we derive another fixture from QuickTest.
//
// The QueueTest test fixture has some logic and shared objects in
// addition to what's in QuickTest already. We define the additional
// stuff inside the body of the test fixture, as usual.
class
QueueTest
:
public
QuickTest
{
protected:
virtual
void
SetUp
()
{
// First, we need to set up the super fixture (QuickTest).
QuickTest
::
SetUp
();
// Second, some additional setup for this fixture.
q1_
.
Enqueue
(
1
);
q2_
.
Enqueue
(
2
);
q2_
.
Enqueue
(
3
);
}
// By default, TearDown() inherits the behavior of
// QuickTest::TearDown(). As we have no additional cleaning work
// for QueueTest, we omit it here.
//
// virtual void TearDown() {
// QuickTest::TearDown();
// }
Queue
<
int
>
q0_
;
Queue
<
int
>
q1_
;
Queue
<
int
>
q2_
;
};
// Now, let's write tests using the QueueTest fixture.
// Tests the default constructor.
TEST_F
(
QueueTest
,
DefaultConstructor
)
{
EXPECT_EQ
(
0u
,
q0_
.
Size
());
}
// Tests Dequeue().
TEST_F
(
QueueTest
,
Dequeue
)
{
int
*
n
=
q0_
.
Dequeue
();
EXPECT_TRUE
(
n
==
NULL
);
n
=
q1_
.
Dequeue
();
EXPECT_TRUE
(
n
!=
NULL
);
EXPECT_EQ
(
1
,
*
n
);
EXPECT_EQ
(
0u
,
q1_
.
Size
());
delete
n
;
n
=
q2_
.
Dequeue
();
EXPECT_TRUE
(
n
!=
NULL
);
EXPECT_EQ
(
2
,
*
n
);
EXPECT_EQ
(
1u
,
q2_
.
Size
());
delete
n
;
}
// If necessary, you can derive further test fixtures from a derived
// fixture itself. For example, you can derive another fixture from
// QueueTest. Google Test imposes no limit on how deep the hierarchy
// can be. In practice, however, you probably don't want it to be too
// deep as to be confusing.
test/gtest-1.7.0/samples/sample6_unittest.cc
0 → 100644
View file @
9583d1ab
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// This sample shows how to test common properties of multiple
// implementations of the same interface (aka interface tests).
// The interface and its implementations are in this header.
#include "prime_tables.h"
#include "gtest/gtest.h"
// First, we define some factory functions for creating instances of
// the implementations. You may be able to skip this step if all your
// implementations can be constructed the same way.
template
<
class
T
>
PrimeTable
*
CreatePrimeTable
();
template
<
>
PrimeTable
*
CreatePrimeTable
<
OnTheFlyPrimeTable
>
()
{
return
new
OnTheFlyPrimeTable
;
}
template
<
>
PrimeTable
*
CreatePrimeTable
<
PreCalculatedPrimeTable
>
()
{
return
new
PreCalculatedPrimeTable
(
10000
);
}
// Then we define a test fixture class template.
template
<
class
T
>
class
PrimeTableTest
:
public
testing
::
Test
{
protected:
// The ctor calls the factory function to create a prime table
// implemented by T.
PrimeTableTest
()
:
table_
(
CreatePrimeTable
<
T
>
())
{}
virtual
~
PrimeTableTest
()
{
delete
table_
;
}
// Note that we test an implementation via the base interface
// instead of the actual implementation class. This is important
// for keeping the tests close to the real world scenario, where the
// implementation is invoked via the base interface. It avoids
// got-yas where the implementation class has a method that shadows
// a method with the same name (but slightly different argument
// types) in the base interface, for example.
PrimeTable
*
const
table_
;
};
#if GTEST_HAS_TYPED_TEST
using
testing
::
Types
;
// Google Test offers two ways for reusing tests for different types.
// The first is called "typed tests". You should use it if you
// already know *all* the types you are gonna exercise when you write
// the tests.
// To write a typed test case, first use
//
// TYPED_TEST_CASE(TestCaseName, TypeList);
//
// to declare it and specify the type parameters. As with TEST_F,
// TestCaseName must match the test fixture name.
// The list of types we want to test.
typedef
Types
<
OnTheFlyPrimeTable
,
PreCalculatedPrimeTable
>
Implementations
;
TYPED_TEST_CASE
(
PrimeTableTest
,
Implementations
);
// Then use TYPED_TEST(TestCaseName, TestName) to define a typed test,
// similar to TEST_F.
TYPED_TEST
(
PrimeTableTest
,
ReturnsFalseForNonPrimes
)
{
// Inside the test body, you can refer to the type parameter by
// TypeParam, and refer to the fixture class by TestFixture. We
// don't need them in this example.
// Since we are in the template world, C++ requires explicitly
// writing 'this->' when referring to members of the fixture class.
// This is something you have to learn to live with.
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
-
5
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
0
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
1
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
4
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
6
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
100
));
}
TYPED_TEST
(
PrimeTableTest
,
ReturnsTrueForPrimes
)
{
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
2
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
3
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
5
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
7
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
11
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
131
));
}
TYPED_TEST
(
PrimeTableTest
,
CanGetNextPrime
)
{
EXPECT_EQ
(
2
,
this
->
table_
->
GetNextPrime
(
0
));
EXPECT_EQ
(
3
,
this
->
table_
->
GetNextPrime
(
2
));
EXPECT_EQ
(
5
,
this
->
table_
->
GetNextPrime
(
3
));
EXPECT_EQ
(
7
,
this
->
table_
->
GetNextPrime
(
5
));
EXPECT_EQ
(
11
,
this
->
table_
->
GetNextPrime
(
7
));
EXPECT_EQ
(
131
,
this
->
table_
->
GetNextPrime
(
128
));
}
// That's it! Google Test will repeat each TYPED_TEST for each type
// in the type list specified in TYPED_TEST_CASE. Sit back and be
// happy that you don't have to define them multiple times.
#endif // GTEST_HAS_TYPED_TEST
#if GTEST_HAS_TYPED_TEST_P
using
testing
::
Types
;
// Sometimes, however, you don't yet know all the types that you want
// to test when you write the tests. For example, if you are the
// author of an interface and expect other people to implement it, you
// might want to write a set of tests to make sure each implementation
// conforms to some basic requirements, but you don't know what
// implementations will be written in the future.
//
// How can you write the tests without committing to the type
// parameters? That's what "type-parameterized tests" can do for you.
// It is a bit more involved than typed tests, but in return you get a
// test pattern that can be reused in many contexts, which is a big
// win. Here's how you do it:
// First, define a test fixture class template. Here we just reuse
// the PrimeTableTest fixture defined earlier:
template
<
class
T
>
class
PrimeTableTest2
:
public
PrimeTableTest
<
T
>
{
};
// Then, declare the test case. The argument is the name of the test
// fixture, and also the name of the test case (as usual). The _P
// suffix is for "parameterized" or "pattern".
TYPED_TEST_CASE_P
(
PrimeTableTest2
);
// Next, use TYPED_TEST_P(TestCaseName, TestName) to define a test,
// similar to what you do with TEST_F.
TYPED_TEST_P
(
PrimeTableTest2
,
ReturnsFalseForNonPrimes
)
{
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
-
5
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
0
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
1
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
4
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
6
));
EXPECT_FALSE
(
this
->
table_
->
IsPrime
(
100
));
}
TYPED_TEST_P
(
PrimeTableTest2
,
ReturnsTrueForPrimes
)
{
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
2
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
3
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
5
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
7
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
11
));
EXPECT_TRUE
(
this
->
table_
->
IsPrime
(
131
));
}
TYPED_TEST_P
(
PrimeTableTest2
,
CanGetNextPrime
)
{
EXPECT_EQ
(
2
,
this
->
table_
->
GetNextPrime
(
0
));
EXPECT_EQ
(
3
,
this
->
table_
->
GetNextPrime
(
2
));
EXPECT_EQ
(
5
,
this
->
table_
->
GetNextPrime
(
3
));
EXPECT_EQ
(
7
,
this
->
table_
->
GetNextPrime
(
5
));
EXPECT_EQ
(
11
,
this
->
table_
->
GetNextPrime
(
7
));
EXPECT_EQ
(
131
,
this
->
table_
->
GetNextPrime
(
128
));
}
// Type-parameterized tests involve one extra step: you have to
// enumerate the tests you defined:
REGISTER_TYPED_TEST_CASE_P
(
PrimeTableTest2
,
// The first argument is the test case name.
// The rest of the arguments are the test names.
ReturnsFalseForNonPrimes
,
ReturnsTrueForPrimes
,
CanGetNextPrime
);
// At this point the test pattern is done. However, you don't have
// any real test yet as you haven't said which types you want to run
// the tests with.
// To turn the abstract test pattern into real tests, you instantiate
// it with a list of types. Usually the test pattern will be defined
// in a .h file, and anyone can #include and instantiate it. You can
// even instantiate it more than once in the same program. To tell
// different instances apart, you give each of them a name, which will
// become part of the test case name and can be used in test filters.
// The list of types we want to test. Note that it doesn't have to be
// defined at the time we write the TYPED_TEST_P()s.
typedef
Types
<
OnTheFlyPrimeTable
,
PreCalculatedPrimeTable
>
PrimeTableImplementations
;
INSTANTIATE_TYPED_TEST_CASE_P
(
OnTheFlyAndPreCalculated
,
// Instance name
PrimeTableTest2
,
// Test case name
PrimeTableImplementations
);
// Type list
#endif // GTEST_HAS_TYPED_TEST_P
test/gtest-1.7.0/samples/sample7_unittest.cc
0 → 100644
View file @
9583d1ab
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
// This sample shows how to test common properties of multiple
// implementations of an interface (aka interface tests) using
// value-parameterized tests. Each test in the test case has
// a parameter that is an interface pointer to an implementation
// tested.
// The interface and its implementations are in this header.
#include "prime_tables.h"
#include "gtest/gtest.h"
#if GTEST_HAS_PARAM_TEST
using
::
testing
::
TestWithParam
;
using
::
testing
::
Values
;
// As a general rule, to prevent a test from affecting the tests that come
// after it, you should create and destroy the tested objects for each test
// instead of reusing them. In this sample we will define a simple factory
// function for PrimeTable objects. We will instantiate objects in test's
// SetUp() method and delete them in TearDown() method.
typedef
PrimeTable
*
CreatePrimeTableFunc
();
PrimeTable
*
CreateOnTheFlyPrimeTable
()
{
return
new
OnTheFlyPrimeTable
();
}
template
<
size_t
max_precalculated
>
PrimeTable
*
CreatePreCalculatedPrimeTable
()
{
return
new
PreCalculatedPrimeTable
(
max_precalculated
);
}
// Inside the test body, fixture constructor, SetUp(), and TearDown() you
// can refer to the test parameter by GetParam(). In this case, the test
// parameter is a factory function which we call in fixture's SetUp() to
// create and store an instance of PrimeTable.
class
PrimeTableTest
:
public
TestWithParam
<
CreatePrimeTableFunc
*>
{
public:
virtual
~
PrimeTableTest
()
{
delete
table_
;
}
virtual
void
SetUp
()
{
table_
=
(
*
GetParam
())();
}
virtual
void
TearDown
()
{
delete
table_
;
table_
=
NULL
;
}
protected:
PrimeTable
*
table_
;
};
TEST_P
(
PrimeTableTest
,
ReturnsFalseForNonPrimes
)
{
EXPECT_FALSE
(
table_
->
IsPrime
(
-
5
));
EXPECT_FALSE
(
table_
->
IsPrime
(
0
));
EXPECT_FALSE
(
table_
->
IsPrime
(
1
));
EXPECT_FALSE
(
table_
->
IsPrime
(
4
));
EXPECT_FALSE
(
table_
->
IsPrime
(
6
));
EXPECT_FALSE
(
table_
->
IsPrime
(
100
));
}
TEST_P
(
PrimeTableTest
,
ReturnsTrueForPrimes
)
{
EXPECT_TRUE
(
table_
->
IsPrime
(
2
));
EXPECT_TRUE
(
table_
->
IsPrime
(
3
));
EXPECT_TRUE
(
table_
->
IsPrime
(
5
));
EXPECT_TRUE
(
table_
->
IsPrime
(
7
));
EXPECT_TRUE
(
table_
->
IsPrime
(
11
));
EXPECT_TRUE
(
table_
->
IsPrime
(
131
));
}
TEST_P
(
PrimeTableTest
,
CanGetNextPrime
)
{
EXPECT_EQ
(
2
,
table_
->
GetNextPrime
(
0
));
EXPECT_EQ
(
3
,
table_
->
GetNextPrime
(
2
));
EXPECT_EQ
(
5
,
table_
->
GetNextPrime
(
3
));
EXPECT_EQ
(
7
,
table_
->
GetNextPrime
(
5
));
EXPECT_EQ
(
11
,
table_
->
GetNextPrime
(
7
));
EXPECT_EQ
(
131
,
table_
->
GetNextPrime
(
128
));
}
// In order to run value-parameterized tests, you need to instantiate them,
// or bind them to a list of values which will be used as test parameters.
// You can instantiate them in a different translation module, or even
// instantiate them several times.
//
// Here, we instantiate our tests with a list of two PrimeTable object
// factory functions:
INSTANTIATE_TEST_CASE_P
(
OnTheFlyAndPreCalculated
,
PrimeTableTest
,
Values
(
&
CreateOnTheFlyPrimeTable
,
&
CreatePreCalculatedPrimeTable
<
1000
>
));
#else
// Google Test may not support value-parameterized tests with some
// compilers. If we use conditional compilation to compile out all
// code referring to the gtest_main library, MSVC linker will not link
// that library at all and consequently complain about missing entry
// point defined in that library (fatal error LNK1561: entry point
// must be defined). This dummy test keeps gtest_main linked in.
TEST
(
DummyTest
,
ValueParameterizedTestsAreNotSupportedOnThisPlatform
)
{}
#endif // GTEST_HAS_PARAM_TEST
test/gtest-1.7.0/samples/sample8_unittest.cc
0 → 100644
View file @
9583d1ab
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
// This sample shows how to test code relying on some global flag variables.
// Combine() helps with generating all possible combinations of such flags,
// and each test is given one combination as a parameter.
// Use class definitions to test from this header.
#include "prime_tables.h"
#include "gtest/gtest.h"
#if GTEST_HAS_COMBINE
// Suppose we want to introduce a new, improved implementation of PrimeTable
// which combines speed of PrecalcPrimeTable and versatility of
// OnTheFlyPrimeTable (see prime_tables.h). Inside it instantiates both
// PrecalcPrimeTable and OnTheFlyPrimeTable and uses the one that is more
// appropriate under the circumstances. But in low memory conditions, it can be
// told to instantiate without PrecalcPrimeTable instance at all and use only
// OnTheFlyPrimeTable.
class
HybridPrimeTable
:
public
PrimeTable
{
public:
HybridPrimeTable
(
bool
force_on_the_fly
,
int
max_precalculated
)
:
on_the_fly_impl_
(
new
OnTheFlyPrimeTable
),
precalc_impl_
(
force_on_the_fly
?
NULL
:
new
PreCalculatedPrimeTable
(
max_precalculated
)),
max_precalculated_
(
max_precalculated
)
{}
virtual
~
HybridPrimeTable
()
{
delete
on_the_fly_impl_
;
delete
precalc_impl_
;
}
virtual
bool
IsPrime
(
int
n
)
const
{
if
(
precalc_impl_
!=
NULL
&&
n
<
max_precalculated_
)
return
precalc_impl_
->
IsPrime
(
n
);
else
return
on_the_fly_impl_
->
IsPrime
(
n
);
}
virtual
int
GetNextPrime
(
int
p
)
const
{
int
next_prime
=
-
1
;
if
(
precalc_impl_
!=
NULL
&&
p
<
max_precalculated_
)
next_prime
=
precalc_impl_
->
GetNextPrime
(
p
);
return
next_prime
!=
-
1
?
next_prime
:
on_the_fly_impl_
->
GetNextPrime
(
p
);
}
private:
OnTheFlyPrimeTable
*
on_the_fly_impl_
;
PreCalculatedPrimeTable
*
precalc_impl_
;
int
max_precalculated_
;
};
using
::
testing
::
TestWithParam
;
using
::
testing
::
Bool
;
using
::
testing
::
Values
;
using
::
testing
::
Combine
;
// To test all code paths for HybridPrimeTable we must test it with numbers
// both within and outside PreCalculatedPrimeTable's capacity and also with
// PreCalculatedPrimeTable disabled. We do this by defining fixture which will
// accept different combinations of parameters for instantiating a
// HybridPrimeTable instance.
class
PrimeTableTest
:
public
TestWithParam
<
::
std
::
tr1
::
tuple
<
bool
,
int
>
>
{
protected:
virtual
void
SetUp
()
{
// This can be written as
//
// bool force_on_the_fly;
// int max_precalculated;
// tie(force_on_the_fly, max_precalculated) = GetParam();
//
// once the Google C++ Style Guide allows use of ::std::tr1::tie.
//
bool
force_on_the_fly
=
::
std
::
tr1
::
get
<
0
>
(
GetParam
());
int
max_precalculated
=
::
std
::
tr1
::
get
<
1
>
(
GetParam
());
table_
=
new
HybridPrimeTable
(
force_on_the_fly
,
max_precalculated
);
}
virtual
void
TearDown
()
{
delete
table_
;
table_
=
NULL
;
}
HybridPrimeTable
*
table_
;
};
TEST_P
(
PrimeTableTest
,
ReturnsFalseForNonPrimes
)
{
// Inside the test body, you can refer to the test parameter by GetParam().
// In this case, the test parameter is a PrimeTable interface pointer which
// we can use directly.
// Please note that you can also save it in the fixture's SetUp() method
// or constructor and use saved copy in the tests.
EXPECT_FALSE
(
table_
->
IsPrime
(
-
5
));
EXPECT_FALSE
(
table_
->
IsPrime
(
0
));
EXPECT_FALSE
(
table_
->
IsPrime
(
1
));
EXPECT_FALSE
(
table_
->
IsPrime
(
4
));
EXPECT_FALSE
(
table_
->
IsPrime
(
6
));
EXPECT_FALSE
(
table_
->
IsPrime
(
100
));
}
TEST_P
(
PrimeTableTest
,
ReturnsTrueForPrimes
)
{
EXPECT_TRUE
(
table_
->
IsPrime
(
2
));
EXPECT_TRUE
(
table_
->
IsPrime
(
3
));
EXPECT_TRUE
(
table_
->
IsPrime
(
5
));
EXPECT_TRUE
(
table_
->
IsPrime
(
7
));
EXPECT_TRUE
(
table_
->
IsPrime
(
11
));
EXPECT_TRUE
(
table_
->
IsPrime
(
131
));
}
TEST_P
(
PrimeTableTest
,
CanGetNextPrime
)
{
EXPECT_EQ
(
2
,
table_
->
GetNextPrime
(
0
));
EXPECT_EQ
(
3
,
table_
->
GetNextPrime
(
2
));
EXPECT_EQ
(
5
,
table_
->
GetNextPrime
(
3
));
EXPECT_EQ
(
7
,
table_
->
GetNextPrime
(
5
));
EXPECT_EQ
(
11
,
table_
->
GetNextPrime
(
7
));
EXPECT_EQ
(
131
,
table_
->
GetNextPrime
(
128
));
}
// In order to run value-parameterized tests, you need to instantiate them,
// or bind them to a list of values which will be used as test parameters.
// You can instantiate them in a different translation module, or even
// instantiate them several times.
//
// Here, we instantiate our tests with a list of parameters. We must combine
// all variations of the boolean flag suppressing PrecalcPrimeTable and some
// meaningful values for tests. We choose a small value (1), and a value that
// will put some of the tested numbers beyond the capability of the
// PrecalcPrimeTable instance and some inside it (10). Combine will produce all
// possible combinations.
INSTANTIATE_TEST_CASE_P
(
MeaningfulTestParameters
,
PrimeTableTest
,
Combine
(
Bool
(),
Values
(
1
,
10
)));
#else
// Google Test may not support Combine() with some compilers. If we
// use conditional compilation to compile out all code referring to
// the gtest_main library, MSVC linker will not link that library at
// all and consequently complain about missing entry point defined in
// that library (fatal error LNK1561: entry point must be
// defined). This dummy test keeps gtest_main linked in.
TEST
(
DummyTest
,
CombineIsNotSupportedOnThisPlatform
)
{}
#endif // GTEST_HAS_COMBINE
test/gtest-1.7.0/samples/sample9_unittest.cc
0 → 100644
View file @
9583d1ab
// Copyright 2009 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
// This sample shows how to use Google Test listener API to implement
// an alternative console output and how to use the UnitTest reflection API
// to enumerate test cases and tests and to inspect their results.
#include <stdio.h>
#include "gtest/gtest.h"
using
::
testing
::
EmptyTestEventListener
;
using
::
testing
::
InitGoogleTest
;
using
::
testing
::
Test
;
using
::
testing
::
TestCase
;
using
::
testing
::
TestEventListeners
;
using
::
testing
::
TestInfo
;
using
::
testing
::
TestPartResult
;
using
::
testing
::
UnitTest
;
namespace
{
// Provides alternative output mode which produces minimal amount of
// information about tests.
class
TersePrinter
:
public
EmptyTestEventListener
{
private:
// Called before any test activity starts.
virtual
void
OnTestProgramStart
(
const
UnitTest
&
/* unit_test */
)
{}
// Called after all test activities have ended.
virtual
void
OnTestProgramEnd
(
const
UnitTest
&
unit_test
)
{
fprintf
(
stdout
,
"TEST %s
\n
"
,
unit_test
.
Passed
()
?
"PASSED"
:
"FAILED"
);
fflush
(
stdout
);
}
// Called before a test starts.
virtual
void
OnTestStart
(
const
TestInfo
&
test_info
)
{
fprintf
(
stdout
,
"*** Test %s.%s starting.
\n
"
,
test_info
.
test_case_name
(),
test_info
.
name
());
fflush
(
stdout
);
}
// Called after a failed assertion or a SUCCEED() invocation.
virtual
void
OnTestPartResult
(
const
TestPartResult
&
test_part_result
)
{
fprintf
(
stdout
,
"%s in %s:%d
\n
%s
\n
"
,
test_part_result
.
failed
()
?
"*** Failure"
:
"Success"
,
test_part_result
.
file_name
(),
test_part_result
.
line_number
(),
test_part_result
.
summary
());
fflush
(
stdout
);
}
// Called after a test ends.
virtual
void
OnTestEnd
(
const
TestInfo
&
test_info
)
{
fprintf
(
stdout
,
"*** Test %s.%s ending.
\n
"
,
test_info
.
test_case_name
(),
test_info
.
name
());
fflush
(
stdout
);
}
};
// class TersePrinter
TEST
(
CustomOutputTest
,
PrintsMessage
)
{
printf
(
"Printing something from the test body...
\n
"
);
}
TEST
(
CustomOutputTest
,
Succeeds
)
{
SUCCEED
()
<<
"SUCCEED() has been invoked from here"
;
}
TEST
(
CustomOutputTest
,
Fails
)
{
EXPECT_EQ
(
1
,
2
)
<<
"This test fails in order to demonstrate alternative failure messages"
;
}
}
// namespace
int
main
(
int
argc
,
char
**
argv
)
{
InitGoogleTest
(
&
argc
,
argv
);
bool
terse_output
=
false
;
if
(
argc
>
1
&&
strcmp
(
argv
[
1
],
"--terse_output"
)
==
0
)
terse_output
=
true
;
else
printf
(
"%s
\n
"
,
"Run this program with --terse_output to change the way "
"it prints its output."
);
UnitTest
&
unit_test
=
*
UnitTest
::
GetInstance
();
// If we are given the --terse_output command line flag, suppresses the
// standard output and attaches own result printer.
if
(
terse_output
)
{
TestEventListeners
&
listeners
=
unit_test
.
listeners
();
// Removes the default console output listener from the list so it will
// not receive events from Google Test and won't print any output. Since
// this operation transfers ownership of the listener to the caller we
// have to delete it as well.
delete
listeners
.
Release
(
listeners
.
default_result_printer
());
// Adds the custom output listener to the list. It will now receive
// events from Google Test and print the alternative output. We don't
// have to worry about deleting it since Google Test assumes ownership
// over it after adding it to the list.
listeners
.
Append
(
new
TersePrinter
);
}
int
ret_val
=
RUN_ALL_TESTS
();
// This is an example of using the UnitTest reflection API to inspect test
// results. Here we discount failures from the tests we expected to fail.
int
unexpectedly_failed_tests
=
0
;
for
(
int
i
=
0
;
i
<
unit_test
.
total_test_case_count
();
++
i
)
{
const
TestCase
&
test_case
=
*
unit_test
.
GetTestCase
(
i
);
for
(
int
j
=
0
;
j
<
test_case
.
total_test_count
();
++
j
)
{
const
TestInfo
&
test_info
=
*
test_case
.
GetTestInfo
(
j
);
// Counts failed tests that were not meant to fail (those without
// 'Fails' in the name).
if
(
test_info
.
result
()
->
Failed
()
&&
strcmp
(
test_info
.
name
(),
"Fails"
)
!=
0
)
{
unexpectedly_failed_tests
++
;
}
}
}
// Test that were meant to fail should not affect the test program outcome.
if
(
unexpectedly_failed_tests
==
0
)
ret_val
=
0
;
return
ret_val
;
}
test/gtest-1.7.0/scripts/fuse_gtest_files.py
0 → 100755
View file @
9583d1ab
#!/usr/bin/env python
#
# Copyright 2009, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""fuse_gtest_files.py v0.2.0
Fuses Google Test source code into a .h file and a .cc file.
SYNOPSIS
fuse_gtest_files.py [GTEST_ROOT_DIR] OUTPUT_DIR
Scans GTEST_ROOT_DIR for Google Test source code, and generates
two files: OUTPUT_DIR/gtest/gtest.h and OUTPUT_DIR/gtest/gtest-all.cc.
Then you can build your tests by adding OUTPUT_DIR to the include
search path and linking with OUTPUT_DIR/gtest/gtest-all.cc. These
two files contain everything you need to use Google Test. Hence
you can "install" Google Test by copying them to wherever you want.
GTEST_ROOT_DIR can be omitted and defaults to the parent
directory of the directory holding this script.
EXAMPLES
./fuse_gtest_files.py fused_gtest
./fuse_gtest_files.py path/to/unpacked/gtest fused_gtest
This tool is experimental. In particular, it assumes that there is no
conditional inclusion of Google Test headers. Please report any
problems to googletestframework@googlegroups.com. You can read
http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide for
more information.
"""
__author__
=
'wan@google.com (Zhanyong Wan)'
import
os
import
re
import
sets
import
sys
# We assume that this file is in the scripts/ directory in the Google
# Test root directory.
DEFAULT_GTEST_ROOT_DIR
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'..'
)
# Regex for matching '#include "gtest/..."'.
INCLUDE_GTEST_FILE_REGEX
=
re
.
compile
(
r
'^\s*#\s*include\s*"(gtest/.+)"'
)
# Regex for matching '#include "src/..."'.
INCLUDE_SRC_FILE_REGEX
=
re
.
compile
(
r
'^\s*#\s*include\s*"(src/.+)"'
)
# Where to find the source seed files.
GTEST_H_SEED
=
'include/gtest/gtest.h'
GTEST_SPI_H_SEED
=
'include/gtest/gtest-spi.h'
GTEST_ALL_CC_SEED
=
'src/gtest-all.cc'
# Where to put the generated files.
GTEST_H_OUTPUT
=
'gtest/gtest.h'
GTEST_ALL_CC_OUTPUT
=
'gtest/gtest-all.cc'
def
VerifyFileExists
(
directory
,
relative_path
):
"""Verifies that the given file exists; aborts on failure.
relative_path is the file path relative to the given directory.
"""
if
not
os
.
path
.
isfile
(
os
.
path
.
join
(
directory
,
relative_path
)):
print
'ERROR: Cannot find %s in directory %s.'
%
(
relative_path
,
directory
)
print
(
'Please either specify a valid project root directory '
'or omit it on the command line.'
)
sys
.
exit
(
1
)
def
ValidateGTestRootDir
(
gtest_root
):
"""Makes sure gtest_root points to a valid gtest root directory.
The function aborts the program on failure.
"""
VerifyFileExists
(
gtest_root
,
GTEST_H_SEED
)
VerifyFileExists
(
gtest_root
,
GTEST_ALL_CC_SEED
)
def
VerifyOutputFile
(
output_dir
,
relative_path
):
"""Verifies that the given output file path is valid.
relative_path is relative to the output_dir directory.
"""
# Makes sure the output file either doesn't exist or can be overwritten.
output_file
=
os
.
path
.
join
(
output_dir
,
relative_path
)
if
os
.
path
.
exists
(
output_file
):
# TODO(wan@google.com): The following user-interaction doesn't
# work with automated processes. We should provide a way for the
# Makefile to force overwriting the files.
print
(
'%s already exists in directory %s - overwrite it? (y/N) '
%
(
relative_path
,
output_dir
))
answer
=
sys
.
stdin
.
readline
().
strip
()
if
answer
not
in
[
'y'
,
'Y'
]:
print
'ABORTED.'
sys
.
exit
(
1
)
# Makes sure the directory holding the output file exists; creates
# it and all its ancestors if necessary.
parent_directory
=
os
.
path
.
dirname
(
output_file
)
if
not
os
.
path
.
isdir
(
parent_directory
):
os
.
makedirs
(
parent_directory
)
def
ValidateOutputDir
(
output_dir
):
"""Makes sure output_dir points to a valid output directory.
The function aborts the program on failure.
"""
VerifyOutputFile
(
output_dir
,
GTEST_H_OUTPUT
)
VerifyOutputFile
(
output_dir
,
GTEST_ALL_CC_OUTPUT
)
def
FuseGTestH
(
gtest_root
,
output_dir
):
"""Scans folder gtest_root to generate gtest/gtest.h in output_dir."""
output_file
=
file
(
os
.
path
.
join
(
output_dir
,
GTEST_H_OUTPUT
),
'w'
)
processed_files
=
sets
.
Set
()
# Holds all gtest headers we've processed.
def
ProcessFile
(
gtest_header_path
):
"""Processes the given gtest header file."""
# We don't process the same header twice.
if
gtest_header_path
in
processed_files
:
return
processed_files
.
add
(
gtest_header_path
)
# Reads each line in the given gtest header.
for
line
in
file
(
os
.
path
.
join
(
gtest_root
,
gtest_header_path
),
'r'
):
m
=
INCLUDE_GTEST_FILE_REGEX
.
match
(
line
)
if
m
:
# It's '#include "gtest/..."' - let's process it recursively.
ProcessFile
(
'include/'
+
m
.
group
(
1
))
else
:
# Otherwise we copy the line unchanged to the output file.
output_file
.
write
(
line
)
ProcessFile
(
GTEST_H_SEED
)
output_file
.
close
()
def
FuseGTestAllCcToFile
(
gtest_root
,
output_file
):
"""Scans folder gtest_root to generate gtest/gtest-all.cc in output_file."""
processed_files
=
sets
.
Set
()
def
ProcessFile
(
gtest_source_file
):
"""Processes the given gtest source file."""
# We don't process the same #included file twice.
if
gtest_source_file
in
processed_files
:
return
processed_files
.
add
(
gtest_source_file
)
# Reads each line in the given gtest source file.
for
line
in
file
(
os
.
path
.
join
(
gtest_root
,
gtest_source_file
),
'r'
):
m
=
INCLUDE_GTEST_FILE_REGEX
.
match
(
line
)
if
m
:
if
'include/'
+
m
.
group
(
1
)
==
GTEST_SPI_H_SEED
:
# It's '#include "gtest/gtest-spi.h"'. This file is not
# #included by "gtest/gtest.h", so we need to process it.
ProcessFile
(
GTEST_SPI_H_SEED
)
else
:
# It's '#include "gtest/foo.h"' where foo is not gtest-spi.
# We treat it as '#include "gtest/gtest.h"', as all other
# gtest headers are being fused into gtest.h and cannot be
# #included directly.
# There is no need to #include "gtest/gtest.h" more than once.
if
not
GTEST_H_SEED
in
processed_files
:
processed_files
.
add
(
GTEST_H_SEED
)
output_file
.
write
(
'#include "%s"
\n
'
%
(
GTEST_H_OUTPUT
,))
else
:
m
=
INCLUDE_SRC_FILE_REGEX
.
match
(
line
)
if
m
:
# It's '#include "src/foo"' - let's process it recursively.
ProcessFile
(
m
.
group
(
1
))
else
:
output_file
.
write
(
line
)
ProcessFile
(
GTEST_ALL_CC_SEED
)
def
FuseGTestAllCc
(
gtest_root
,
output_dir
):
"""Scans folder gtest_root to generate gtest/gtest-all.cc in output_dir."""
output_file
=
file
(
os
.
path
.
join
(
output_dir
,
GTEST_ALL_CC_OUTPUT
),
'w'
)
FuseGTestAllCcToFile
(
gtest_root
,
output_file
)
output_file
.
close
()
def
FuseGTest
(
gtest_root
,
output_dir
):
"""Fuses gtest.h and gtest-all.cc."""
ValidateGTestRootDir
(
gtest_root
)
ValidateOutputDir
(
output_dir
)
FuseGTestH
(
gtest_root
,
output_dir
)
FuseGTestAllCc
(
gtest_root
,
output_dir
)
def
main
():
argc
=
len
(
sys
.
argv
)
if
argc
==
2
:
# fuse_gtest_files.py OUTPUT_DIR
FuseGTest
(
DEFAULT_GTEST_ROOT_DIR
,
sys
.
argv
[
1
])
elif
argc
==
3
:
# fuse_gtest_files.py GTEST_ROOT_DIR OUTPUT_DIR
FuseGTest
(
sys
.
argv
[
1
],
sys
.
argv
[
2
])
else
:
print
__doc__
sys
.
exit
(
1
)
if
__name__
==
'__main__'
:
main
()
test/gtest-1.7.0/scripts/gen_gtest_pred_impl.py
0 → 100755
View file @
9583d1ab
#!/usr/bin/env python
#
# Copyright 2006, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""gen_gtest_pred_impl.py v0.1
Generates the implementation of Google Test predicate assertions and
accompanying tests.
Usage:
gen_gtest_pred_impl.py MAX_ARITY
where MAX_ARITY is a positive integer.
The command generates the implementation of up-to MAX_ARITY-ary
predicate assertions, and writes it to file gtest_pred_impl.h in the
directory where the script is. It also generates the accompanying
unit test in file gtest_pred_impl_unittest.cc.
"""
__author__
=
'wan@google.com (Zhanyong Wan)'
import
os
import
sys
import
time
# Where this script is.
SCRIPT_DIR
=
os
.
path
.
dirname
(
sys
.
argv
[
0
])
# Where to store the generated header.
HEADER
=
os
.
path
.
join
(
SCRIPT_DIR
,
'../include/gtest/gtest_pred_impl.h'
)
# Where to store the generated unit test.
UNIT_TEST
=
os
.
path
.
join
(
SCRIPT_DIR
,
'../test/gtest_pred_impl_unittest.cc'
)
def
HeaderPreamble
(
n
):
"""Returns the preamble for the header file.
Args:
n: the maximum arity of the predicate macros to be generated.
"""
# A map that defines the values used in the preamble template.
DEFS
=
{
'today'
:
time
.
strftime
(
'%m/%d/%Y'
),
'year'
:
time
.
strftime
(
'%Y'
),
'command'
:
'%s %s'
%
(
os
.
path
.
basename
(
sys
.
argv
[
0
]),
n
),
'n'
:
n
}
return
(
"""// Copyright 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file is AUTOMATICALLY GENERATED on %(today)s by command
// '%(command)s'. DO NOT EDIT BY HAND!
//
// Implements a family of generic predicate assertion macros.
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
// Makes sure this header is not included before gtest.h.
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
# error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
// This header implements a family of generic predicate assertion
// macros:
//
// ASSERT_PRED_FORMAT1(pred_format, v1)
// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
// ...
//
// where pred_format is a function or functor that takes n (in the
// case of ASSERT_PRED_FORMATn) values and their source expression
// text, and returns a testing::AssertionResult. See the definition
// of ASSERT_EQ in gtest.h for an example.
//
// If you don't care about formatting, you can use the more
// restrictive version:
//
// ASSERT_PRED1(pred, v1)
// ASSERT_PRED2(pred, v1, v2)
// ...
//
// where pred is an n-ary function or functor that returns bool,
// and the values v1, v2, ..., must support the << operator for
// streaming to std::ostream.
//
// We also define the EXPECT_* variations.
//
// For now we only support predicates whose arity is at most %(n)s.
// Please email googletestframework@googlegroups.com if you need
// support for higher arities.
// GTEST_ASSERT_ is the basic statement to which all of the assertions
// in this file reduce. Don't use this in your code.
#define GTEST_ASSERT_(expression, on_failure)
\\
GTEST_AMBIGUOUS_ELSE_BLOCKER_
\\
if (const ::testing::AssertionResult gtest_ar = (expression))
\\
;
\\
else
\\
on_failure(gtest_ar.failure_message())
"""
%
DEFS
)
def
Arity
(
n
):
"""Returns the English name of the given arity."""
if
n
<
0
:
return
None
elif
n
<=
3
:
return
[
'nullary'
,
'unary'
,
'binary'
,
'ternary'
][
n
]
else
:
return
'%s-ary'
%
n
def
Title
(
word
):
"""Returns the given word in title case. The difference between
this and string's title() method is that Title('4-ary') is '4-ary'
while '4-ary'.title() is '4-Ary'."""
return
word
[
0
].
upper
()
+
word
[
1
:]
def
OneTo
(
n
):
"""Returns the list [1, 2, 3, ..., n]."""
return
range
(
1
,
n
+
1
)
def
Iter
(
n
,
format
,
sep
=
''
):
"""Given a positive integer n, a format string that contains 0 or
more '%s' format specs, and optionally a separator string, returns
the join of n strings, each formatted with the format string on an
iterator ranged from 1 to n.
Example:
Iter(3, 'v%s', sep=', ') returns 'v1, v2, v3'.
"""
# How many '%s' specs are in format?
spec_count
=
len
(
format
.
split
(
'%s'
))
-
1
return
sep
.
join
([
format
%
(
spec_count
*
(
i
,))
for
i
in
OneTo
(
n
)])
def
ImplementationForArity
(
n
):
"""Returns the implementation of n-ary predicate assertions."""
# A map the defines the values used in the implementation template.
DEFS
=
{
'n'
:
str
(
n
),
'vs'
:
Iter
(
n
,
'v%s'
,
sep
=
', '
),
'vts'
:
Iter
(
n
,
'#v%s'
,
sep
=
', '
),
'arity'
:
Arity
(
n
),
'Arity'
:
Title
(
Arity
(
n
))
}
impl
=
"""
// Helper function for implementing {EXPECT|ASSERT}_PRED%(n)s. Don't use
// this in your code.
template <typename Pred"""
%
DEFS
impl
+=
Iter
(
n
,
""",
typename T%s"""
)
impl
+=
""">
AssertionResult AssertPred%(n)sHelper(const char* pred_text"""
%
DEFS
impl
+=
Iter
(
n
,
""",
const char* e%s"""
)
impl
+=
""",
Pred pred"""
impl
+=
Iter
(
n
,
""",
const T%s& v%s"""
)
impl
+=
""") {
if (pred(%(vs)s)) return AssertionSuccess();
"""
%
DEFS
impl
+=
' return AssertionFailure() << pred_text << "("'
impl
+=
Iter
(
n
,
"""
<< e%s"""
,
sep
=
' << ", "'
)
impl
+=
' << ") evaluates to false, where"'
impl
+=
Iter
(
n
,
"""
<< "
\\
n" << e%s << " evaluates to " << v%s"""
)
impl
+=
""";
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
// Don't use this in your code.
#define GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, on_failure)
\\
GTEST_ASSERT_(pred_format(%(vts)s, %(vs)s),
\\
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED%(n)s. Don't use
// this in your code.
#define GTEST_PRED%(n)s_(pred, %(vs)s, on_failure)
\\
GTEST_ASSERT_(::testing::AssertPred%(n)sHelper(#pred"""
%
DEFS
impl
+=
Iter
(
n
,
""",
\\
#v%s"""
)
impl
+=
""",
\\
pred"""
impl
+=
Iter
(
n
,
""",
\\
v%s"""
)
impl
+=
"""), on_failure)
// %(Arity)s predicate assertion macros.
#define EXPECT_PRED_FORMAT%(n)s(pred_format, %(vs)s)
\\
GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED%(n)s(pred, %(vs)s)
\\
GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT%(n)s(pred_format, %(vs)s)
\\
GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED%(n)s(pred, %(vs)s)
\\
GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_FATAL_FAILURE_)
"""
%
DEFS
return
impl
def
HeaderPostamble
():
"""Returns the postamble for the header file."""
return
"""
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
"""
def
GenerateFile
(
path
,
content
):
"""Given a file path and a content string, overwrites it with the
given content."""
print
'Updating file %s . . .'
%
path
f
=
file
(
path
,
'w+'
)
print
>>
f
,
content
,
f
.
close
()
print
'File %s has been updated.'
%
path
def
GenerateHeader
(
n
):
"""Given the maximum arity n, updates the header file that implements
the predicate assertions."""
GenerateFile
(
HEADER
,
HeaderPreamble
(
n
)
+
''
.
join
([
ImplementationForArity
(
i
)
for
i
in
OneTo
(
n
)])
+
HeaderPostamble
())
def
UnitTestPreamble
():
"""Returns the preamble for the unit test file."""
# A map that defines the values used in the preamble template.
DEFS
=
{
'today'
:
time
.
strftime
(
'%m/%d/%Y'
),
'year'
:
time
.
strftime
(
'%Y'
),
'command'
:
'%s %s'
%
(
os
.
path
.
basename
(
sys
.
argv
[
0
]),
sys
.
argv
[
1
]),
}
return
(
"""// Copyright 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file is AUTOMATICALLY GENERATED on %(today)s by command
// '%(command)s'. DO NOT EDIT BY HAND!
// Regression test for gtest_pred_impl.h
//
// This file is generated by a script and quite long. If you intend to
// learn how Google Test works by reading its unit tests, read
// gtest_unittest.cc instead.
//
// This is intended as a regression test for the Google Test predicate
// assertions. We compile it as part of the gtest_unittest target
// only to keep the implementation tidy and compact, as it is quite
// involved to set up the stage for testing Google Test using Google
// Test itself.
//
// Currently, gtest_unittest takes ~11 seconds to run in the testing
// daemon. In the future, if it grows too large and needs much more
// time to finish, we should consider separating this file into a
// stand-alone regression test.
#include <iostream>
#include "gtest/gtest.h"
#include "gtest/gtest-spi.h"
// A user-defined data type.
struct Bool {
explicit Bool(int val) : value(val != 0) {}
bool operator>(int n) const { return value > Bool(n).value; }
Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); }
bool operator==(const Bool& rhs) const { return value == rhs.value; }
bool value;
};
// Enables Bool to be used in assertions.
std::ostream& operator<<(std::ostream& os, const Bool& x) {
return os << (x.value ? "true" : "false");
}
"""
%
DEFS
)
def
TestsForArity
(
n
):
"""Returns the tests for n-ary predicate assertions."""
# A map that defines the values used in the template for the tests.
DEFS
=
{
'n'
:
n
,
'es'
:
Iter
(
n
,
'e%s'
,
sep
=
', '
),
'vs'
:
Iter
(
n
,
'v%s'
,
sep
=
', '
),
'vts'
:
Iter
(
n
,
'#v%s'
,
sep
=
', '
),
'tvs'
:
Iter
(
n
,
'T%s v%s'
,
sep
=
', '
),
'int_vs'
:
Iter
(
n
,
'int v%s'
,
sep
=
', '
),
'Bool_vs'
:
Iter
(
n
,
'Bool v%s'
,
sep
=
', '
),
'types'
:
Iter
(
n
,
'typename T%s'
,
sep
=
', '
),
'v_sum'
:
Iter
(
n
,
'v%s'
,
sep
=
' + '
),
'arity'
:
Arity
(
n
),
'Arity'
:
Title
(
Arity
(
n
)),
}
tests
=
(
"""// Sample functions/functors for testing %(arity)s predicate assertions.
// A %(arity)s predicate function.
template <%(types)s>
bool PredFunction%(n)s(%(tvs)s) {
return %(v_sum)s > 0;
}
// The following two functions are needed to circumvent a bug in
// gcc 2.95.3, which sometimes has problem with the above template
// function.
bool PredFunction%(n)sInt(%(int_vs)s) {
return %(v_sum)s > 0;
}
bool PredFunction%(n)sBool(%(Bool_vs)s) {
return %(v_sum)s > 0;
}
"""
%
DEFS
)
tests
+=
"""
// A %(arity)s predicate functor.
struct PredFunctor%(n)s {
template <%(types)s>
bool operator()("""
%
DEFS
tests
+=
Iter
(
n
,
'const T%s& v%s'
,
sep
=
""",
"""
)
tests
+=
""") {
return %(v_sum)s > 0;
}
};
"""
%
DEFS
tests
+=
"""
// A %(arity)s predicate-formatter function.
template <%(types)s>
testing::AssertionResult PredFormatFunction%(n)s("""
%
DEFS
tests
+=
Iter
(
n
,
'const char* e%s'
,
sep
=
""",
"""
)
tests
+=
Iter
(
n
,
""",
const T%s& v%s"""
)
tests
+=
""") {
if (PredFunction%(n)s(%(vs)s))
return testing::AssertionSuccess();
return testing::AssertionFailure()
<< """
%
DEFS
tests
+=
Iter
(
n
,
'e%s'
,
sep
=
' << " + " << '
)
tests
+=
"""
<< " is expected to be positive, but evaluates to "
<< %(v_sum)s << ".";
}
"""
%
DEFS
tests
+=
"""
// A %(arity)s predicate-formatter functor.
struct PredFormatFunctor%(n)s {
template <%(types)s>
testing::AssertionResult operator()("""
%
DEFS
tests
+=
Iter
(
n
,
'const char* e%s'
,
sep
=
""",
"""
)
tests
+=
Iter
(
n
,
""",
const T%s& v%s"""
)
tests
+=
""") const {
return PredFormatFunction%(n)s(%(es)s, %(vs)s);
}
};
"""
%
DEFS
tests
+=
"""
// Tests for {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
class Predicate%(n)sTest : public testing::Test {
protected:
virtual void SetUp() {
expected_to_finish_ = true;
finished_ = false;"""
%
DEFS
tests
+=
"""
"""
+
Iter
(
n
,
'n%s_ = '
)
+
"""0;
}
"""
tests
+=
"""
virtual void TearDown() {
// Verifies that each of the predicate's arguments was evaluated
// exactly once."""
tests
+=
''
.
join
([
"""
EXPECT_EQ(1, n%s_) <<
"The predicate assertion didn't evaluate argument %s "
"exactly once.";"""
%
(
i
,
i
+
1
)
for
i
in
OneTo
(
n
)])
tests
+=
"""
// Verifies that the control flow in the test function is expected.
if (expected_to_finish_ && !finished_) {
FAIL() << "The predicate assertion unexpactedly aborted the test.";
} else if (!expected_to_finish_ && finished_) {
FAIL() << "The failed predicate assertion didn't abort the test "
"as expected.";
}
}
// true iff the test function is expected to run to finish.
static bool expected_to_finish_;
// true iff the test function did run to finish.
static bool finished_;
"""
%
DEFS
tests
+=
Iter
(
n
,
"""
static int n%s_;"""
)
tests
+=
"""
};
bool Predicate%(n)sTest::expected_to_finish_;
bool Predicate%(n)sTest::finished_;
"""
%
DEFS
tests
+=
Iter
(
n
,
"""int Predicate%%(n)sTest::n%s_;
"""
)
%
DEFS
tests
+=
"""
typedef Predicate%(n)sTest EXPECT_PRED_FORMAT%(n)sTest;
typedef Predicate%(n)sTest ASSERT_PRED_FORMAT%(n)sTest;
typedef Predicate%(n)sTest EXPECT_PRED%(n)sTest;
typedef Predicate%(n)sTest ASSERT_PRED%(n)sTest;
"""
%
DEFS
def
GenTest
(
use_format
,
use_assert
,
expect_failure
,
use_functor
,
use_user_type
):
"""Returns the test for a predicate assertion macro.
Args:
use_format: true iff the assertion is a *_PRED_FORMAT*.
use_assert: true iff the assertion is a ASSERT_*.
expect_failure: true iff the assertion is expected to fail.
use_functor: true iff the first argument of the assertion is
a functor (as opposed to a function)
use_user_type: true iff the predicate functor/function takes
argument(s) of a user-defined type.
Example:
GenTest(1, 0, 0, 1, 0) returns a test that tests the behavior
of a successful EXPECT_PRED_FORMATn() that takes a functor
whose arguments have built-in types."""
if
use_assert
:
assrt
=
'ASSERT'
# 'assert' is reserved, so we cannot use
# that identifier here.
else
:
assrt
=
'EXPECT'
assertion
=
assrt
+
'_PRED'
if
use_format
:
pred_format
=
'PredFormat'
assertion
+=
'_FORMAT'
else
:
pred_format
=
'Pred'
assertion
+=
'%(n)s'
%
DEFS
if
use_functor
:
pred_format_type
=
'functor'
pred_format
+=
'Functor%(n)s()'
else
:
pred_format_type
=
'function'
pred_format
+=
'Function%(n)s'
if
not
use_format
:
if
use_user_type
:
pred_format
+=
'Bool'
else
:
pred_format
+=
'Int'
test_name
=
pred_format_type
.
title
()
if
use_user_type
:
arg_type
=
'user-defined type (Bool)'
test_name
+=
'OnUserType'
if
expect_failure
:
arg
=
'Bool(n%s_++)'
else
:
arg
=
'Bool(++n%s_)'
else
:
arg_type
=
'built-in type (int)'
test_name
+=
'OnBuiltInType'
if
expect_failure
:
arg
=
'n%s_++'
else
:
arg
=
'++n%s_'
if
expect_failure
:
successful_or_failed
=
'failed'
expected_or_not
=
'expected.'
test_name
+=
'Failure'
else
:
successful_or_failed
=
'successful'
expected_or_not
=
'UNEXPECTED!'
test_name
+=
'Success'
# A map that defines the values used in the test template.
defs
=
DEFS
.
copy
()
defs
.
update
({
'assert'
:
assrt
,
'assertion'
:
assertion
,
'test_name'
:
test_name
,
'pf_type'
:
pred_format_type
,
'pf'
:
pred_format
,
'arg_type'
:
arg_type
,
'arg'
:
arg
,
'successful'
:
successful_or_failed
,
'expected'
:
expected_or_not
,
})
test
=
"""
// Tests a %(successful)s %(assertion)s where the
// predicate-formatter is a %(pf_type)s on a %(arg_type)s.
TEST_F(%(assertion)sTest, %(test_name)s) {"""
%
defs
indent
=
(
len
(
assertion
)
+
3
)
*
' '
extra_indent
=
''
if
expect_failure
:
extra_indent
=
' '
if
use_assert
:
test
+=
"""
expected_to_finish_ = false;
EXPECT_FATAL_FAILURE({ // NOLINT"""
else
:
test
+=
"""
EXPECT_NONFATAL_FAILURE({ // NOLINT"""
test
+=
'
\n
'
+
extra_indent
+
""" %(assertion)s(%(pf)s"""
%
defs
test
=
test
%
defs
test
+=
Iter
(
n
,
',
\n
'
+
indent
+
extra_indent
+
'%(arg)s'
%
defs
)
test
+=
');
\n
'
+
extra_indent
+
' finished_ = true;
\n
'
if
expect_failure
:
test
+=
' }, "");
\n
'
test
+=
'}
\n
'
return
test
# Generates tests for all 2**6 = 64 combinations.
tests
+=
''
.
join
([
GenTest
(
use_format
,
use_assert
,
expect_failure
,
use_functor
,
use_user_type
)
for
use_format
in
[
0
,
1
]
for
use_assert
in
[
0
,
1
]
for
expect_failure
in
[
0
,
1
]
for
use_functor
in
[
0
,
1
]
for
use_user_type
in
[
0
,
1
]
])
return
tests
def
UnitTestPostamble
():
"""Returns the postamble for the tests."""
return
''
def
GenerateUnitTest
(
n
):
"""Returns the tests for up-to n-ary predicate assertions."""
GenerateFile
(
UNIT_TEST
,
UnitTestPreamble
()
+
''
.
join
([
TestsForArity
(
i
)
for
i
in
OneTo
(
n
)])
+
UnitTestPostamble
())
def
_Main
():
"""The entry point of the script. Generates the header file and its
unit test."""
if
len
(
sys
.
argv
)
!=
2
:
print
__doc__
print
'Author: '
+
__author__
sys
.
exit
(
1
)
n
=
int
(
sys
.
argv
[
1
])
GenerateHeader
(
n
)
GenerateUnitTest
(
n
)
if
__name__
==
'__main__'
:
_Main
()
test/gtest-1.7.0/scripts/gtest-config.in
0 → 100755
View file @
9583d1ab
#!/bin/sh
# These variables are automatically filled in by the configure script.
name
=
"@PACKAGE_TARNAME@"
version
=
"@PACKAGE_VERSION@"
show_usage
()
{
echo
"Usage: gtest-config [OPTIONS...]"
}
show_help
()
{
show_usage
cat
<<
\
EOF
The `gtest-config' script provides access to the necessary compile and linking
flags to connect with Google C++ Testing Framework, both in a build prior to
installation, and on the system proper after installation. The installation
overrides may be issued in combination with any other queries, but will only
affect installation queries if called on a built but not installed gtest. The
installation queries may not be issued with any other types of queries, and
only one installation query may be made at a time. The version queries and
compiler flag queries may be combined as desired but not mixed. Different
version queries are always combined with logical "and" semantics, and only the
last of any particular query is used while all previous ones ignored. All
versions must be specified as a sequence of numbers separated by periods.
Compiler flag queries output the union of the sets of flags when combined.
Examples:
gtest-config --min-version=1.0 || echo "Insufficient Google Test version."
g++
$(
gtest-config
--cppflags
--cxxflags
)
-o foo.o -c foo.cpp
g++
$(
gtest-config
--ldflags
--libs
)
-o foo foo.o
# When using a built but not installed Google Test:
g++
$(
../../my_gtest_build/scripts/gtest-config ...
)
...
# When using an installed Google Test, but with installation overrides:
export GTEST_PREFIX="/opt"
g++
$(
gtest-config
--libdir
=
"/opt/lib64"
...
)
...
Help:
--usage brief usage information
--help display this help message
Installation Overrides:
--prefix=<dir> overrides the installation prefix
--exec-prefix=<dir> overrides the executable installation prefix
--libdir=<dir> overrides the library installation prefix
--includedir=<dir> overrides the header file installation prefix
Installation Queries:
--prefix installation prefix
--exec-prefix executable installation prefix
--libdir library installation directory
--includedir header file installation directory
--version the version of the Google Test installation
Version Queries:
--min-version=VERSION return 0 if the version is at least VERSION
--exact-version=VERSION return 0 if the version is exactly VERSION
--max-version=VERSION return 0 if the version is at most VERSION
Compilation Flag Queries:
--cppflags compile flags specific to the C-like preprocessors
--cxxflags compile flags appropriate for C++ programs
--ldflags linker flags
--libs libraries for linking
EOF
}
# This function bounds our version with a min and a max. It uses some clever
# POSIX-compliant variable expansion to portably do all the work in the shell
# and avoid any dependency on a particular "sed" or "awk" implementation.
# Notable is that it will only ever compare the first 3 components of versions.
# Further components will be cleanly stripped off. All versions must be
# unadorned, so "v1.0" will *not* work. The minimum version must be in $1, and
# the max in $2. TODO(chandlerc@google.com): If this ever breaks, we should
# investigate expanding this via autom4te from AS_VERSION_COMPARE rather than
# continuing to maintain our own shell version.
check_versions
()
{
major_version
=
${
version
%%.*
}
minor_version
=
"0"
point_version
=
"0"
if
test
"
${
version
#*.
}
"
!=
"
${
version
}
"
;
then
minor_version
=
${
version
#*.
}
minor_version
=
${
minor_version
%%.*
}
fi
if
test
"
${
version
#*.*.
}
"
!=
"
${
version
}
"
;
then
point_version
=
${
version
#*.*.
}
point_version
=
${
point_version
%%.*
}
fi
min_version
=
"
$1
"
min_major_version
=
${
min_version
%%.*
}
min_minor_version
=
"0"
min_point_version
=
"0"
if
test
"
${
min_version
#*.
}
"
!=
"
${
min_version
}
"
;
then
min_minor_version
=
${
min_version
#*.
}
min_minor_version
=
${
min_minor_version
%%.*
}
fi
if
test
"
${
min_version
#*.*.
}
"
!=
"
${
min_version
}
"
;
then
min_point_version
=
${
min_version
#*.*.
}
min_point_version
=
${
min_point_version
%%.*
}
fi
max_version
=
"
$2
"
max_major_version
=
${
max_version
%%.*
}
max_minor_version
=
"0"
max_point_version
=
"0"
if
test
"
${
max_version
#*.
}
"
!=
"
${
max_version
}
"
;
then
max_minor_version
=
${
max_version
#*.
}
max_minor_version
=
${
max_minor_version
%%.*
}
fi
if
test
"
${
max_version
#*.*.
}
"
!=
"
${
max_version
}
"
;
then
max_point_version
=
${
max_version
#*.*.
}
max_point_version
=
${
max_point_version
%%.*
}
fi
test
$((
$major_version
))
-lt
$((
$min_major_version
))
&&
exit
1
if
test
$((
$major_version
))
-eq
$((
$min_major_version
))
;
then
test
$((
$minor_version
))
-lt
$((
$min_minor_version
))
&&
exit
1
if
test
$((
$minor_version
))
-eq
$((
$min_minor_version
))
;
then
test
$((
$point_version
))
-lt
$((
$min_point_version
))
&&
exit
1
fi
fi
test
$((
$major_version
))
-gt
$((
$max_major_version
))
&&
exit
1
if
test
$((
$major_version
))
-eq
$((
$max_major_version
))
;
then
test
$((
$minor_version
))
-gt
$((
$max_minor_version
))
&&
exit
1
if
test
$((
$minor_version
))
-eq
$((
$max_minor_version
))
;
then
test
$((
$point_version
))
-gt
$((
$max_point_version
))
&&
exit
1
fi
fi
exit
0
}
# Show the usage line when no arguments are specified.
if
test
$#
-eq
0
;
then
show_usage
exit
1
fi
while
test
$#
-gt
0
;
do
case
$1
in
--usage
)
show_usage
;
exit
0
;;
--help
)
show_help
;
exit
0
;;
# Installation overrides
--prefix
=
*
)
GTEST_PREFIX
=
${
1
#--prefix=
}
;;
--exec-prefix
=
*
)
GTEST_EXEC_PREFIX
=
${
1
#--exec-prefix=
}
;;
--libdir
=
*
)
GTEST_LIBDIR
=
${
1
#--libdir=
}
;;
--includedir
=
*
)
GTEST_INCLUDEDIR
=
${
1
#--includedir=
}
;;
# Installation queries
--prefix
|
--exec-prefix
|
--libdir
|
--includedir
|
--version
)
if
test
-n
"
${
do_query
}
"
;
then
show_usage
exit
1
fi
do_query
=
${
1
#--
}
;;
# Version checking
--min-version
=
*
)
do_check_versions
=
yes
min_version
=
${
1
#--min-version=
}
;;
--max-version
=
*
)
do_check_versions
=
yes
max_version
=
${
1
#--max-version=
}
;;
--exact-version
=
*
)
do_check_versions
=
yes
exact_version
=
${
1
#--exact-version=
}
;;
# Compiler flag output
--cppflags
)
echo_cppflags
=
yes
;;
--cxxflags
)
echo_cxxflags
=
yes
;;
--ldflags
)
echo_ldflags
=
yes
;;
--libs
)
echo_libs
=
yes
;;
# Everything else is an error
*
)
show_usage
;
exit
1
;;
esac
shift
done
# These have defaults filled in by the configure script but can also be
# overridden by environment variables or command line parameters.
prefix
=
"
${
GTEST_PREFIX
:-
@prefix@
}
"
exec_prefix
=
"
${
GTEST_EXEC_PREFIX
:-
@exec_prefix@
}
"
libdir
=
"
${
GTEST_LIBDIR
:-
@libdir@
}
"
includedir
=
"
${
GTEST_INCLUDEDIR
:-
@includedir@
}
"
# We try and detect if our binary is not located at its installed location. If
# it's not, we provide variables pointing to the source and build tree rather
# than to the install tree. This allows building against a just-built gtest
# rather than an installed gtest.
bindir
=
"@bindir@"
this_relative_bindir
=
`
dirname
$0
`
this_bindir
=
`
cd
${
this_relative_bindir
}
;
pwd
-P
`
if
test
"
${
this_bindir
}
"
=
"
${
this_bindir
%
${
bindir
}}
"
;
then
# The path to the script doesn't end in the bindir sequence from Autoconf,
# assume that we are in a build tree.
build_dir
=
`
dirname
${
this_bindir
}
`
src_dir
=
`
cd
${
this_bindir
}
;
cd
@top_srcdir@
;
pwd
-P
`
# TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
# should work to remove it, and/or remove libtool altogether, replacing it
# with direct references to the library and a link path.
gtest_libs
=
"
${
build_dir
}
/lib/libgtest.la @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
gtest_ldflags
=
""
# We provide hooks to include from either the source or build dir, where the
# build dir is always preferred. This will potentially allow us to write
# build rules for generated headers and have them automatically be preferred
# over provided versions.
gtest_cppflags
=
"-I
${
build_dir
}
/include -I
${
src_dir
}
/include"
gtest_cxxflags
=
"@PTHREAD_CFLAGS@"
else
# We're using an installed gtest, although it may be staged under some
# prefix. Assume (as our own libraries do) that we can resolve the prefix,
# and are present in the dynamic link paths.
gtest_ldflags
=
"-L
${
libdir
}
"
gtest_libs
=
"-l
${
name
}
@PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
gtest_cppflags
=
"-I
${
includedir
}
"
gtest_cxxflags
=
"@PTHREAD_CFLAGS@"
fi
# Do an installation query if requested.
if
test
-n
"
$do_query
"
;
then
case
$do_query
in
prefix
)
echo
$prefix
;
exit
0
;;
exec-prefix
)
echo
$exec_prefix
;
exit
0
;;
libdir
)
echo
$libdir
;
exit
0
;;
includedir
)
echo
$includedir
;
exit
0
;;
version
)
echo
$version
;
exit
0
;;
*
)
show_usage
;
exit
1
;;
esac
fi
# Do a version check if requested.
if
test
"
$do_check_versions
"
=
"yes"
;
then
# Make sure we didn't receive a bad combination of parameters.
test
"
$echo_cppflags
"
=
"yes"
&&
show_usage
&&
exit
1
test
"
$echo_cxxflags
"
=
"yes"
&&
show_usage
&&
exit
1
test
"
$echo_ldflags
"
=
"yes"
&&
show_usage
&&
exit
1
test
"
$echo_libs
"
=
"yes"
&&
show_usage
&&
exit
1
if
test
"
$exact_version
"
!=
""
;
then
check_versions
$exact_version
$exact_version
# unreachable
else
check_versions
${
min_version
:-
0
.0.0
}
${
max_version
:-
9999
.9999.9999
}
# unreachable
fi
fi
# Do the output in the correct order so that these can be used in-line of
# a compiler invocation.
output
=
""
test
"
$echo_cppflags
"
=
"yes"
&&
output
=
"
$output
$gtest_cppflags
"
test
"
$echo_cxxflags
"
=
"yes"
&&
output
=
"
$output
$gtest_cxxflags
"
test
"
$echo_ldflags
"
=
"yes"
&&
output
=
"
$output
$gtest_ldflags
"
test
"
$echo_libs
"
=
"yes"
&&
output
=
"
$output
$gtest_libs
"
echo
$output
exit
0
test/gtest-1.7.0/scripts/pump.py
0 → 100755
View file @
9583d1ab
#!/usr/bin/env python
#
# Copyright 2008, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""pump v0.2.0 - Pretty Useful for Meta Programming.
A tool for preprocessor meta programming. Useful for generating
repetitive boilerplate code. Especially useful for writing C++
classes, functions, macros, and templates that need to work with
various number of arguments.
USAGE:
pump.py SOURCE_FILE
EXAMPLES:
pump.py foo.cc.pump
Converts foo.cc.pump to foo.cc.
GRAMMAR:
CODE ::= ATOMIC_CODE*
ATOMIC_CODE ::= $var ID = EXPRESSION
| $var ID = [[ CODE ]]
| $range ID EXPRESSION..EXPRESSION
| $for ID SEPARATOR [[ CODE ]]
| $($)
| $ID
| $(EXPRESSION)
| $if EXPRESSION [[ CODE ]] ELSE_BRANCH
| [[ CODE ]]
| RAW_CODE
SEPARATOR ::= RAW_CODE | EMPTY
ELSE_BRANCH ::= $else [[ CODE ]]
| $elif EXPRESSION [[ CODE ]] ELSE_BRANCH
| EMPTY
EXPRESSION has Python syntax.
"""
__author__
=
'wan@google.com (Zhanyong Wan)'
import
os
import
re
import
sys
TOKEN_TABLE
=
[
(
re
.
compile
(
r
'\$var\s+'
),
'$var'
),
(
re
.
compile
(
r
'\$elif\s+'
),
'$elif'
),
(
re
.
compile
(
r
'\$else\s+'
),
'$else'
),
(
re
.
compile
(
r
'\$for\s+'
),
'$for'
),
(
re
.
compile
(
r
'\$if\s+'
),
'$if'
),
(
re
.
compile
(
r
'\$range\s+'
),
'$range'
),
(
re
.
compile
(
r
'\$[_A-Za-z]\w*'
),
'$id'
),
(
re
.
compile
(
r
'\$\(\$\)'
),
'$($)'
),
(
re
.
compile
(
r
'\$'
),
'$'
),
(
re
.
compile
(
r
'\[\[\n?'
),
'[['
),
(
re
.
compile
(
r
'\]\]\n?'
),
']]'
),
]
class
Cursor
:
"""Represents a position (line and column) in a text file."""
def
__init__
(
self
,
line
=-
1
,
column
=-
1
):
self
.
line
=
line
self
.
column
=
column
def
__eq__
(
self
,
rhs
):
return
self
.
line
==
rhs
.
line
and
self
.
column
==
rhs
.
column
def
__ne__
(
self
,
rhs
):
return
not
self
==
rhs
def
__lt__
(
self
,
rhs
):
return
self
.
line
<
rhs
.
line
or
(
self
.
line
==
rhs
.
line
and
self
.
column
<
rhs
.
column
)
def
__le__
(
self
,
rhs
):
return
self
<
rhs
or
self
==
rhs
def
__gt__
(
self
,
rhs
):
return
rhs
<
self
def
__ge__
(
self
,
rhs
):
return
rhs
<=
self
def
__str__
(
self
):
if
self
==
Eof
():
return
'EOF'
else
:
return
'%s(%s)'
%
(
self
.
line
+
1
,
self
.
column
)
def
__add__
(
self
,
offset
):
return
Cursor
(
self
.
line
,
self
.
column
+
offset
)
def
__sub__
(
self
,
offset
):
return
Cursor
(
self
.
line
,
self
.
column
-
offset
)
def
Clone
(
self
):
"""Returns a copy of self."""
return
Cursor
(
self
.
line
,
self
.
column
)
# Special cursor to indicate the end-of-file.
def
Eof
():
"""Returns the special cursor to denote the end-of-file."""
return
Cursor
(
-
1
,
-
1
)
class
Token
:
"""Represents a token in a Pump source file."""
def
__init__
(
self
,
start
=
None
,
end
=
None
,
value
=
None
,
token_type
=
None
):
if
start
is
None
:
self
.
start
=
Eof
()
else
:
self
.
start
=
start
if
end
is
None
:
self
.
end
=
Eof
()
else
:
self
.
end
=
end
self
.
value
=
value
self
.
token_type
=
token_type
def
__str__
(
self
):
return
'Token @%s:
\'
%s
\'
type=%s'
%
(
self
.
start
,
self
.
value
,
self
.
token_type
)
def
Clone
(
self
):
"""Returns a copy of self."""
return
Token
(
self
.
start
.
Clone
(),
self
.
end
.
Clone
(),
self
.
value
,
self
.
token_type
)
def
StartsWith
(
lines
,
pos
,
string
):
"""Returns True iff the given position in lines starts with 'string'."""
return
lines
[
pos
.
line
][
pos
.
column
:].
startswith
(
string
)
def
FindFirstInLine
(
line
,
token_table
):
best_match_start
=
-
1
for
(
regex
,
token_type
)
in
token_table
:
m
=
regex
.
search
(
line
)
if
m
:
# We found regex in lines
if
best_match_start
<
0
or
m
.
start
()
<
best_match_start
:
best_match_start
=
m
.
start
()
best_match_length
=
m
.
end
()
-
m
.
start
()
best_match_token_type
=
token_type
if
best_match_start
<
0
:
return
None
return
(
best_match_start
,
best_match_length
,
best_match_token_type
)
def
FindFirst
(
lines
,
token_table
,
cursor
):
"""Finds the first occurrence of any string in strings in lines."""
start
=
cursor
.
Clone
()
cur_line_number
=
cursor
.
line
for
line
in
lines
[
start
.
line
:]:
if
cur_line_number
==
start
.
line
:
line
=
line
[
start
.
column
:]
m
=
FindFirstInLine
(
line
,
token_table
)
if
m
:
# We found a regex in line.
(
start_column
,
length
,
token_type
)
=
m
if
cur_line_number
==
start
.
line
:
start_column
+=
start
.
column
found_start
=
Cursor
(
cur_line_number
,
start_column
)
found_end
=
found_start
+
length
return
MakeToken
(
lines
,
found_start
,
found_end
,
token_type
)
cur_line_number
+=
1
# We failed to find str in lines
return
None
def
SubString
(
lines
,
start
,
end
):
"""Returns a substring in lines."""
if
end
==
Eof
():
end
=
Cursor
(
len
(
lines
)
-
1
,
len
(
lines
[
-
1
]))
if
start
>=
end
:
return
''
if
start
.
line
==
end
.
line
:
return
lines
[
start
.
line
][
start
.
column
:
end
.
column
]
result_lines
=
([
lines
[
start
.
line
][
start
.
column
:]]
+
lines
[
start
.
line
+
1
:
end
.
line
]
+
[
lines
[
end
.
line
][:
end
.
column
]])
return
''
.
join
(
result_lines
)
def
StripMetaComments
(
str
):
"""Strip meta comments from each line in the given string."""
# First, completely remove lines containing nothing but a meta
# comment, including the trailing \n.
str
=
re
.
sub
(
r
'^\s*\$\$.*\n'
,
''
,
str
)
# Then, remove meta comments from contentful lines.
return
re
.
sub
(
r
'\s*\$\$.*'
,
''
,
str
)
def
MakeToken
(
lines
,
start
,
end
,
token_type
):
"""Creates a new instance of Token."""
return
Token
(
start
,
end
,
SubString
(
lines
,
start
,
end
),
token_type
)
def
ParseToken
(
lines
,
pos
,
regex
,
token_type
):
line
=
lines
[
pos
.
line
][
pos
.
column
:]
m
=
regex
.
search
(
line
)
if
m
and
not
m
.
start
():
return
MakeToken
(
lines
,
pos
,
pos
+
m
.
end
(),
token_type
)
else
:
print
'ERROR: %s expected at %s.'
%
(
token_type
,
pos
)
sys
.
exit
(
1
)
ID_REGEX
=
re
.
compile
(
r
'[_A-Za-z]\w*'
)
EQ_REGEX
=
re
.
compile
(
r
'='
)
REST_OF_LINE_REGEX
=
re
.
compile
(
r
'.*?(?=$|\$\$)'
)
OPTIONAL_WHITE_SPACES_REGEX
=
re
.
compile
(
r
'\s*'
)
WHITE_SPACE_REGEX
=
re
.
compile
(
r
'\s'
)
DOT_DOT_REGEX
=
re
.
compile
(
r
'\.\.'
)
def
Skip
(
lines
,
pos
,
regex
):
line
=
lines
[
pos
.
line
][
pos
.
column
:]
m
=
re
.
search
(
regex
,
line
)
if
m
and
not
m
.
start
():
return
pos
+
m
.
end
()
else
:
return
pos
def
SkipUntil
(
lines
,
pos
,
regex
,
token_type
):
line
=
lines
[
pos
.
line
][
pos
.
column
:]
m
=
re
.
search
(
regex
,
line
)
if
m
:
return
pos
+
m
.
start
()
else
:
print
(
'ERROR: %s expected on line %s after column %s.'
%
(
token_type
,
pos
.
line
+
1
,
pos
.
column
))
sys
.
exit
(
1
)
def
ParseExpTokenInParens
(
lines
,
pos
):
def
ParseInParens
(
pos
):
pos
=
Skip
(
lines
,
pos
,
OPTIONAL_WHITE_SPACES_REGEX
)
pos
=
Skip
(
lines
,
pos
,
r
'\('
)
pos
=
Parse
(
pos
)
pos
=
Skip
(
lines
,
pos
,
r
'\)'
)
return
pos
def
Parse
(
pos
):
pos
=
SkipUntil
(
lines
,
pos
,
r
'\(|\)'
,
')'
)
if
SubString
(
lines
,
pos
,
pos
+
1
)
==
'('
:
pos
=
Parse
(
pos
+
1
)
pos
=
Skip
(
lines
,
pos
,
r
'\)'
)
return
Parse
(
pos
)
else
:
return
pos
start
=
pos
.
Clone
()
pos
=
ParseInParens
(
pos
)
return
MakeToken
(
lines
,
start
,
pos
,
'exp'
)
def
RStripNewLineFromToken
(
token
):
if
token
.
value
.
endswith
(
'
\n
'
):
return
Token
(
token
.
start
,
token
.
end
,
token
.
value
[:
-
1
],
token
.
token_type
)
else
:
return
token
def
TokenizeLines
(
lines
,
pos
):
while
True
:
found
=
FindFirst
(
lines
,
TOKEN_TABLE
,
pos
)
if
not
found
:
yield
MakeToken
(
lines
,
pos
,
Eof
(),
'code'
)
return
if
found
.
start
==
pos
:
prev_token
=
None
prev_token_rstripped
=
None
else
:
prev_token
=
MakeToken
(
lines
,
pos
,
found
.
start
,
'code'
)
prev_token_rstripped
=
RStripNewLineFromToken
(
prev_token
)
if
found
.
token_type
==
'$var'
:
if
prev_token_rstripped
:
yield
prev_token_rstripped
yield
found
id_token
=
ParseToken
(
lines
,
found
.
end
,
ID_REGEX
,
'id'
)
yield
id_token
pos
=
Skip
(
lines
,
id_token
.
end
,
OPTIONAL_WHITE_SPACES_REGEX
)
eq_token
=
ParseToken
(
lines
,
pos
,
EQ_REGEX
,
'='
)
yield
eq_token
pos
=
Skip
(
lines
,
eq_token
.
end
,
r
'\s*'
)
if
SubString
(
lines
,
pos
,
pos
+
2
)
!=
'[['
:
exp_token
=
ParseToken
(
lines
,
pos
,
REST_OF_LINE_REGEX
,
'exp'
)
yield
exp_token
pos
=
Cursor
(
exp_token
.
end
.
line
+
1
,
0
)
elif
found
.
token_type
==
'$for'
:
if
prev_token_rstripped
:
yield
prev_token_rstripped
yield
found
id_token
=
ParseToken
(
lines
,
found
.
end
,
ID_REGEX
,
'id'
)
yield
id_token
pos
=
Skip
(
lines
,
id_token
.
end
,
WHITE_SPACE_REGEX
)
elif
found
.
token_type
==
'$range'
:
if
prev_token_rstripped
:
yield
prev_token_rstripped
yield
found
id_token
=
ParseToken
(
lines
,
found
.
end
,
ID_REGEX
,
'id'
)
yield
id_token
pos
=
Skip
(
lines
,
id_token
.
end
,
OPTIONAL_WHITE_SPACES_REGEX
)
dots_pos
=
SkipUntil
(
lines
,
pos
,
DOT_DOT_REGEX
,
'..'
)
yield
MakeToken
(
lines
,
pos
,
dots_pos
,
'exp'
)
yield
MakeToken
(
lines
,
dots_pos
,
dots_pos
+
2
,
'..'
)
pos
=
dots_pos
+
2
new_pos
=
Cursor
(
pos
.
line
+
1
,
0
)
yield
MakeToken
(
lines
,
pos
,
new_pos
,
'exp'
)
pos
=
new_pos
elif
found
.
token_type
==
'$'
:
if
prev_token
:
yield
prev_token
yield
found
exp_token
=
ParseExpTokenInParens
(
lines
,
found
.
end
)
yield
exp_token
pos
=
exp_token
.
end
elif
(
found
.
token_type
==
']]'
or
found
.
token_type
==
'$if'
or
found
.
token_type
==
'$elif'
or
found
.
token_type
==
'$else'
):
if
prev_token_rstripped
:
yield
prev_token_rstripped
yield
found
pos
=
found
.
end
else
:
if
prev_token
:
yield
prev_token
yield
found
pos
=
found
.
end
def
Tokenize
(
s
):
"""A generator that yields the tokens in the given string."""
if
s
!=
''
:
lines
=
s
.
splitlines
(
True
)
for
token
in
TokenizeLines
(
lines
,
Cursor
(
0
,
0
)):
yield
token
class
CodeNode
:
def
__init__
(
self
,
atomic_code_list
=
None
):
self
.
atomic_code
=
atomic_code_list
class
VarNode
:
def
__init__
(
self
,
identifier
=
None
,
atomic_code
=
None
):
self
.
identifier
=
identifier
self
.
atomic_code
=
atomic_code
class
RangeNode
:
def
__init__
(
self
,
identifier
=
None
,
exp1
=
None
,
exp2
=
None
):
self
.
identifier
=
identifier
self
.
exp1
=
exp1
self
.
exp2
=
exp2
class
ForNode
:
def
__init__
(
self
,
identifier
=
None
,
sep
=
None
,
code
=
None
):
self
.
identifier
=
identifier
self
.
sep
=
sep
self
.
code
=
code
class
ElseNode
:
def
__init__
(
self
,
else_branch
=
None
):
self
.
else_branch
=
else_branch
class
IfNode
:
def
__init__
(
self
,
exp
=
None
,
then_branch
=
None
,
else_branch
=
None
):
self
.
exp
=
exp
self
.
then_branch
=
then_branch
self
.
else_branch
=
else_branch
class
RawCodeNode
:
def
__init__
(
self
,
token
=
None
):
self
.
raw_code
=
token
class
LiteralDollarNode
:
def
__init__
(
self
,
token
):
self
.
token
=
token
class
ExpNode
:
def
__init__
(
self
,
token
,
python_exp
):
self
.
token
=
token
self
.
python_exp
=
python_exp
def
PopFront
(
a_list
):
head
=
a_list
[
0
]
a_list
[:
1
]
=
[]
return
head
def
PushFront
(
a_list
,
elem
):
a_list
[:
0
]
=
[
elem
]
def
PopToken
(
a_list
,
token_type
=
None
):
token
=
PopFront
(
a_list
)
if
token_type
is
not
None
and
token
.
token_type
!=
token_type
:
print
'ERROR: %s expected at %s'
%
(
token_type
,
token
.
start
)
print
'ERROR: %s found instead'
%
(
token
,)
sys
.
exit
(
1
)
return
token
def
PeekToken
(
a_list
):
if
not
a_list
:
return
None
return
a_list
[
0
]
def
ParseExpNode
(
token
):
python_exp
=
re
.
sub
(
r
'([_A-Za-z]\w*)'
,
r
'self.GetValue("\1")'
,
token
.
value
)
return
ExpNode
(
token
,
python_exp
)
def
ParseElseNode
(
tokens
):
def
Pop
(
token_type
=
None
):
return
PopToken
(
tokens
,
token_type
)
next
=
PeekToken
(
tokens
)
if
not
next
:
return
None
if
next
.
token_type
==
'$else'
:
Pop
(
'$else'
)
Pop
(
'[['
)
code_node
=
ParseCodeNode
(
tokens
)
Pop
(
']]'
)
return
code_node
elif
next
.
token_type
==
'$elif'
:
Pop
(
'$elif'
)
exp
=
Pop
(
'code'
)
Pop
(
'[['
)
code_node
=
ParseCodeNode
(
tokens
)
Pop
(
']]'
)
inner_else_node
=
ParseElseNode
(
tokens
)
return
CodeNode
([
IfNode
(
ParseExpNode
(
exp
),
code_node
,
inner_else_node
)])
elif
not
next
.
value
.
strip
():
Pop
(
'code'
)
return
ParseElseNode
(
tokens
)
else
:
return
None
def
ParseAtomicCodeNode
(
tokens
):
def
Pop
(
token_type
=
None
):
return
PopToken
(
tokens
,
token_type
)
head
=
PopFront
(
tokens
)
t
=
head
.
token_type
if
t
==
'code'
:
return
RawCodeNode
(
head
)
elif
t
==
'$var'
:
id_token
=
Pop
(
'id'
)
Pop
(
'='
)
next
=
PeekToken
(
tokens
)
if
next
.
token_type
==
'exp'
:
exp_token
=
Pop
()
return
VarNode
(
id_token
,
ParseExpNode
(
exp_token
))
Pop
(
'[['
)
code_node
=
ParseCodeNode
(
tokens
)
Pop
(
']]'
)
return
VarNode
(
id_token
,
code_node
)
elif
t
==
'$for'
:
id_token
=
Pop
(
'id'
)
next_token
=
PeekToken
(
tokens
)
if
next_token
.
token_type
==
'code'
:
sep_token
=
next_token
Pop
(
'code'
)
else
:
sep_token
=
None
Pop
(
'[['
)
code_node
=
ParseCodeNode
(
tokens
)
Pop
(
']]'
)
return
ForNode
(
id_token
,
sep_token
,
code_node
)
elif
t
==
'$if'
:
exp_token
=
Pop
(
'code'
)
Pop
(
'[['
)
code_node
=
ParseCodeNode
(
tokens
)
Pop
(
']]'
)
else_node
=
ParseElseNode
(
tokens
)
return
IfNode
(
ParseExpNode
(
exp_token
),
code_node
,
else_node
)
elif
t
==
'$range'
:
id_token
=
Pop
(
'id'
)
exp1_token
=
Pop
(
'exp'
)
Pop
(
'..'
)
exp2_token
=
Pop
(
'exp'
)
return
RangeNode
(
id_token
,
ParseExpNode
(
exp1_token
),
ParseExpNode
(
exp2_token
))
elif
t
==
'$id'
:
return
ParseExpNode
(
Token
(
head
.
start
+
1
,
head
.
end
,
head
.
value
[
1
:],
'id'
))
elif
t
==
'$($)'
:
return
LiteralDollarNode
(
head
)
elif
t
==
'$'
:
exp_token
=
Pop
(
'exp'
)
return
ParseExpNode
(
exp_token
)
elif
t
==
'[['
:
code_node
=
ParseCodeNode
(
tokens
)
Pop
(
']]'
)
return
code_node
else
:
PushFront
(
tokens
,
head
)
return
None
def
ParseCodeNode
(
tokens
):
atomic_code_list
=
[]
while
True
:
if
not
tokens
:
break
atomic_code_node
=
ParseAtomicCodeNode
(
tokens
)
if
atomic_code_node
:
atomic_code_list
.
append
(
atomic_code_node
)
else
:
break
return
CodeNode
(
atomic_code_list
)
def
ParseToAST
(
pump_src_text
):
"""Convert the given Pump source text into an AST."""
tokens
=
list
(
Tokenize
(
pump_src_text
))
code_node
=
ParseCodeNode
(
tokens
)
return
code_node
class
Env
:
def
__init__
(
self
):
self
.
variables
=
[]
self
.
ranges
=
[]
def
Clone
(
self
):
clone
=
Env
()
clone
.
variables
=
self
.
variables
[:]
clone
.
ranges
=
self
.
ranges
[:]
return
clone
def
PushVariable
(
self
,
var
,
value
):
# If value looks like an int, store it as an int.
try
:
int_value
=
int
(
value
)
if
(
'%s'
%
int_value
)
==
value
:
value
=
int_value
except
Exception
:
pass
self
.
variables
[:
0
]
=
[(
var
,
value
)]
def
PopVariable
(
self
):
self
.
variables
[:
1
]
=
[]
def
PushRange
(
self
,
var
,
lower
,
upper
):
self
.
ranges
[:
0
]
=
[(
var
,
lower
,
upper
)]
def
PopRange
(
self
):
self
.
ranges
[:
1
]
=
[]
def
GetValue
(
self
,
identifier
):
for
(
var
,
value
)
in
self
.
variables
:
if
identifier
==
var
:
return
value
print
'ERROR: meta variable %s is undefined.'
%
(
identifier
,)
sys
.
exit
(
1
)
def
EvalExp
(
self
,
exp
):
try
:
result
=
eval
(
exp
.
python_exp
)
except
Exception
,
e
:
print
'ERROR: caught exception %s: %s'
%
(
e
.
__class__
.
__name__
,
e
)
print
(
'ERROR: failed to evaluate meta expression %s at %s'
%
(
exp
.
python_exp
,
exp
.
token
.
start
))
sys
.
exit
(
1
)
return
result
def
GetRange
(
self
,
identifier
):
for
(
var
,
lower
,
upper
)
in
self
.
ranges
:
if
identifier
==
var
:
return
(
lower
,
upper
)
print
'ERROR: range %s is undefined.'
%
(
identifier
,)
sys
.
exit
(
1
)
class
Output
:
def
__init__
(
self
):
self
.
string
=
''
def
GetLastLine
(
self
):
index
=
self
.
string
.
rfind
(
'
\n
'
)
if
index
<
0
:
return
''
return
self
.
string
[
index
+
1
:]
def
Append
(
self
,
s
):
self
.
string
+=
s
def
RunAtomicCode
(
env
,
node
,
output
):
if
isinstance
(
node
,
VarNode
):
identifier
=
node
.
identifier
.
value
.
strip
()
result
=
Output
()
RunAtomicCode
(
env
.
Clone
(),
node
.
atomic_code
,
result
)
value
=
result
.
string
env
.
PushVariable
(
identifier
,
value
)
elif
isinstance
(
node
,
RangeNode
):
identifier
=
node
.
identifier
.
value
.
strip
()
lower
=
int
(
env
.
EvalExp
(
node
.
exp1
))
upper
=
int
(
env
.
EvalExp
(
node
.
exp2
))
env
.
PushRange
(
identifier
,
lower
,
upper
)
elif
isinstance
(
node
,
ForNode
):
identifier
=
node
.
identifier
.
value
.
strip
()
if
node
.
sep
is
None
:
sep
=
''
else
:
sep
=
node
.
sep
.
value
(
lower
,
upper
)
=
env
.
GetRange
(
identifier
)
for
i
in
range
(
lower
,
upper
+
1
):
new_env
=
env
.
Clone
()
new_env
.
PushVariable
(
identifier
,
i
)
RunCode
(
new_env
,
node
.
code
,
output
)
if
i
!=
upper
:
output
.
Append
(
sep
)
elif
isinstance
(
node
,
RawCodeNode
):
output
.
Append
(
node
.
raw_code
.
value
)
elif
isinstance
(
node
,
IfNode
):
cond
=
env
.
EvalExp
(
node
.
exp
)
if
cond
:
RunCode
(
env
.
Clone
(),
node
.
then_branch
,
output
)
elif
node
.
else_branch
is
not
None
:
RunCode
(
env
.
Clone
(),
node
.
else_branch
,
output
)
elif
isinstance
(
node
,
ExpNode
):
value
=
env
.
EvalExp
(
node
)
output
.
Append
(
'%s'
%
(
value
,))
elif
isinstance
(
node
,
LiteralDollarNode
):
output
.
Append
(
'$'
)
elif
isinstance
(
node
,
CodeNode
):
RunCode
(
env
.
Clone
(),
node
,
output
)
else
:
print
'BAD'
print
node
sys
.
exit
(
1
)
def
RunCode
(
env
,
code_node
,
output
):
for
atomic_code
in
code_node
.
atomic_code
:
RunAtomicCode
(
env
,
atomic_code
,
output
)
def
IsSingleLineComment
(
cur_line
):
return
'//'
in
cur_line
def
IsInPreprocessorDirective
(
prev_lines
,
cur_line
):
if
cur_line
.
lstrip
().
startswith
(
'#'
):
return
True
return
prev_lines
and
prev_lines
[
-
1
].
endswith
(
'
\\
'
)
def
WrapComment
(
line
,
output
):
loc
=
line
.
find
(
'//'
)
before_comment
=
line
[:
loc
].
rstrip
()
if
before_comment
==
''
:
indent
=
loc
else
:
output
.
append
(
before_comment
)
indent
=
len
(
before_comment
)
-
len
(
before_comment
.
lstrip
())
prefix
=
indent
*
' '
+
'// '
max_len
=
80
-
len
(
prefix
)
comment
=
line
[
loc
+
2
:].
strip
()
segs
=
[
seg
for
seg
in
re
.
split
(
r
'(\w+\W*)'
,
comment
)
if
seg
!=
''
]
cur_line
=
''
for
seg
in
segs
:
if
len
((
cur_line
+
seg
).
rstrip
())
<
max_len
:
cur_line
+=
seg
else
:
if
cur_line
.
strip
()
!=
''
:
output
.
append
(
prefix
+
cur_line
.
rstrip
())
cur_line
=
seg
.
lstrip
()
if
cur_line
.
strip
()
!=
''
:
output
.
append
(
prefix
+
cur_line
.
strip
())
def
WrapCode
(
line
,
line_concat
,
output
):
indent
=
len
(
line
)
-
len
(
line
.
lstrip
())
prefix
=
indent
*
' '
# Prefix of the current line
max_len
=
80
-
indent
-
len
(
line_concat
)
# Maximum length of the current line
new_prefix
=
prefix
+
4
*
' '
# Prefix of a continuation line
new_max_len
=
max_len
-
4
# Maximum length of a continuation line
# Prefers to wrap a line after a ',' or ';'.
segs
=
[
seg
for
seg
in
re
.
split
(
r
'([^,;]+[,;]?)'
,
line
.
strip
())
if
seg
!=
''
]
cur_line
=
''
# The current line without leading spaces.
for
seg
in
segs
:
# If the line is still too long, wrap at a space.
while
cur_line
==
''
and
len
(
seg
.
strip
())
>
max_len
:
seg
=
seg
.
lstrip
()
split_at
=
seg
.
rfind
(
' '
,
0
,
max_len
)
output
.
append
(
prefix
+
seg
[:
split_at
].
strip
()
+
line_concat
)
seg
=
seg
[
split_at
+
1
:]
prefix
=
new_prefix
max_len
=
new_max_len
if
len
((
cur_line
+
seg
).
rstrip
())
<
max_len
:
cur_line
=
(
cur_line
+
seg
).
lstrip
()
else
:
output
.
append
(
prefix
+
cur_line
.
rstrip
()
+
line_concat
)
prefix
=
new_prefix
max_len
=
new_max_len
cur_line
=
seg
.
lstrip
()
if
cur_line
.
strip
()
!=
''
:
output
.
append
(
prefix
+
cur_line
.
strip
())
def
WrapPreprocessorDirective
(
line
,
output
):
WrapCode
(
line
,
'
\\
'
,
output
)
def
WrapPlainCode
(
line
,
output
):
WrapCode
(
line
,
''
,
output
)
def
IsMultiLineIWYUPragma
(
line
):
return
re
.
search
(
r
'/\* IWYU pragma: '
,
line
)
def
IsHeaderGuardIncludeOrOneLineIWYUPragma
(
line
):
return
(
re
.
match
(
r
'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$'
,
line
)
or
re
.
match
(
r
'^#include\s'
,
line
)
or
# Don't break IWYU pragmas, either; that causes iwyu.py problems.
re
.
search
(
r
'// IWYU pragma: '
,
line
))
def
WrapLongLine
(
line
,
output
):
line
=
line
.
rstrip
()
if
len
(
line
)
<=
80
:
output
.
append
(
line
)
elif
IsSingleLineComment
(
line
):
if
IsHeaderGuardIncludeOrOneLineIWYUPragma
(
line
):
# The style guide made an exception to allow long header guard lines,
# includes and IWYU pragmas.
output
.
append
(
line
)
else
:
WrapComment
(
line
,
output
)
elif
IsInPreprocessorDirective
(
output
,
line
):
if
IsHeaderGuardIncludeOrOneLineIWYUPragma
(
line
):
# The style guide made an exception to allow long header guard lines,
# includes and IWYU pragmas.
output
.
append
(
line
)
else
:
WrapPreprocessorDirective
(
line
,
output
)
elif
IsMultiLineIWYUPragma
(
line
):
output
.
append
(
line
)
else
:
WrapPlainCode
(
line
,
output
)
def
BeautifyCode
(
string
):
lines
=
string
.
splitlines
()
output
=
[]
for
line
in
lines
:
WrapLongLine
(
line
,
output
)
output2
=
[
line
.
rstrip
()
for
line
in
output
]
return
'
\n
'
.
join
(
output2
)
+
'
\n
'
def
ConvertFromPumpSource
(
src_text
):
"""Return the text generated from the given Pump source text."""
ast
=
ParseToAST
(
StripMetaComments
(
src_text
))
output
=
Output
()
RunCode
(
Env
(),
ast
,
output
)
return
BeautifyCode
(
output
.
string
)
def
main
(
argv
):
if
len
(
argv
)
==
1
:
print
__doc__
sys
.
exit
(
1
)
file_path
=
argv
[
-
1
]
output_str
=
ConvertFromPumpSource
(
file
(
file_path
,
'r'
).
read
())
if
file_path
.
endswith
(
'.pump'
):
output_file_path
=
file_path
[:
-
5
]
else
:
output_file_path
=
'-'
if
output_file_path
==
'-'
:
print
output_str
,
else
:
output_file
=
file
(
output_file_path
,
'w'
)
output_file
.
write
(
'// This file was GENERATED by command:
\n
'
)
output_file
.
write
(
'// %s %s
\n
'
%
(
os
.
path
.
basename
(
__file__
),
os
.
path
.
basename
(
file_path
)))
output_file
.
write
(
'// DO NOT EDIT BY HAND!!!
\n\n
'
)
output_file
.
write
(
output_str
)
output_file
.
close
()
if
__name__
==
'__main__'
:
main
(
sys
.
argv
)
test/gtest-1.7.0/scripts/test/Makefile
0 → 100644
View file @
9583d1ab
# A Makefile for fusing Google Test and building a sample test against it.
#
# SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make check - makes everything and runs the built sample test.
# make clean - removes all files generated by make.
# Points to the root of fused Google Test, relative to where this file is.
FUSED_GTEST_DIR
=
output
# Paths to the fused gtest files.
FUSED_GTEST_H
=
$(FUSED_GTEST_DIR)
/gtest/gtest.h
FUSED_GTEST_ALL_CC
=
$(FUSED_GTEST_DIR)
/gtest/gtest-all.cc
# Where to find the sample test.
SAMPLE_DIR
=
../../samples
# Where to find gtest_main.cc.
GTEST_MAIN_CC
=
../../src/gtest_main.cc
# Flags passed to the preprocessor.
# We have no idea here whether pthreads is available in the system, so
# disable its use.
CPPFLAGS
+=
-I
$(FUSED_GTEST_DIR)
-DGTEST_HAS_PTHREAD
=
0
# Flags passed to the C++ compiler.
CXXFLAGS
+=
-g
all
:
sample1_unittest
check
:
all
./sample1_unittest
clean
:
rm
-rf
$(FUSED_GTEST_DIR)
sample1_unittest
*
.o
$(FUSED_GTEST_H)
:
../fuse_gtest_files.py
$(FUSED_GTEST_DIR)
$(FUSED_GTEST_ALL_CC)
:
../fuse_gtest_files.py
$(FUSED_GTEST_DIR)
gtest-all.o
:
$(FUSED_GTEST_H) $(FUSED_GTEST_ALL_CC)
$(CXX)
$(CPPFLAGS)
$(CXXFLAGS)
-c
$(FUSED_GTEST_DIR)
/gtest/gtest-all.cc
gtest_main.o
:
$(FUSED_GTEST_H) $(GTEST_MAIN_CC)
$(CXX)
$(CPPFLAGS)
$(CXXFLAGS)
-c
$(GTEST_MAIN_CC)
sample1.o
:
$(SAMPLE_DIR)/sample1.cc $(SAMPLE_DIR)/sample1.h
$(CXX)
$(CPPFLAGS)
$(CXXFLAGS)
-c
$(SAMPLE_DIR)
/sample1.cc
sample1_unittest.o
:
$(SAMPLE_DIR)/sample1_unittest.cc
\
$(SAMPLE_DIR)/sample1.h $(FUSED_GTEST_H)
$(CXX)
$(CPPFLAGS)
$(CXXFLAGS)
-c
$(SAMPLE_DIR)
/sample1_unittest.cc
sample1_unittest
:
sample1.o sample1_unittest.o gtest-all.o gtest_main.o
$(CXX)
$(CPPFLAGS)
$(CXXFLAGS)
$^
-o
$@
test/gtest-1.7.0/src/gtest-all.cc
0 → 100644
View file @
9583d1ab
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: mheule@google.com (Markus Heule)
//
// Google C++ Testing Framework (Google Test)
//
// Sometimes it's desirable to build Google Test by compiling a single file.
// This file serves this purpose.
// This line ensures that gtest.h can be compiled on its own, even
// when it's fused.
#include "gtest/gtest.h"
// The following lines pull in the real gtest *.cc files.
#include "src/gtest.cc"
#include "src/gtest-death-test.cc"
#include "src/gtest-filepath.cc"
#include "src/gtest-port.cc"
#include "src/gtest-printers.cc"
#include "src/gtest-test-part.cc"
#include "src/gtest-typed-test.cc"
test/gtest-1.7.0/src/gtest-death-test.cc
0 → 100644
View file @
9583d1ab
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
//
// This file implements death tests.
#include "gtest/gtest-death-test.h"
#include "gtest/internal/gtest-port.h"
#if GTEST_HAS_DEATH_TEST
# if GTEST_OS_MAC
# include <crt_externs.h>
# endif // GTEST_OS_MAC
# include <errno.h>
# include <fcntl.h>
# include <limits.h>
# if GTEST_OS_LINUX
# include <signal.h>
# endif // GTEST_OS_LINUX
# include <stdarg.h>
# if GTEST_OS_WINDOWS
# include <windows.h>
# else
# include <sys/mman.h>
# include <sys/wait.h>
# endif // GTEST_OS_WINDOWS
# if GTEST_OS_QNX
# include <spawn.h>
# endif // GTEST_OS_QNX
#endif // GTEST_HAS_DEATH_TEST
#include "gtest/gtest-message.h"
#include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to
// prevent a user from accidentally including gtest-internal-inl.h in
// his code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
namespace
testing
{
// Constants.
// The default death test style.
static
const
char
kDefaultDeathTestStyle
[]
=
"fast"
;
GTEST_DEFINE_string_
(
death_test_style
,
internal
::
StringFromGTestEnv
(
"death_test_style"
,
kDefaultDeathTestStyle
),
"Indicates how to run a death test in a forked child process: "
"
\"
threadsafe
\"
(child process re-executes the test binary "
"from the beginning, running only the specific death test) or "
"
\"
fast
\"
(child process runs the death test immediately "
"after forking)."
);
GTEST_DEFINE_bool_
(
death_test_use_fork
,
internal
::
BoolFromGTestEnv
(
"death_test_use_fork"
,
false
),
"Instructs to use fork()/_exit() instead of clone() in death tests. "
"Ignored and always uses fork() on POSIX systems where clone() is not "
"implemented. Useful when running under valgrind or similar tools if "
"those do not support clone(). Valgrind 3.3.1 will just fail if "
"it sees an unsupported combination of clone() flags. "
"It is not recommended to use this flag w/o valgrind though it will "
"work in 99% of the cases. Once valgrind is fixed, this flag will "
"most likely be removed."
);
namespace
internal
{
GTEST_DEFINE_string_
(
internal_run_death_test
,
""
,
"Indicates the file, line number, temporal index of "
"the single death test to run, and a file descriptor to "
"which a success code may be sent, all separated by "
"the '|' characters. This flag is specified if and only if the current "
"process is a sub-process launched for running a thread-safe "
"death test. FOR INTERNAL USE ONLY."
);
}
// namespace internal
#if GTEST_HAS_DEATH_TEST
namespace
internal
{
// Valid only for fast death tests. Indicates the code is running in the
// child process of a fast style death test.
static
bool
g_in_fast_death_test_child
=
false
;
// Returns a Boolean value indicating whether the caller is currently
// executing in the context of the death test child process. Tools such as
// Valgrind heap checkers may need this to modify their behavior in death
// tests. IMPORTANT: This is an internal utility. Using it may break the
// implementation of death tests. User code MUST NOT use it.
bool
InDeathTestChild
()
{
# if GTEST_OS_WINDOWS
// On Windows, death tests are thread-safe regardless of the value of the
// death_test_style flag.
return
!
GTEST_FLAG
(
internal_run_death_test
).
empty
();
# else
if
(
GTEST_FLAG
(
death_test_style
)
==
"threadsafe"
)
return
!
GTEST_FLAG
(
internal_run_death_test
).
empty
();
else
return
g_in_fast_death_test_child
;
#endif
}
}
// namespace internal
// ExitedWithCode constructor.
ExitedWithCode
::
ExitedWithCode
(
int
exit_code
)
:
exit_code_
(
exit_code
)
{
}
// ExitedWithCode function-call operator.
bool
ExitedWithCode
::
operator
()(
int
exit_status
)
const
{
# if GTEST_OS_WINDOWS
return
exit_status
==
exit_code_
;
# else
return
WIFEXITED
(
exit_status
)
&&
WEXITSTATUS
(
exit_status
)
==
exit_code_
;
# endif // GTEST_OS_WINDOWS
}
# if !GTEST_OS_WINDOWS
// KilledBySignal constructor.
KilledBySignal
::
KilledBySignal
(
int
signum
)
:
signum_
(
signum
)
{
}
// KilledBySignal function-call operator.
bool
KilledBySignal
::
operator
()(
int
exit_status
)
const
{
return
WIFSIGNALED
(
exit_status
)
&&
WTERMSIG
(
exit_status
)
==
signum_
;
}
# endif // !GTEST_OS_WINDOWS
namespace
internal
{
// Utilities needed for death tests.
// Generates a textual description of a given exit code, in the format
// specified by wait(2).
static
std
::
string
ExitSummary
(
int
exit_code
)
{
Message
m
;
# if GTEST_OS_WINDOWS
m
<<
"Exited with exit status "
<<
exit_code
;
# else
if
(
WIFEXITED
(
exit_code
))
{
m
<<
"Exited with exit status "
<<
WEXITSTATUS
(
exit_code
);
}
else
if
(
WIFSIGNALED
(
exit_code
))
{
m
<<
"Terminated by signal "
<<
WTERMSIG
(
exit_code
);
}
# ifdef WCOREDUMP
if
(
WCOREDUMP
(
exit_code
))
{
m
<<
" (core dumped)"
;
}
# endif
# endif // GTEST_OS_WINDOWS
return
m
.
GetString
();
}
// Returns true if exit_status describes a process that was terminated
// by a signal, or exited normally with a nonzero exit code.
bool
ExitedUnsuccessfully
(
int
exit_status
)
{
return
!
ExitedWithCode
(
0
)(
exit_status
);
}
# if !GTEST_OS_WINDOWS
// Generates a textual failure message when a death test finds more than
// one thread running, or cannot determine the number of threads, prior
// to executing the given statement. It is the responsibility of the
// caller not to pass a thread_count of 1.
static
std
::
string
DeathTestThreadWarning
(
size_t
thread_count
)
{
Message
msg
;
msg
<<
"Death tests use fork(), which is unsafe particularly"
<<
" in a threaded context. For this test, "
<<
GTEST_NAME_
<<
" "
;
if
(
thread_count
==
0
)
msg
<<
"couldn't detect the number of threads."
;
else
msg
<<
"detected "
<<
thread_count
<<
" threads."
;
return
msg
.
GetString
();
}
# endif // !GTEST_OS_WINDOWS
// Flag characters for reporting a death test that did not die.
static
const
char
kDeathTestLived
=
'L'
;
static
const
char
kDeathTestReturned
=
'R'
;
static
const
char
kDeathTestThrew
=
'T'
;
static
const
char
kDeathTestInternalError
=
'I'
;
// An enumeration describing all of the possible ways that a death test can
// conclude. DIED means that the process died while executing the test
// code; LIVED means that process lived beyond the end of the test code;
// RETURNED means that the test statement attempted to execute a return
// statement, which is not allowed; THREW means that the test statement
// returned control by throwing an exception. IN_PROGRESS means the test
// has not yet concluded.
// TODO(vladl@google.com): Unify names and possibly values for
// AbortReason, DeathTestOutcome, and flag characters above.
enum
DeathTestOutcome
{
IN_PROGRESS
,
DIED
,
LIVED
,
RETURNED
,
THREW
};
// Routine for aborting the program which is safe to call from an
// exec-style death test child process, in which case the error
// message is propagated back to the parent process. Otherwise, the
// message is simply printed to stderr. In either case, the program
// then exits with status 1.
void
DeathTestAbort
(
const
std
::
string
&
message
)
{
// On a POSIX system, this function may be called from a threadsafe-style
// death test child process, which operates on a very small stack. Use
// the heap for any additional non-minuscule memory requirements.
const
InternalRunDeathTestFlag
*
const
flag
=
GetUnitTestImpl
()
->
internal_run_death_test_flag
();
if
(
flag
!=
NULL
)
{
FILE
*
parent
=
posix
::
FDOpen
(
flag
->
write_fd
(),
"w"
);
fputc
(
kDeathTestInternalError
,
parent
);
fprintf
(
parent
,
"%s"
,
message
.
c_str
());
fflush
(
parent
);
_exit
(
1
);
}
else
{
fprintf
(
stderr
,
"%s"
,
message
.
c_str
());
fflush
(
stderr
);
posix
::
Abort
();
}
}
// A replacement for CHECK that calls DeathTestAbort if the assertion
// fails.
# define GTEST_DEATH_TEST_CHECK_(expression) \
do { \
if (!::testing::internal::IsTrue(expression)) { \
DeathTestAbort( \
::std::string("CHECK failed: File ") + __FILE__ + ", line " \
+ ::testing::internal::StreamableToString(__LINE__) + ": " \
+ #expression); \
} \
} while (::testing::internal::AlwaysFalse())
// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
// evaluating any system call that fulfills two conditions: it must return
// -1 on failure, and set errno to EINTR when it is interrupted and
// should be tried again. The macro expands to a loop that repeatedly
// evaluates the expression as long as it evaluates to -1 and sets
// errno to EINTR. If the expression evaluates to -1 but errno is
// something other than EINTR, DeathTestAbort is called.
# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
do { \
int gtest_retval; \
do { \
gtest_retval = (expression); \
} while (gtest_retval == -1 && errno == EINTR); \
if (gtest_retval == -1) { \
DeathTestAbort( \
::std::string("CHECK failed: File ") + __FILE__ + ", line " \
+ ::testing::internal::StreamableToString(__LINE__) + ": " \
+ #expression + " != -1"); \
} \
} while (::testing::internal::AlwaysFalse())
// Returns the message describing the last system error in errno.
std
::
string
GetLastErrnoDescription
()
{
return
errno
==
0
?
""
:
posix
::
StrError
(
errno
);
}
// This is called from a death test parent process to read a failure
// message from the death test child process and log it with the FATAL
// severity. On Windows, the message is read from a pipe handle. On other
// platforms, it is read from a file descriptor.
static
void
FailFromInternalError
(
int
fd
)
{
Message
error
;
char
buffer
[
256
];
int
num_read
;
do
{
while
((
num_read
=
posix
::
Read
(
fd
,
buffer
,
255
))
>
0
)
{
buffer
[
num_read
]
=
'\0'
;
error
<<
buffer
;
}
}
while
(
num_read
==
-
1
&&
errno
==
EINTR
);
if
(
num_read
==
0
)
{
GTEST_LOG_
(
FATAL
)
<<
error
.
GetString
();
}
else
{
const
int
last_error
=
errno
;
GTEST_LOG_
(
FATAL
)
<<
"Error while reading death test internal: "
<<
GetLastErrnoDescription
()
<<
" ["
<<
last_error
<<
"]"
;
}
}
// Death test constructor. Increments the running death test count
// for the current test.
DeathTest
::
DeathTest
()
{
TestInfo
*
const
info
=
GetUnitTestImpl
()
->
current_test_info
();
if
(
info
==
NULL
)
{
DeathTestAbort
(
"Cannot run a death test outside of a TEST or "
"TEST_F construct"
);
}
}
// Creates and returns a death test by dispatching to the current
// death test factory.
bool
DeathTest
::
Create
(
const
char
*
statement
,
const
RE
*
regex
,
const
char
*
file
,
int
line
,
DeathTest
**
test
)
{
return
GetUnitTestImpl
()
->
death_test_factory
()
->
Create
(
statement
,
regex
,
file
,
line
,
test
);
}
const
char
*
DeathTest
::
LastMessage
()
{
return
last_death_test_message_
.
c_str
();
}
void
DeathTest
::
set_last_death_test_message
(
const
std
::
string
&
message
)
{
last_death_test_message_
=
message
;
}
std
::
string
DeathTest
::
last_death_test_message_
;
// Provides cross platform implementation for some death functionality.
class
DeathTestImpl
:
public
DeathTest
{
protected:
DeathTestImpl
(
const
char
*
a_statement
,
const
RE
*
a_regex
)
:
statement_
(
a_statement
),
regex_
(
a_regex
),
spawned_
(
false
),
status_
(
-
1
),
outcome_
(
IN_PROGRESS
),
read_fd_
(
-
1
),
write_fd_
(
-
1
)
{}
// read_fd_ is expected to be closed and cleared by a derived class.
~
DeathTestImpl
()
{
GTEST_DEATH_TEST_CHECK_
(
read_fd_
==
-
1
);
}
void
Abort
(
AbortReason
reason
);
virtual
bool
Passed
(
bool
status_ok
);
const
char
*
statement
()
const
{
return
statement_
;
}
const
RE
*
regex
()
const
{
return
regex_
;
}
bool
spawned
()
const
{
return
spawned_
;
}
void
set_spawned
(
bool
is_spawned
)
{
spawned_
=
is_spawned
;
}
int
status
()
const
{
return
status_
;
}
void
set_status
(
int
a_status
)
{
status_
=
a_status
;
}
DeathTestOutcome
outcome
()
const
{
return
outcome_
;
}
void
set_outcome
(
DeathTestOutcome
an_outcome
)
{
outcome_
=
an_outcome
;
}
int
read_fd
()
const
{
return
read_fd_
;
}
void
set_read_fd
(
int
fd
)
{
read_fd_
=
fd
;
}
int
write_fd
()
const
{
return
write_fd_
;
}
void
set_write_fd
(
int
fd
)
{
write_fd_
=
fd
;
}
// Called in the parent process only. Reads the result code of the death
// test child process via a pipe, interprets it to set the outcome_
// member, and closes read_fd_. Outputs diagnostics and terminates in
// case of unexpected codes.
void
ReadAndInterpretStatusByte
();
private:
// The textual content of the code this object is testing. This class
// doesn't own this string and should not attempt to delete it.
const
char
*
const
statement_
;
// The regular expression which test output must match. DeathTestImpl
// doesn't own this object and should not attempt to delete it.
const
RE
*
const
regex_
;
// True if the death test child process has been successfully spawned.
bool
spawned_
;
// The exit status of the child process.
int
status_
;
// How the death test concluded.
DeathTestOutcome
outcome_
;
// Descriptor to the read end of the pipe to the child process. It is
// always -1 in the child process. The child keeps its write end of the
// pipe in write_fd_.
int
read_fd_
;
// Descriptor to the child's write end of the pipe to the parent process.
// It is always -1 in the parent process. The parent keeps its end of the
// pipe in read_fd_.
int
write_fd_
;
};
// Called in the parent process only. Reads the result code of the death
// test child process via a pipe, interprets it to set the outcome_
// member, and closes read_fd_. Outputs diagnostics and terminates in
// case of unexpected codes.
void
DeathTestImpl
::
ReadAndInterpretStatusByte
()
{
char
flag
;
int
bytes_read
;
// The read() here blocks until data is available (signifying the
// failure of the death test) or until the pipe is closed (signifying
// its success), so it's okay to call this in the parent before
// the child process has exited.
do
{
bytes_read
=
posix
::
Read
(
read_fd
(),
&
flag
,
1
);
}
while
(
bytes_read
==
-
1
&&
errno
==
EINTR
);
if
(
bytes_read
==
0
)
{
set_outcome
(
DIED
);
}
else
if
(
bytes_read
==
1
)
{
switch
(
flag
)
{
case
kDeathTestReturned
:
set_outcome
(
RETURNED
);
break
;
case
kDeathTestThrew
:
set_outcome
(
THREW
);
break
;
case
kDeathTestLived
:
set_outcome
(
LIVED
);
break
;
case
kDeathTestInternalError
:
FailFromInternalError
(
read_fd
());
// Does not return.
break
;
default:
GTEST_LOG_
(
FATAL
)
<<
"Death test child process reported "
<<
"unexpected status byte ("
<<
static_cast
<
unsigned
int
>
(
flag
)
<<
")"
;
}
}
else
{
GTEST_LOG_
(
FATAL
)
<<
"Read from death test child process failed: "
<<
GetLastErrnoDescription
();
}
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
posix
::
Close
(
read_fd
()));
set_read_fd
(
-
1
);
}
// Signals that the death test code which should have exited, didn't.
// Should be called only in a death test child process.
// Writes a status byte to the child's status file descriptor, then
// calls _exit(1).
void
DeathTestImpl
::
Abort
(
AbortReason
reason
)
{
// The parent process considers the death test to be a failure if
// it finds any data in our pipe. So, here we write a single flag byte
// to the pipe, then exit.
const
char
status_ch
=
reason
==
TEST_DID_NOT_DIE
?
kDeathTestLived
:
reason
==
TEST_THREW_EXCEPTION
?
kDeathTestThrew
:
kDeathTestReturned
;
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
posix
::
Write
(
write_fd
(),
&
status_ch
,
1
));
// We are leaking the descriptor here because on some platforms (i.e.,
// when built as Windows DLL), destructors of global objects will still
// run after calling _exit(). On such systems, write_fd_ will be
// indirectly closed from the destructor of UnitTestImpl, causing double
// close if it is also closed here. On debug configurations, double close
// may assert. As there are no in-process buffers to flush here, we are
// relying on the OS to close the descriptor after the process terminates
// when the destructors are not run.
_exit
(
1
);
// Exits w/o any normal exit hooks (we were supposed to crash)
}
// Returns an indented copy of stderr output for a death test.
// This makes distinguishing death test output lines from regular log lines
// much easier.
static
::
std
::
string
FormatDeathTestOutput
(
const
::
std
::
string
&
output
)
{
::
std
::
string
ret
;
for
(
size_t
at
=
0
;
;
)
{
const
size_t
line_end
=
output
.
find
(
'\n'
,
at
);
ret
+=
"[ DEATH ] "
;
if
(
line_end
==
::
std
::
string
::
npos
)
{
ret
+=
output
.
substr
(
at
);
break
;
}
ret
+=
output
.
substr
(
at
,
line_end
+
1
-
at
);
at
=
line_end
+
1
;
}
return
ret
;
}
// Assesses the success or failure of a death test, using both private
// members which have previously been set, and one argument:
//
// Private data members:
// outcome: An enumeration describing how the death test
// concluded: DIED, LIVED, THREW, or RETURNED. The death test
// fails in the latter three cases.
// status: The exit status of the child process. On *nix, it is in the
// in the format specified by wait(2). On Windows, this is the
// value supplied to the ExitProcess() API or a numeric code
// of the exception that terminated the program.
// regex: A regular expression object to be applied to
// the test's captured standard error output; the death test
// fails if it does not match.
//
// Argument:
// status_ok: true if exit_status is acceptable in the context of
// this particular death test, which fails if it is false
//
// Returns true iff all of the above conditions are met. Otherwise, the
// first failing condition, in the order given above, is the one that is
// reported. Also sets the last death test message string.
bool
DeathTestImpl
::
Passed
(
bool
status_ok
)
{
if
(
!
spawned
())
return
false
;
const
std
::
string
error_message
=
GetCapturedStderr
();
bool
success
=
false
;
Message
buffer
;
buffer
<<
"Death test: "
<<
statement
()
<<
"
\n
"
;
switch
(
outcome
())
{
case
LIVED
:
buffer
<<
" Result: failed to die.
\n
"
<<
" Error msg:
\n
"
<<
FormatDeathTestOutput
(
error_message
);
break
;
case
THREW
:
buffer
<<
" Result: threw an exception.
\n
"
<<
" Error msg:
\n
"
<<
FormatDeathTestOutput
(
error_message
);
break
;
case
RETURNED
:
buffer
<<
" Result: illegal return in test statement.
\n
"
<<
" Error msg:
\n
"
<<
FormatDeathTestOutput
(
error_message
);
break
;
case
DIED
:
if
(
status_ok
)
{
const
bool
matched
=
RE
::
PartialMatch
(
error_message
.
c_str
(),
*
regex
());
if
(
matched
)
{
success
=
true
;
}
else
{
buffer
<<
" Result: died but not with expected error.
\n
"
<<
" Expected: "
<<
regex
()
->
pattern
()
<<
"
\n
"
<<
"Actual msg:
\n
"
<<
FormatDeathTestOutput
(
error_message
);
}
}
else
{
buffer
<<
" Result: died but not with expected exit code:
\n
"
<<
" "
<<
ExitSummary
(
status
())
<<
"
\n
"
<<
"Actual msg:
\n
"
<<
FormatDeathTestOutput
(
error_message
);
}
break
;
case
IN_PROGRESS
:
default:
GTEST_LOG_
(
FATAL
)
<<
"DeathTest::Passed somehow called before conclusion of test"
;
}
DeathTest
::
set_last_death_test_message
(
buffer
.
GetString
());
return
success
;
}
# if GTEST_OS_WINDOWS
// WindowsDeathTest implements death tests on Windows. Due to the
// specifics of starting new processes on Windows, death tests there are
// always threadsafe, and Google Test considers the
// --gtest_death_test_style=fast setting to be equivalent to
// --gtest_death_test_style=threadsafe there.
//
// A few implementation notes: Like the Linux version, the Windows
// implementation uses pipes for child-to-parent communication. But due to
// the specifics of pipes on Windows, some extra steps are required:
//
// 1. The parent creates a communication pipe and stores handles to both
// ends of it.
// 2. The parent starts the child and provides it with the information
// necessary to acquire the handle to the write end of the pipe.
// 3. The child acquires the write end of the pipe and signals the parent
// using a Windows event.
// 4. Now the parent can release the write end of the pipe on its side. If
// this is done before step 3, the object's reference count goes down to
// 0 and it is destroyed, preventing the child from acquiring it. The
// parent now has to release it, or read operations on the read end of
// the pipe will not return when the child terminates.
// 5. The parent reads child's output through the pipe (outcome code and
// any possible error messages) from the pipe, and its stderr and then
// determines whether to fail the test.
//
// Note: to distinguish Win32 API calls from the local method and function
// calls, the former are explicitly resolved in the global namespace.
//
class
WindowsDeathTest
:
public
DeathTestImpl
{
public:
WindowsDeathTest
(
const
char
*
a_statement
,
const
RE
*
a_regex
,
const
char
*
file
,
int
line
)
:
DeathTestImpl
(
a_statement
,
a_regex
),
file_
(
file
),
line_
(
line
)
{}
// All of these virtual functions are inherited from DeathTest.
virtual
int
Wait
();
virtual
TestRole
AssumeRole
();
private:
// The name of the file in which the death test is located.
const
char
*
const
file_
;
// The line number on which the death test is located.
const
int
line_
;
// Handle to the write end of the pipe to the child process.
AutoHandle
write_handle_
;
// Child process handle.
AutoHandle
child_handle_
;
// Event the child process uses to signal the parent that it has
// acquired the handle to the write end of the pipe. After seeing this
// event the parent can release its own handles to make sure its
// ReadFile() calls return when the child terminates.
AutoHandle
event_handle_
;
};
// Waits for the child in a death test to exit, returning its exit
// status, or 0 if no child process exists. As a side effect, sets the
// outcome data member.
int
WindowsDeathTest
::
Wait
()
{
if
(
!
spawned
())
return
0
;
// Wait until the child either signals that it has acquired the write end
// of the pipe or it dies.
const
HANDLE
wait_handles
[
2
]
=
{
child_handle_
.
Get
(),
event_handle_
.
Get
()
};
switch
(
::
WaitForMultipleObjects
(
2
,
wait_handles
,
FALSE
,
// Waits for any of the handles.
INFINITE
))
{
case
WAIT_OBJECT_0
:
case
WAIT_OBJECT_0
+
1
:
break
;
default:
GTEST_DEATH_TEST_CHECK_
(
false
);
// Should not get here.
}
// The child has acquired the write end of the pipe or exited.
// We release the handle on our side and continue.
write_handle_
.
Reset
();
event_handle_
.
Reset
();
ReadAndInterpretStatusByte
();
// Waits for the child process to exit if it haven't already. This
// returns immediately if the child has already exited, regardless of
// whether previous calls to WaitForMultipleObjects synchronized on this
// handle or not.
GTEST_DEATH_TEST_CHECK_
(
WAIT_OBJECT_0
==
::
WaitForSingleObject
(
child_handle_
.
Get
(),
INFINITE
));
DWORD
status_code
;
GTEST_DEATH_TEST_CHECK_
(
::
GetExitCodeProcess
(
child_handle_
.
Get
(),
&
status_code
)
!=
FALSE
);
child_handle_
.
Reset
();
set_status
(
static_cast
<
int
>
(
status_code
));
return
status
();
}
// The AssumeRole process for a Windows death test. It creates a child
// process with the same executable as the current process to run the
// death test. The child process is given the --gtest_filter and
// --gtest_internal_run_death_test flags such that it knows to run the
// current death test only.
DeathTest
::
TestRole
WindowsDeathTest
::
AssumeRole
()
{
const
UnitTestImpl
*
const
impl
=
GetUnitTestImpl
();
const
InternalRunDeathTestFlag
*
const
flag
=
impl
->
internal_run_death_test_flag
();
const
TestInfo
*
const
info
=
impl
->
current_test_info
();
const
int
death_test_index
=
info
->
result
()
->
death_test_count
();
if
(
flag
!=
NULL
)
{
// ParseInternalRunDeathTestFlag() has performed all the necessary
// processing.
set_write_fd
(
flag
->
write_fd
());
return
EXECUTE_TEST
;
}
// WindowsDeathTest uses an anonymous pipe to communicate results of
// a death test.
SECURITY_ATTRIBUTES
handles_are_inheritable
=
{
sizeof
(
SECURITY_ATTRIBUTES
),
NULL
,
TRUE
};
HANDLE
read_handle
,
write_handle
;
GTEST_DEATH_TEST_CHECK_
(
::
CreatePipe
(
&
read_handle
,
&
write_handle
,
&
handles_are_inheritable
,
0
)
// Default buffer size.
!=
FALSE
);
set_read_fd
(
::
_open_osfhandle
(
reinterpret_cast
<
intptr_t
>
(
read_handle
),
O_RDONLY
));
write_handle_
.
Reset
(
write_handle
);
event_handle_
.
Reset
(
::
CreateEvent
(
&
handles_are_inheritable
,
TRUE
,
// The event will automatically reset to non-signaled state.
FALSE
,
// The initial state is non-signalled.
NULL
));
// The even is unnamed.
GTEST_DEATH_TEST_CHECK_
(
event_handle_
.
Get
()
!=
NULL
);
const
std
::
string
filter_flag
=
std
::
string
(
"--"
)
+
GTEST_FLAG_PREFIX_
+
kFilterFlag
+
"="
+
info
->
test_case_name
()
+
"."
+
info
->
name
();
const
std
::
string
internal_flag
=
std
::
string
(
"--"
)
+
GTEST_FLAG_PREFIX_
+
kInternalRunDeathTestFlag
+
"="
+
file_
+
"|"
+
StreamableToString
(
line_
)
+
"|"
+
StreamableToString
(
death_test_index
)
+
"|"
+
StreamableToString
(
static_cast
<
unsigned
int
>
(
::
GetCurrentProcessId
()))
+
// size_t has the same width as pointers on both 32-bit and 64-bit
// Windows platforms.
// See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
"|"
+
StreamableToString
(
reinterpret_cast
<
size_t
>
(
write_handle
))
+
"|"
+
StreamableToString
(
reinterpret_cast
<
size_t
>
(
event_handle_
.
Get
()));
char
executable_path
[
_MAX_PATH
+
1
];
// NOLINT
GTEST_DEATH_TEST_CHECK_
(
_MAX_PATH
+
1
!=
::
GetModuleFileNameA
(
NULL
,
executable_path
,
_MAX_PATH
));
std
::
string
command_line
=
std
::
string
(
::
GetCommandLineA
())
+
" "
+
filter_flag
+
"
\"
"
+
internal_flag
+
"
\"
"
;
DeathTest
::
set_last_death_test_message
(
""
);
CaptureStderr
();
// Flush the log buffers since the log streams are shared with the child.
FlushInfoLog
();
// The child process will share the standard handles with the parent.
STARTUPINFOA
startup_info
;
memset
(
&
startup_info
,
0
,
sizeof
(
STARTUPINFO
));
startup_info
.
dwFlags
=
STARTF_USESTDHANDLES
;
startup_info
.
hStdInput
=
::
GetStdHandle
(
STD_INPUT_HANDLE
);
startup_info
.
hStdOutput
=
::
GetStdHandle
(
STD_OUTPUT_HANDLE
);
startup_info
.
hStdError
=
::
GetStdHandle
(
STD_ERROR_HANDLE
);
PROCESS_INFORMATION
process_info
;
GTEST_DEATH_TEST_CHECK_
(
::
CreateProcessA
(
executable_path
,
const_cast
<
char
*>
(
command_line
.
c_str
()),
NULL
,
// Retuned process handle is not inheritable.
NULL
,
// Retuned thread handle is not inheritable.
TRUE
,
// Child inherits all inheritable handles (for write_handle_).
0x0
,
// Default creation flags.
NULL
,
// Inherit the parent's environment.
UnitTest
::
GetInstance
()
->
original_working_dir
(),
&
startup_info
,
&
process_info
)
!=
FALSE
);
child_handle_
.
Reset
(
process_info
.
hProcess
);
::
CloseHandle
(
process_info
.
hThread
);
set_spawned
(
true
);
return
OVERSEE_TEST
;
}
# else // We are not on Windows.
// ForkingDeathTest provides implementations for most of the abstract
// methods of the DeathTest interface. Only the AssumeRole method is
// left undefined.
class
ForkingDeathTest
:
public
DeathTestImpl
{
public:
ForkingDeathTest
(
const
char
*
statement
,
const
RE
*
regex
);
// All of these virtual functions are inherited from DeathTest.
virtual
int
Wait
();
protected:
void
set_child_pid
(
pid_t
child_pid
)
{
child_pid_
=
child_pid
;
}
private:
// PID of child process during death test; 0 in the child process itself.
pid_t
child_pid_
;
};
// Constructs a ForkingDeathTest.
ForkingDeathTest
::
ForkingDeathTest
(
const
char
*
a_statement
,
const
RE
*
a_regex
)
:
DeathTestImpl
(
a_statement
,
a_regex
),
child_pid_
(
-
1
)
{}
// Waits for the child in a death test to exit, returning its exit
// status, or 0 if no child process exists. As a side effect, sets the
// outcome data member.
int
ForkingDeathTest
::
Wait
()
{
if
(
!
spawned
())
return
0
;
ReadAndInterpretStatusByte
();
int
status_value
;
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
waitpid
(
child_pid_
,
&
status_value
,
0
));
set_status
(
status_value
);
return
status_value
;
}
// A concrete death test class that forks, then immediately runs the test
// in the child process.
class
NoExecDeathTest
:
public
ForkingDeathTest
{
public:
NoExecDeathTest
(
const
char
*
a_statement
,
const
RE
*
a_regex
)
:
ForkingDeathTest
(
a_statement
,
a_regex
)
{
}
virtual
TestRole
AssumeRole
();
};
// The AssumeRole process for a fork-and-run death test. It implements a
// straightforward fork, with a simple pipe to transmit the status byte.
DeathTest
::
TestRole
NoExecDeathTest
::
AssumeRole
()
{
const
size_t
thread_count
=
GetThreadCount
();
if
(
thread_count
!=
1
)
{
GTEST_LOG_
(
WARNING
)
<<
DeathTestThreadWarning
(
thread_count
);
}
int
pipe_fd
[
2
];
GTEST_DEATH_TEST_CHECK_
(
pipe
(
pipe_fd
)
!=
-
1
);
DeathTest
::
set_last_death_test_message
(
""
);
CaptureStderr
();
// When we fork the process below, the log file buffers are copied, but the
// file descriptors are shared. We flush all log files here so that closing
// the file descriptors in the child process doesn't throw off the
// synchronization between descriptors and buffers in the parent process.
// This is as close to the fork as possible to avoid a race condition in case
// there are multiple threads running before the death test, and another
// thread writes to the log file.
FlushInfoLog
();
const
pid_t
child_pid
=
fork
();
GTEST_DEATH_TEST_CHECK_
(
child_pid
!=
-
1
);
set_child_pid
(
child_pid
);
if
(
child_pid
==
0
)
{
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
close
(
pipe_fd
[
0
]));
set_write_fd
(
pipe_fd
[
1
]);
// Redirects all logging to stderr in the child process to prevent
// concurrent writes to the log files. We capture stderr in the parent
// process and append the child process' output to a log.
LogToStderr
();
// Event forwarding to the listeners of event listener API mush be shut
// down in death test subprocesses.
GetUnitTestImpl
()
->
listeners
()
->
SuppressEventForwarding
();
g_in_fast_death_test_child
=
true
;
return
EXECUTE_TEST
;
}
else
{
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
close
(
pipe_fd
[
1
]));
set_read_fd
(
pipe_fd
[
0
]);
set_spawned
(
true
);
return
OVERSEE_TEST
;
}
}
// A concrete death test class that forks and re-executes the main
// program from the beginning, with command-line flags set that cause
// only this specific death test to be run.
class
ExecDeathTest
:
public
ForkingDeathTest
{
public:
ExecDeathTest
(
const
char
*
a_statement
,
const
RE
*
a_regex
,
const
char
*
file
,
int
line
)
:
ForkingDeathTest
(
a_statement
,
a_regex
),
file_
(
file
),
line_
(
line
)
{
}
virtual
TestRole
AssumeRole
();
private:
static
::
std
::
vector
<
testing
::
internal
::
string
>
GetArgvsForDeathTestChildProcess
()
{
::
std
::
vector
<
testing
::
internal
::
string
>
args
=
GetInjectableArgvs
();
return
args
;
}
// The name of the file in which the death test is located.
const
char
*
const
file_
;
// The line number on which the death test is located.
const
int
line_
;
};
// Utility class for accumulating command-line arguments.
class
Arguments
{
public:
Arguments
()
{
args_
.
push_back
(
NULL
);
}
~
Arguments
()
{
for
(
std
::
vector
<
char
*>::
iterator
i
=
args_
.
begin
();
i
!=
args_
.
end
();
++
i
)
{
free
(
*
i
);
}
}
void
AddArgument
(
const
char
*
argument
)
{
args_
.
insert
(
args_
.
end
()
-
1
,
posix
::
StrDup
(
argument
));
}
template
<
typename
Str
>
void
AddArguments
(
const
::
std
::
vector
<
Str
>&
arguments
)
{
for
(
typename
::
std
::
vector
<
Str
>::
const_iterator
i
=
arguments
.
begin
();
i
!=
arguments
.
end
();
++
i
)
{
args_
.
insert
(
args_
.
end
()
-
1
,
posix
::
StrDup
(
i
->
c_str
()));
}
}
char
*
const
*
Argv
()
{
return
&
args_
[
0
];
}
private:
std
::
vector
<
char
*>
args_
;
};
// A struct that encompasses the arguments to the child process of a
// threadsafe-style death test process.
struct
ExecDeathTestArgs
{
char
*
const
*
argv
;
// Command-line arguments for the child's call to exec
int
close_fd
;
// File descriptor to close; the read end of a pipe
};
# if GTEST_OS_MAC
inline
char
**
GetEnviron
()
{
// When Google Test is built as a framework on MacOS X, the environ variable
// is unavailable. Apple's documentation (man environ) recommends using
// _NSGetEnviron() instead.
return
*
_NSGetEnviron
();
}
# else
// Some POSIX platforms expect you to declare environ. extern "C" makes
// it reside in the global namespace.
extern
"C"
char
**
environ
;
inline
char
**
GetEnviron
()
{
return
environ
;
}
# endif // GTEST_OS_MAC
# if !GTEST_OS_QNX
// The main function for a threadsafe-style death test child process.
// This function is called in a clone()-ed process and thus must avoid
// any potentially unsafe operations like malloc or libc functions.
static
int
ExecDeathTestChildMain
(
void
*
child_arg
)
{
ExecDeathTestArgs
*
const
args
=
static_cast
<
ExecDeathTestArgs
*>
(
child_arg
);
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
close
(
args
->
close_fd
));
// We need to execute the test program in the same environment where
// it was originally invoked. Therefore we change to the original
// working directory first.
const
char
*
const
original_dir
=
UnitTest
::
GetInstance
()
->
original_working_dir
();
// We can safely call chdir() as it's a direct system call.
if
(
chdir
(
original_dir
)
!=
0
)
{
DeathTestAbort
(
std
::
string
(
"chdir(
\"
"
)
+
original_dir
+
"
\"
) failed: "
+
GetLastErrnoDescription
());
return
EXIT_FAILURE
;
}
// We can safely call execve() as it's a direct system call. We
// cannot use execvp() as it's a libc function and thus potentially
// unsafe. Since execve() doesn't search the PATH, the user must
// invoke the test program via a valid path that contains at least
// one path separator.
execve
(
args
->
argv
[
0
],
args
->
argv
,
GetEnviron
());
DeathTestAbort
(
std
::
string
(
"execve("
)
+
args
->
argv
[
0
]
+
", ...) in "
+
original_dir
+
" failed: "
+
GetLastErrnoDescription
());
return
EXIT_FAILURE
;
}
# endif // !GTEST_OS_QNX
// Two utility routines that together determine the direction the stack
// grows.
// This could be accomplished more elegantly by a single recursive
// function, but we want to guard against the unlikely possibility of
// a smart compiler optimizing the recursion away.
//
// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
// StackLowerThanAddress into StackGrowsDown, which then doesn't give
// correct answer.
void
StackLowerThanAddress
(
const
void
*
ptr
,
bool
*
result
)
GTEST_NO_INLINE_
;
void
StackLowerThanAddress
(
const
void
*
ptr
,
bool
*
result
)
{
int
dummy
;
*
result
=
(
&
dummy
<
ptr
);
}
bool
StackGrowsDown
()
{
int
dummy
;
bool
result
;
StackLowerThanAddress
(
&
dummy
,
&
result
);
return
result
;
}
// Spawns a child process with the same executable as the current process in
// a thread-safe manner and instructs it to run the death test. The
// implementation uses fork(2) + exec. On systems where clone(2) is
// available, it is used instead, being slightly more thread-safe. On QNX,
// fork supports only single-threaded environments, so this function uses
// spawn(2) there instead. The function dies with an error message if
// anything goes wrong.
static
pid_t
ExecDeathTestSpawnChild
(
char
*
const
*
argv
,
int
close_fd
)
{
ExecDeathTestArgs
args
=
{
argv
,
close_fd
};
pid_t
child_pid
=
-
1
;
# if GTEST_OS_QNX
// Obtains the current directory and sets it to be closed in the child
// process.
const
int
cwd_fd
=
open
(
"."
,
O_RDONLY
);
GTEST_DEATH_TEST_CHECK_
(
cwd_fd
!=
-
1
);
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
fcntl
(
cwd_fd
,
F_SETFD
,
FD_CLOEXEC
));
// We need to execute the test program in the same environment where
// it was originally invoked. Therefore we change to the original
// working directory first.
const
char
*
const
original_dir
=
UnitTest
::
GetInstance
()
->
original_working_dir
();
// We can safely call chdir() as it's a direct system call.
if
(
chdir
(
original_dir
)
!=
0
)
{
DeathTestAbort
(
std
::
string
(
"chdir(
\"
"
)
+
original_dir
+
"
\"
) failed: "
+
GetLastErrnoDescription
());
return
EXIT_FAILURE
;
}
int
fd_flags
;
// Set close_fd to be closed after spawn.
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
fd_flags
=
fcntl
(
close_fd
,
F_GETFD
));
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
fcntl
(
close_fd
,
F_SETFD
,
fd_flags
|
FD_CLOEXEC
));
struct
inheritance
inherit
=
{
0
};
// spawn is a system call.
child_pid
=
spawn
(
args
.
argv
[
0
],
0
,
NULL
,
&
inherit
,
args
.
argv
,
GetEnviron
());
// Restores the current working directory.
GTEST_DEATH_TEST_CHECK_
(
fchdir
(
cwd_fd
)
!=
-
1
);
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
close
(
cwd_fd
));
# else // GTEST_OS_QNX
# if GTEST_OS_LINUX
// When a SIGPROF signal is received while fork() or clone() are executing,
// the process may hang. To avoid this, we ignore SIGPROF here and re-enable
// it after the call to fork()/clone() is complete.
struct
sigaction
saved_sigprof_action
;
struct
sigaction
ignore_sigprof_action
;
memset
(
&
ignore_sigprof_action
,
0
,
sizeof
(
ignore_sigprof_action
));
sigemptyset
(
&
ignore_sigprof_action
.
sa_mask
);
ignore_sigprof_action
.
sa_handler
=
SIG_IGN
;
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
sigaction
(
SIGPROF
,
&
ignore_sigprof_action
,
&
saved_sigprof_action
));
# endif // GTEST_OS_LINUX
# if GTEST_HAS_CLONE
const
bool
use_fork
=
GTEST_FLAG
(
death_test_use_fork
);
if
(
!
use_fork
)
{
static
const
bool
stack_grows_down
=
StackGrowsDown
();
const
size_t
stack_size
=
getpagesize
();
// MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
void
*
const
stack
=
mmap
(
NULL
,
stack_size
,
PROT_READ
|
PROT_WRITE
,
MAP_ANON
|
MAP_PRIVATE
,
-
1
,
0
);
GTEST_DEATH_TEST_CHECK_
(
stack
!=
MAP_FAILED
);
// Maximum stack alignment in bytes: For a downward-growing stack, this
// amount is subtracted from size of the stack space to get an address
// that is within the stack space and is aligned on all systems we care
// about. As far as I know there is no ABI with stack alignment greater
// than 64. We assume stack and stack_size already have alignment of
// kMaxStackAlignment.
const
size_t
kMaxStackAlignment
=
64
;
void
*
const
stack_top
=
static_cast
<
char
*>
(
stack
)
+
(
stack_grows_down
?
stack_size
-
kMaxStackAlignment
:
0
);
GTEST_DEATH_TEST_CHECK_
(
stack_size
>
kMaxStackAlignment
&&
reinterpret_cast
<
intptr_t
>
(
stack_top
)
%
kMaxStackAlignment
==
0
);
child_pid
=
clone
(
&
ExecDeathTestChildMain
,
stack_top
,
SIGCHLD
,
&
args
);
GTEST_DEATH_TEST_CHECK_
(
munmap
(
stack
,
stack_size
)
!=
-
1
);
}
# else
const
bool
use_fork
=
true
;
# endif // GTEST_HAS_CLONE
if
(
use_fork
&&
(
child_pid
=
fork
())
==
0
)
{
ExecDeathTestChildMain
(
&
args
);
_exit
(
0
);
}
# endif // GTEST_OS_QNX
# if GTEST_OS_LINUX
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
sigaction
(
SIGPROF
,
&
saved_sigprof_action
,
NULL
));
# endif // GTEST_OS_LINUX
GTEST_DEATH_TEST_CHECK_
(
child_pid
!=
-
1
);
return
child_pid
;
}
// The AssumeRole process for a fork-and-exec death test. It re-executes the
// main program from the beginning, setting the --gtest_filter
// and --gtest_internal_run_death_test flags to cause only the current
// death test to be re-run.
DeathTest
::
TestRole
ExecDeathTest
::
AssumeRole
()
{
const
UnitTestImpl
*
const
impl
=
GetUnitTestImpl
();
const
InternalRunDeathTestFlag
*
const
flag
=
impl
->
internal_run_death_test_flag
();
const
TestInfo
*
const
info
=
impl
->
current_test_info
();
const
int
death_test_index
=
info
->
result
()
->
death_test_count
();
if
(
flag
!=
NULL
)
{
set_write_fd
(
flag
->
write_fd
());
return
EXECUTE_TEST
;
}
int
pipe_fd
[
2
];
GTEST_DEATH_TEST_CHECK_
(
pipe
(
pipe_fd
)
!=
-
1
);
// Clear the close-on-exec flag on the write end of the pipe, lest
// it be closed when the child process does an exec:
GTEST_DEATH_TEST_CHECK_
(
fcntl
(
pipe_fd
[
1
],
F_SETFD
,
0
)
!=
-
1
);
const
std
::
string
filter_flag
=
std
::
string
(
"--"
)
+
GTEST_FLAG_PREFIX_
+
kFilterFlag
+
"="
+
info
->
test_case_name
()
+
"."
+
info
->
name
();
const
std
::
string
internal_flag
=
std
::
string
(
"--"
)
+
GTEST_FLAG_PREFIX_
+
kInternalRunDeathTestFlag
+
"="
+
file_
+
"|"
+
StreamableToString
(
line_
)
+
"|"
+
StreamableToString
(
death_test_index
)
+
"|"
+
StreamableToString
(
pipe_fd
[
1
]);
Arguments
args
;
args
.
AddArguments
(
GetArgvsForDeathTestChildProcess
());
args
.
AddArgument
(
filter_flag
.
c_str
());
args
.
AddArgument
(
internal_flag
.
c_str
());
DeathTest
::
set_last_death_test_message
(
""
);
CaptureStderr
();
// See the comment in NoExecDeathTest::AssumeRole for why the next line
// is necessary.
FlushInfoLog
();
const
pid_t
child_pid
=
ExecDeathTestSpawnChild
(
args
.
Argv
(),
pipe_fd
[
0
]);
GTEST_DEATH_TEST_CHECK_SYSCALL_
(
close
(
pipe_fd
[
1
]));
set_child_pid
(
child_pid
);
set_read_fd
(
pipe_fd
[
0
]);
set_spawned
(
true
);
return
OVERSEE_TEST
;
}
# endif // !GTEST_OS_WINDOWS
// Creates a concrete DeathTest-derived class that depends on the
// --gtest_death_test_style flag, and sets the pointer pointed to
// by the "test" argument to its address. If the test should be
// skipped, sets that pointer to NULL. Returns true, unless the
// flag is set to an invalid value.
bool
DefaultDeathTestFactory
::
Create
(
const
char
*
statement
,
const
RE
*
regex
,
const
char
*
file
,
int
line
,
DeathTest
**
test
)
{
UnitTestImpl
*
const
impl
=
GetUnitTestImpl
();
const
InternalRunDeathTestFlag
*
const
flag
=
impl
->
internal_run_death_test_flag
();
const
int
death_test_index
=
impl
->
current_test_info
()
->
increment_death_test_count
();
if
(
flag
!=
NULL
)
{
if
(
death_test_index
>
flag
->
index
())
{
DeathTest
::
set_last_death_test_message
(
"Death test count ("
+
StreamableToString
(
death_test_index
)
+
") somehow exceeded expected maximum ("
+
StreamableToString
(
flag
->
index
())
+
")"
);
return
false
;
}
if
(
!
(
flag
->
file
()
==
file
&&
flag
->
line
()
==
line
&&
flag
->
index
()
==
death_test_index
))
{
*
test
=
NULL
;
return
true
;
}
}
# if GTEST_OS_WINDOWS
if
(
GTEST_FLAG
(
death_test_style
)
==
"threadsafe"
||
GTEST_FLAG
(
death_test_style
)
==
"fast"
)
{
*
test
=
new
WindowsDeathTest
(
statement
,
regex
,
file
,
line
);
}
# else
if
(
GTEST_FLAG
(
death_test_style
)
==
"threadsafe"
)
{
*
test
=
new
ExecDeathTest
(
statement
,
regex
,
file
,
line
);
}
else
if
(
GTEST_FLAG
(
death_test_style
)
==
"fast"
)
{
*
test
=
new
NoExecDeathTest
(
statement
,
regex
);
}
# endif // GTEST_OS_WINDOWS
else
{
// NOLINT - this is more readable than unbalanced brackets inside #if.
DeathTest
::
set_last_death_test_message
(
"Unknown death test style
\"
"
+
GTEST_FLAG
(
death_test_style
)
+
"
\"
encountered"
);
return
false
;
}
return
true
;
}
// Splits a given string on a given delimiter, populating a given
// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have
// ::std::string, so we can use it here.
static
void
SplitString
(
const
::
std
::
string
&
str
,
char
delimiter
,
::
std
::
vector
<
::
std
::
string
>*
dest
)
{
::
std
::
vector
<
::
std
::
string
>
parsed
;
::
std
::
string
::
size_type
pos
=
0
;
while
(
::
testing
::
internal
::
AlwaysTrue
())
{
const
::
std
::
string
::
size_type
colon
=
str
.
find
(
delimiter
,
pos
);
if
(
colon
==
::
std
::
string
::
npos
)
{
parsed
.
push_back
(
str
.
substr
(
pos
));
break
;
}
else
{
parsed
.
push_back
(
str
.
substr
(
pos
,
colon
-
pos
));
pos
=
colon
+
1
;
}
}
dest
->
swap
(
parsed
);
}
# if GTEST_OS_WINDOWS
// Recreates the pipe and event handles from the provided parameters,
// signals the event, and returns a file descriptor wrapped around the pipe
// handle. This function is called in the child process only.
int
GetStatusFileDescriptor
(
unsigned
int
parent_process_id
,
size_t
write_handle_as_size_t
,
size_t
event_handle_as_size_t
)
{
AutoHandle
parent_process_handle
(
::
OpenProcess
(
PROCESS_DUP_HANDLE
,
FALSE
,
// Non-inheritable.
parent_process_id
));
if
(
parent_process_handle
.
Get
()
==
INVALID_HANDLE_VALUE
)
{
DeathTestAbort
(
"Unable to open parent process "
+
StreamableToString
(
parent_process_id
));
}
// TODO(vladl@google.com): Replace the following check with a
// compile-time assertion when available.
GTEST_CHECK_
(
sizeof
(
HANDLE
)
<=
sizeof
(
size_t
));
const
HANDLE
write_handle
=
reinterpret_cast
<
HANDLE
>
(
write_handle_as_size_t
);
HANDLE
dup_write_handle
;
// The newly initialized handle is accessible only in in the parent
// process. To obtain one accessible within the child, we need to use
// DuplicateHandle.
if
(
!::
DuplicateHandle
(
parent_process_handle
.
Get
(),
write_handle
,
::
GetCurrentProcess
(),
&
dup_write_handle
,
0x0
,
// Requested privileges ignored since
// DUPLICATE_SAME_ACCESS is used.
FALSE
,
// Request non-inheritable handler.
DUPLICATE_SAME_ACCESS
))
{
DeathTestAbort
(
"Unable to duplicate the pipe handle "
+
StreamableToString
(
write_handle_as_size_t
)
+
" from the parent process "
+
StreamableToString
(
parent_process_id
));
}
const
HANDLE
event_handle
=
reinterpret_cast
<
HANDLE
>
(
event_handle_as_size_t
);
HANDLE
dup_event_handle
;
if
(
!::
DuplicateHandle
(
parent_process_handle
.
Get
(),
event_handle
,
::
GetCurrentProcess
(),
&
dup_event_handle
,
0x0
,
FALSE
,
DUPLICATE_SAME_ACCESS
))
{
DeathTestAbort
(
"Unable to duplicate the event handle "
+
StreamableToString
(
event_handle_as_size_t
)
+
" from the parent process "
+
StreamableToString
(
parent_process_id
));
}
const
int
write_fd
=
::
_open_osfhandle
(
reinterpret_cast
<
intptr_t
>
(
dup_write_handle
),
O_APPEND
);
if
(
write_fd
==
-
1
)
{
DeathTestAbort
(
"Unable to convert pipe handle "
+
StreamableToString
(
write_handle_as_size_t
)
+
" to a file descriptor"
);
}
// Signals the parent that the write end of the pipe has been acquired
// so the parent can release its own write end.
::
SetEvent
(
dup_event_handle
);
return
write_fd
;
}
# endif // GTEST_OS_WINDOWS
// Returns a newly created InternalRunDeathTestFlag object with fields
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
// the flag is specified; otherwise returns NULL.
InternalRunDeathTestFlag
*
ParseInternalRunDeathTestFlag
()
{
if
(
GTEST_FLAG
(
internal_run_death_test
)
==
""
)
return
NULL
;
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
// can use it here.
int
line
=
-
1
;
int
index
=
-
1
;
::
std
::
vector
<
::
std
::
string
>
fields
;
SplitString
(
GTEST_FLAG
(
internal_run_death_test
).
c_str
(),
'|'
,
&
fields
);
int
write_fd
=
-
1
;
# if GTEST_OS_WINDOWS
unsigned
int
parent_process_id
=
0
;
size_t
write_handle_as_size_t
=
0
;
size_t
event_handle_as_size_t
=
0
;
if
(
fields
.
size
()
!=
6
||
!
ParseNaturalNumber
(
fields
[
1
],
&
line
)
||
!
ParseNaturalNumber
(
fields
[
2
],
&
index
)
||
!
ParseNaturalNumber
(
fields
[
3
],
&
parent_process_id
)
||
!
ParseNaturalNumber
(
fields
[
4
],
&
write_handle_as_size_t
)
||
!
ParseNaturalNumber
(
fields
[
5
],
&
event_handle_as_size_t
))
{
DeathTestAbort
(
"Bad --gtest_internal_run_death_test flag: "
+
GTEST_FLAG
(
internal_run_death_test
));
}
write_fd
=
GetStatusFileDescriptor
(
parent_process_id
,
write_handle_as_size_t
,
event_handle_as_size_t
);
# else
if
(
fields
.
size
()
!=
4
||
!
ParseNaturalNumber
(
fields
[
1
],
&
line
)
||
!
ParseNaturalNumber
(
fields
[
2
],
&
index
)
||
!
ParseNaturalNumber
(
fields
[
3
],
&
write_fd
))
{
DeathTestAbort
(
"Bad --gtest_internal_run_death_test flag: "
+
GTEST_FLAG
(
internal_run_death_test
));
}
# endif // GTEST_OS_WINDOWS
return
new
InternalRunDeathTestFlag
(
fields
[
0
],
line
,
index
,
write_fd
);
}
}
// namespace internal
#endif // GTEST_HAS_DEATH_TEST
}
// namespace testing
Prev
1
2
3
4
5
6
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment