Googletest export
Add a matcher `testing::ReturnRoundRobin` which, on each call, returns the next element in the sequence, restarting at the beginning once it has reached the end. PiperOrigin-RevId: 276312136
This commit is contained in:
parent
1110c471ca
commit
37f3227831
@ -503,16 +503,17 @@ which must be a permanent callback.
|
||||
#### Returning a Value
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| | |
|
||||
| :-------------------------- | :-------------------------------------------- |
|
||||
| `Return()` | Return from a `void` mock function. |
|
||||
| `Return(value)` | Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed. |
|
||||
| `ReturnArg<N>()` | Return the `N`-th (0-based) argument. |
|
||||
| `ReturnNew<T>(a1, ..., ak)` | Return `new T(a1, ..., ak)`; a different object is created each time. |
|
||||
| `ReturnNull()` | Return a null pointer. |
|
||||
| `ReturnPointee(ptr)` | Return the value pointed to by `ptr`. |
|
||||
| `ReturnRef(variable)` | Return a reference to `variable`. |
|
||||
| `ReturnRefOfCopy(value)` | Return a reference to a copy of `value`; the copy lives as long as the action. |
|
||||
| | |
|
||||
| :-------------------------------- | :-------------------------------------------- |
|
||||
| `Return()` | Return from a `void` mock function. |
|
||||
| `Return(value)` | Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed. |
|
||||
| `ReturnArg<N>()` | Return the `N`-th (0-based) argument. |
|
||||
| `ReturnNew<T>(a1, ..., ak)` | Return `new T(a1, ..., ak)`; a different object is created each time. |
|
||||
| `ReturnNull()` | Return a null pointer. |
|
||||
| `ReturnPointee(ptr)` | Return the value pointed to by `ptr`. |
|
||||
| `ReturnRef(variable)` | Return a reference to `variable`. |
|
||||
| `ReturnRefOfCopy(value)` | Return a reference to a copy of `value`; the copy lives as long as the action. |
|
||||
| `ReturnRoundRobin({a1, ..., ak})` | Each call will return the next `ai` in the list, starting at the beginning when the end of the list is reached. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
#### Side Effects
|
||||
|
@ -716,6 +716,36 @@ class ReturnRefOfCopyAction {
|
||||
GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction);
|
||||
};
|
||||
|
||||
// Implements the polymorphic ReturnRoundRobin(v) action, which can be
|
||||
// used in any function that returns the element_type of v.
|
||||
template <typename T>
|
||||
class ReturnRoundRobinAction {
|
||||
public:
|
||||
explicit ReturnRoundRobinAction(std::vector<T> values) {
|
||||
GTEST_CHECK_(!values.empty())
|
||||
<< "ReturnRoundRobin requires at least one element.";
|
||||
state_->values = std::move(values);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
T operator()(Args&&...) const {
|
||||
return state_->Next();
|
||||
}
|
||||
|
||||
private:
|
||||
struct State {
|
||||
T Next() {
|
||||
T ret_val = values[i++];
|
||||
if (i == values.size()) i = 0;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
std::vector<T> values;
|
||||
size_t i = 0;
|
||||
};
|
||||
std::shared_ptr<State> state_ = std::make_shared<State>();
|
||||
};
|
||||
|
||||
// Implements the polymorphic DoDefault() action.
|
||||
class DoDefaultAction {
|
||||
public:
|
||||
@ -1039,6 +1069,23 @@ internal::ByMoveWrapper<R> ByMove(R x) {
|
||||
return internal::ByMoveWrapper<R>(std::move(x));
|
||||
}
|
||||
|
||||
// Creates an action that returns an element of `vals`. Calling this action will
|
||||
// repeatedly return the next value from `vals` until it reaches the end and
|
||||
// will restart from the beginning.
|
||||
template <typename T>
|
||||
internal::ReturnRoundRobinAction<T> ReturnRoundRobin(std::vector<T> vals) {
|
||||
return internal::ReturnRoundRobinAction<T>(std::move(vals));
|
||||
}
|
||||
|
||||
// Creates an action that returns an element of `vals`. Calling this action will
|
||||
// repeatedly return the next value from `vals` until it reaches the end and
|
||||
// will restart from the beginning.
|
||||
template <typename T>
|
||||
internal::ReturnRoundRobinAction<T> ReturnRoundRobin(
|
||||
std::initializer_list<T> vals) {
|
||||
return internal::ReturnRoundRobinAction<T>(std::vector<T>(vals));
|
||||
}
|
||||
|
||||
// Creates an action that does the default action for the give mock function.
|
||||
inline internal::DoDefaultAction DoDefault() {
|
||||
return internal::DoDefaultAction();
|
||||
|
5
googlemock/scripts/README.md
Normal file
5
googlemock/scripts/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Please Note:
|
||||
|
||||
Files in this directory are no longer supported by the maintainers. They
|
||||
represent mosty historical artifacts and supported by the community only. There
|
||||
is no guarantee whatsoever that these scripts still work.
|
@ -17,10 +17,7 @@
|
||||
|
||||
"""Generate an Abstract Syntax Tree (AST) for C++."""
|
||||
|
||||
__author__ = 'nnorwitz@google.com (Neal Norwitz)'
|
||||
|
||||
|
||||
# TODO:
|
||||
# FIXME:
|
||||
# * Tokens should never be exported, need to convert to Nodes
|
||||
# (return types, parameters, etc.)
|
||||
# * Handle static class data for templatized classes
|
||||
@ -338,7 +335,7 @@ class Class(_GenericDeclaration):
|
||||
# TODO(nnorwitz): handle namespaces, etc.
|
||||
if self.bases:
|
||||
for token_list in self.bases:
|
||||
# TODO(nnorwitz): bases are tokens, do name comparison.
|
||||
# TODO(nnorwitz): bases are tokens, do name comparision.
|
||||
for token in token_list:
|
||||
if token.name == node.name:
|
||||
return True
|
||||
@ -381,7 +378,7 @@ class Function(_GenericDeclaration):
|
||||
|
||||
def Requires(self, node):
|
||||
if self.parameters:
|
||||
# TODO(nnorwitz): parameters are tokens, do name comparison.
|
||||
# TODO(nnorwitz): parameters are tokens, do name comparision.
|
||||
for p in self.parameters:
|
||||
if p.name == node.name:
|
||||
return True
|
||||
@ -739,6 +736,14 @@ class AstBuilder(object):
|
||||
if token.token_type == tokenize.NAME:
|
||||
if (keywords.IsKeyword(token.name) and
|
||||
not keywords.IsBuiltinType(token.name)):
|
||||
if token.name == 'enum':
|
||||
# Pop the next token and only put it back if it's not
|
||||
# 'class'. This allows us to support the two-token
|
||||
# 'enum class' keyword as if it were simply 'enum'.
|
||||
next = self._GetNextToken()
|
||||
if next.name != 'class':
|
||||
self._AddBackToken(next)
|
||||
|
||||
method = getattr(self, 'handle_' + token.name)
|
||||
return method()
|
||||
elif token.name == self.in_class_name_only:
|
||||
@ -754,7 +759,8 @@ class AstBuilder(object):
|
||||
# Handle data or function declaration/definition.
|
||||
syntax = tokenize.SYNTAX
|
||||
temp_tokens, last_token = \
|
||||
self._GetVarTokensUpTo(syntax, '(', ';', '{', '[')
|
||||
self._GetVarTokensUpToIgnoringTemplates(syntax,
|
||||
'(', ';', '{', '[')
|
||||
temp_tokens.insert(0, token)
|
||||
if last_token.name == '(':
|
||||
# If there is an assignment before the paren,
|
||||
@ -858,7 +864,25 @@ class AstBuilder(object):
|
||||
last_token = self._GetNextToken()
|
||||
return tokens, last_token
|
||||
|
||||
# TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necessary.
|
||||
# Same as _GetVarTokensUpTo, but skips over '<...>' which could contain an
|
||||
# expected token.
|
||||
def _GetVarTokensUpToIgnoringTemplates(self, expected_token_type,
|
||||
*expected_tokens):
|
||||
last_token = self._GetNextToken()
|
||||
tokens = []
|
||||
nesting = 0
|
||||
while (nesting > 0 or
|
||||
last_token.token_type != expected_token_type or
|
||||
last_token.name not in expected_tokens):
|
||||
tokens.append(last_token)
|
||||
last_token = self._GetNextToken()
|
||||
if last_token.name == '<':
|
||||
nesting += 1
|
||||
elif last_token.name == '>':
|
||||
nesting -= 1
|
||||
return tokens, last_token
|
||||
|
||||
# TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necesary.
|
||||
def _IgnoreUpTo(self, token_type, token):
|
||||
unused_tokens = self._GetTokensUpTo(token_type, token)
|
||||
|
||||
@ -1264,9 +1288,6 @@ class AstBuilder(object):
|
||||
return self._GetNestedType(Union)
|
||||
|
||||
def handle_enum(self):
|
||||
token = self._GetNextToken()
|
||||
if not (token.token_type == tokenize.NAME and token.name == 'class'):
|
||||
self._AddBackToken(token)
|
||||
return self._GetNestedType(Enum)
|
||||
|
||||
def handle_auto(self):
|
||||
@ -1298,7 +1319,8 @@ class AstBuilder(object):
|
||||
if token2.token_type == tokenize.SYNTAX and token2.name == '~':
|
||||
return self.GetMethod(FUNCTION_VIRTUAL + FUNCTION_DTOR, None)
|
||||
assert token.token_type == tokenize.NAME or token.name == '::', token
|
||||
return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(') # )
|
||||
return_type_and_name, _ = self._GetVarTokensUpToIgnoringTemplates(
|
||||
tokenize.SYNTAX, '(') # )
|
||||
return_type_and_name.insert(0, token)
|
||||
if token2 is not token:
|
||||
return_type_and_name.insert(1, token2)
|
||||
|
@ -1,18 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2008 Google Inc. All Rights Reserved.
|
||||
# Copyright 2008, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# * 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.
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# 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.
|
||||
|
||||
"""Generate Google Mock classes from base classes.
|
||||
|
||||
@ -26,9 +41,6 @@ Usage:
|
||||
Output is sent to stdout.
|
||||
"""
|
||||
|
||||
__author__ = 'nnorwitz@google.com (Neal Norwitz)'
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
@ -48,6 +60,50 @@ _VERSION = (1, 0, 1) # The version of this script.
|
||||
_INDENT = 2
|
||||
|
||||
|
||||
def _RenderType(ast_type):
|
||||
"""Renders the potentially recursively templated type into a string.
|
||||
|
||||
Args:
|
||||
ast_type: The AST of the type.
|
||||
|
||||
Returns:
|
||||
Rendered string and a boolean to indicate whether we have multiple args
|
||||
(which is not handled correctly).
|
||||
"""
|
||||
has_multiarg_error = False
|
||||
# Add modifiers like 'const'.
|
||||
modifiers = ''
|
||||
if ast_type.modifiers:
|
||||
modifiers = ' '.join(ast_type.modifiers) + ' '
|
||||
return_type = modifiers + ast_type.name
|
||||
if ast_type.templated_types:
|
||||
# Collect template args.
|
||||
template_args = []
|
||||
for arg in ast_type.templated_types:
|
||||
rendered_arg, e = _RenderType(arg)
|
||||
if e: has_multiarg_error = True
|
||||
template_args.append(rendered_arg)
|
||||
return_type += '<' + ', '.join(template_args) + '>'
|
||||
# We are actually not handling multi-template-args correctly. So mark it.
|
||||
if len(template_args) > 1:
|
||||
has_multiarg_error = True
|
||||
if ast_type.pointer:
|
||||
return_type += '*'
|
||||
if ast_type.reference:
|
||||
return_type += '&'
|
||||
return return_type, has_multiarg_error
|
||||
|
||||
|
||||
def _GetNumParameters(parameters, source):
|
||||
num_parameters = len(parameters)
|
||||
if num_parameters == 1:
|
||||
first_param = parameters[0]
|
||||
if source[first_param.start:first_param.end].strip() == 'void':
|
||||
# We must treat T(void) as a function with no parameters.
|
||||
return 0
|
||||
return num_parameters
|
||||
|
||||
|
||||
def _GenerateMethods(output_lines, source, class_node):
|
||||
function_type = (ast.FUNCTION_VIRTUAL | ast.FUNCTION_PURE_VIRTUAL |
|
||||
ast.FUNCTION_OVERRIDE)
|
||||
@ -63,32 +119,16 @@ def _GenerateMethods(output_lines, source, class_node):
|
||||
const = ''
|
||||
if node.modifiers & ast.FUNCTION_CONST:
|
||||
const = 'CONST_'
|
||||
num_parameters = _GetNumParameters(node.parameters, source)
|
||||
return_type = 'void'
|
||||
if node.return_type:
|
||||
# Add modifiers like 'const'.
|
||||
modifiers = ''
|
||||
if node.return_type.modifiers:
|
||||
modifiers = ' '.join(node.return_type.modifiers) + ' '
|
||||
return_type = modifiers + node.return_type.name
|
||||
template_args = [arg.name for arg in node.return_type.templated_types]
|
||||
if template_args:
|
||||
return_type += '<' + ', '.join(template_args) + '>'
|
||||
if len(template_args) > 1:
|
||||
for line in [
|
||||
'// The following line won\'t really compile, as the return',
|
||||
'// type has multiple template arguments. To fix it, use a',
|
||||
'// typedef for the return type.']:
|
||||
output_lines.append(indent + line)
|
||||
if node.return_type.pointer:
|
||||
return_type += '*'
|
||||
if node.return_type.reference:
|
||||
return_type += '&'
|
||||
num_parameters = len(node.parameters)
|
||||
if len(node.parameters) == 1:
|
||||
first_param = node.parameters[0]
|
||||
if source[first_param.start:first_param.end].strip() == 'void':
|
||||
# We must treat T(void) as a function with no parameters.
|
||||
num_parameters = 0
|
||||
return_type, has_multiarg_error = _RenderType(node.return_type)
|
||||
if has_multiarg_error:
|
||||
for line in [
|
||||
'// The following line won\'t really compile, as the return',
|
||||
'// type has multiple template arguments. To fix it, use a',
|
||||
'// typedef for the return type.']:
|
||||
output_lines.append(indent + line)
|
||||
tmpl = ''
|
||||
if class_node.templated_types:
|
||||
tmpl = '_T'
|
||||
|
@ -1,25 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2009 Neal Norwitz All Rights Reserved.
|
||||
# Portions Copyright 2009 Google Inc. All Rights Reserved.
|
||||
# Copyright 2009, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# * 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.
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# 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.
|
||||
|
||||
"""Tests for gmock.scripts.generator.cpp.gmock_class."""
|
||||
|
||||
__author__ = 'nnorwitz@google.com (Neal Norwitz)'
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
@ -444,19 +455,63 @@ void(const FooType& test_arg));
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
|
||||
def testEnumClass(self):
|
||||
def testEnumType(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
enum class Baz { BAZINGA };
|
||||
virtual void Bar(const FooType& test_arg);
|
||||
enum Bar {
|
||||
BAZ, QUX, QUUX, QUUUX
|
||||
};
|
||||
virtual void Foo();
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD1(Bar,
|
||||
void(const FooType& test_arg));
|
||||
MOCK_METHOD0(Foo,
|
||||
void());
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
|
||||
def testEnumClassType(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
enum class Bar {
|
||||
BAZ, QUX, QUUX, QUUUX
|
||||
};
|
||||
virtual void Foo();
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD0(Foo,
|
||||
void());
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
expected, self.GenerateMocks(source))
|
||||
|
||||
def testStdFunction(self):
|
||||
source = """
|
||||
class Test {
|
||||
public:
|
||||
Test(std::function<int(std::string)> foo) : foo_(foo) {}
|
||||
|
||||
virtual std::function<int(std::string)> foo();
|
||||
|
||||
private:
|
||||
std::function<int(std::string)> foo_;
|
||||
};
|
||||
"""
|
||||
expected = """\
|
||||
class MockTest : public Test {
|
||||
public:
|
||||
MOCK_METHOD0(foo,
|
||||
std::function<int (std::string)>());
|
||||
};
|
||||
"""
|
||||
self.assertEqualIgnoreLeadingWhitespace(
|
||||
|
@ -1,25 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2007 Neal Norwitz
|
||||
# Portions Copyright 2007 Google Inc.
|
||||
# Copyright 2007, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# * 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.
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# 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.
|
||||
|
||||
"""C++ keywords and helper utilities for determining keywords."""
|
||||
|
||||
__author__ = 'nnorwitz@google.com (Neal Norwitz)'
|
||||
|
||||
|
||||
try:
|
||||
# Python 3.x
|
||||
import builtins
|
||||
|
@ -1,25 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2007 Neal Norwitz
|
||||
# Portions Copyright 2007 Google Inc.
|
||||
# Copyright 2007, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# * 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.
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# 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.
|
||||
|
||||
"""Tokenize C++ source code."""
|
||||
|
||||
__author__ = 'nnorwitz@google.com (Neal Norwitz)'
|
||||
|
||||
|
||||
try:
|
||||
# Python 3.x
|
||||
import builtins
|
||||
|
@ -1,28 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2007 Neal Norwitz
|
||||
# Portions Copyright 2007 Google Inc.
|
||||
# Copyright 2007, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# * 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.
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# 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.
|
||||
|
||||
"""Generic utilities for C++ parsing."""
|
||||
|
||||
__author__ = 'nnorwitz@google.com (Neal Norwitz)'
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
# Set to True to see the start/end token indices.
|
||||
DEBUG = True
|
||||
|
||||
|
@ -1,22 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2008 Google Inc. All Rights Reserved.
|
||||
# Copyright 2008, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# * 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.
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# 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.
|
||||
|
||||
"""Driver for starting up Google Mock class generator."""
|
||||
|
||||
__author__ = 'nnorwitz@google.com (Neal Norwitz)'
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -1,303 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# These variables are automatically filled in by the configure script.
|
||||
name="@PACKAGE_TARNAME@"
|
||||
version="@PACKAGE_VERSION@"
|
||||
|
||||
show_usage()
|
||||
{
|
||||
echo "Usage: gmock-config [OPTIONS...]"
|
||||
}
|
||||
|
||||
show_help()
|
||||
{
|
||||
show_usage
|
||||
cat <<\EOF
|
||||
|
||||
The `gmock-config' script provides access to the necessary compile and linking
|
||||
flags to connect with Google C++ Mocking 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 gmock. 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:
|
||||
gmock-config --min-version=1.0 || echo "Insufficient Google Mock version."
|
||||
|
||||
g++ $(gmock-config --cppflags --cxxflags) -o foo.o -c foo.cpp
|
||||
g++ $(gmock-config --ldflags --libs) -o foo foo.o
|
||||
|
||||
# When using a built but not installed Google Mock:
|
||||
g++ $(../../my_gmock_build/scripts/gmock-config ...) ...
|
||||
|
||||
# When using an installed Google Mock, but with installation overrides:
|
||||
export GMOCK_PREFIX="/opt"
|
||||
g++ $(gmock-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 Mock 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=*) GMOCK_PREFIX=${1#--prefix=};;
|
||||
--exec-prefix=*) GMOCK_EXEC_PREFIX=${1#--exec-prefix=};;
|
||||
--libdir=*) GMOCK_LIBDIR=${1#--libdir=};;
|
||||
--includedir=*) GMOCK_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="${GMOCK_PREFIX:-@prefix@}"
|
||||
exec_prefix="${GMOCK_EXEC_PREFIX:-@exec_prefix@}"
|
||||
libdir="${GMOCK_LIBDIR:-@libdir@}"
|
||||
includedir="${GMOCK_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. We also locate Google Test using the configured
|
||||
# gtest-config script rather than searching the PATH and our bindir for one.
|
||||
# This allows building against a just-built gmock rather than an installed
|
||||
# gmock.
|
||||
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}/@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.
|
||||
gmock_libs="${build_dir}/lib/libgmock.la"
|
||||
gmock_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.
|
||||
gmock_cppflags="-I${build_dir}/include -I${src_dir}/include"
|
||||
gmock_cxxflags=""
|
||||
|
||||
# Directly invoke the gtest-config script used during the build process.
|
||||
gtest_config="@GTEST_CONFIG@"
|
||||
else
|
||||
# We're using an installed gmock, 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.
|
||||
gmock_ldflags="-L${libdir}"
|
||||
gmock_libs="-l${name}"
|
||||
gmock_cppflags="-I${includedir}"
|
||||
gmock_cxxflags=""
|
||||
|
||||
# We also prefer any gtest-config script installed in our prefix. Lacking
|
||||
# one, we look in the PATH for one.
|
||||
gtest_config="${bindir}/gtest-config"
|
||||
if test ! -x "${gtest_config}"; then
|
||||
gtest_config=`which gtest-config`
|
||||
fi
|
||||
fi
|
||||
|
||||
# Ensure that we have located a Google Test to link against.
|
||||
if ! test -x "${gtest_config}"; then
|
||||
echo "Unable to locate Google Test, check your Google Mock configuration" \
|
||||
"and installation" >&2
|
||||
exit 1
|
||||
elif ! "${gtest_config}" "--exact-version=@GTEST_VERSION@"; then
|
||||
echo "The Google Test found is not the same version as Google Mock was " \
|
||||
"built against" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add the necessary Google Test bits into the various flag variables
|
||||
gmock_cppflags="${gmock_cppflags} `${gtest_config} --cppflags`"
|
||||
gmock_cxxflags="${gmock_cxxflags} `${gtest_config} --cxxflags`"
|
||||
gmock_ldflags="${gmock_ldflags} `${gtest_config} --ldflags`"
|
||||
gmock_libs="${gmock_libs} `${gtest_config} --libs`"
|
||||
|
||||
# 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 $gmock_cppflags"
|
||||
test "$echo_cxxflags" = "yes" && output="$output $gmock_cxxflags"
|
||||
test "$echo_ldflags" = "yes" && output="$output $gmock_ldflags"
|
||||
test "$echo_libs" = "yes" && output="$output $gmock_libs"
|
||||
echo $output
|
||||
|
||||
exit 0
|
@ -1,640 +0,0 @@
|
||||
#!/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.
|
||||
|
||||
"""Converts compiler's errors in code using Google Mock to plain English."""
|
||||
|
||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
_VERSION = '1.0.3'
|
||||
|
||||
_EMAIL = 'googlemock@googlegroups.com'
|
||||
|
||||
_COMMON_GMOCK_SYMBOLS = [
|
||||
# Matchers
|
||||
'_',
|
||||
'A',
|
||||
'AddressSatisfies',
|
||||
'AllOf',
|
||||
'An',
|
||||
'AnyOf',
|
||||
'ContainerEq',
|
||||
'Contains',
|
||||
'ContainsRegex',
|
||||
'DoubleEq',
|
||||
'ElementsAre',
|
||||
'ElementsAreArray',
|
||||
'EndsWith',
|
||||
'Eq',
|
||||
'Field',
|
||||
'FloatEq',
|
||||
'Ge',
|
||||
'Gt',
|
||||
'HasSubstr',
|
||||
'IsInitializedProto',
|
||||
'Le',
|
||||
'Lt',
|
||||
'MatcherCast',
|
||||
'Matches',
|
||||
'MatchesRegex',
|
||||
'NanSensitiveDoubleEq',
|
||||
'NanSensitiveFloatEq',
|
||||
'Ne',
|
||||
'Not',
|
||||
'NotNull',
|
||||
'Pointee',
|
||||
'Property',
|
||||
'Ref',
|
||||
'ResultOf',
|
||||
'SafeMatcherCast',
|
||||
'StartsWith',
|
||||
'StrCaseEq',
|
||||
'StrCaseNe',
|
||||
'StrEq',
|
||||
'StrNe',
|
||||
'Truly',
|
||||
'TypedEq',
|
||||
'Value',
|
||||
|
||||
# Actions
|
||||
'Assign',
|
||||
'ByRef',
|
||||
'DeleteArg',
|
||||
'DoAll',
|
||||
'DoDefault',
|
||||
'IgnoreResult',
|
||||
'Invoke',
|
||||
'InvokeArgument',
|
||||
'InvokeWithoutArgs',
|
||||
'Return',
|
||||
'ReturnNew',
|
||||
'ReturnNull',
|
||||
'ReturnRef',
|
||||
'SaveArg',
|
||||
'SetArgReferee',
|
||||
'SetArgPointee',
|
||||
'SetArgumentPointee',
|
||||
'SetArrayArgument',
|
||||
'SetErrnoAndReturn',
|
||||
'Throw',
|
||||
'WithArg',
|
||||
'WithArgs',
|
||||
'WithoutArgs',
|
||||
|
||||
# Cardinalities
|
||||
'AnyNumber',
|
||||
'AtLeast',
|
||||
'AtMost',
|
||||
'Between',
|
||||
'Exactly',
|
||||
|
||||
# Sequences
|
||||
'InSequence',
|
||||
'Sequence',
|
||||
|
||||
# Misc
|
||||
'DefaultValue',
|
||||
'Mock',
|
||||
]
|
||||
|
||||
# Regex for matching source file path and line number in the compiler's errors.
|
||||
_GCC_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(\d+:)?\s+'
|
||||
_CLANG_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(?P<column>\d+):\s+'
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE = (
|
||||
r'(?P<file>.*[/\\^](?!gmock-)[^/\\]+):(?P<line>\d+):(?P<column>\d+):\s+')
|
||||
|
||||
|
||||
def _FindAllMatches(regex, s):
|
||||
"""Generates all matches of regex in string s."""
|
||||
|
||||
r = re.compile(regex)
|
||||
return r.finditer(s)
|
||||
|
||||
|
||||
def _GenericDiagnoser(short_name, long_name, diagnoses, msg):
|
||||
"""Diagnoses the given disease by pattern matching.
|
||||
|
||||
Can provide different diagnoses for different patterns.
|
||||
|
||||
Args:
|
||||
short_name: Short name of the disease.
|
||||
long_name: Long name of the disease.
|
||||
diagnoses: A list of pairs (regex, pattern for formatting the diagnosis
|
||||
for matching regex).
|
||||
msg: Compiler's error messages.
|
||||
Yields:
|
||||
Tuples of the form
|
||||
(short name of disease, long name of disease, diagnosis).
|
||||
"""
|
||||
for regex, diagnosis in diagnoses:
|
||||
if re.search(regex, msg):
|
||||
diagnosis = '%(file)s:%(line)s:' + diagnosis
|
||||
for m in _FindAllMatches(regex, msg):
|
||||
yield (short_name, long_name, diagnosis % m.groupdict())
|
||||
|
||||
|
||||
def _NeedToReturnReferenceDiagnoser(msg):
|
||||
"""Diagnoses the NRR disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
|
||||
+ _GCC_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gmock-actions\.h.*error: creating array with negative size')
|
||||
clang_regex = (r'error:.*array.*negative.*\r?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'note: in instantiation of function template specialization '
|
||||
r'\'testing::internal::ReturnAction<(?P<type>.*)>'
|
||||
r'::operator Action<.*>\' requested here')
|
||||
clang11_re = (r'use_ReturnRef_instead_of_Return_to_return_a_reference.*'
|
||||
r'(.*\n)*?' + _CLANG_NON_GMOCK_FILE_LINE_RE)
|
||||
|
||||
diagnosis = """
|
||||
You are using a Return() action in a function that returns a reference to
|
||||
%(type)s. Please use ReturnRef() instead."""
|
||||
return _GenericDiagnoser('NRR', 'Need to Return Reference',
|
||||
[(clang_regex, diagnosis),
|
||||
(clang11_re, diagnosis % {'type': 'a type'}),
|
||||
(gcc_regex, diagnosis % {'type': 'a type'})],
|
||||
msg)
|
||||
|
||||
|
||||
def _NeedToReturnSomethingDiagnoser(msg):
|
||||
"""Diagnoses the NRS disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'(instantiated from here\n.'
|
||||
r'*gmock.*actions\.h.*error: void value not ignored)'
|
||||
r'|(error: control reaches end of non-void function)')
|
||||
clang_regex1 = (_CLANG_FILE_LINE_RE +
|
||||
r'error: cannot initialize return object '
|
||||
r'of type \'Result\' \(aka \'(?P<return_type>.*)\'\) '
|
||||
r'with an rvalue of type \'void\'')
|
||||
clang_regex2 = (_CLANG_FILE_LINE_RE +
|
||||
r'error: cannot initialize return object '
|
||||
r'of type \'(?P<return_type>.*)\' '
|
||||
r'with an rvalue of type \'void\'')
|
||||
diagnosis = """
|
||||
You are using an action that returns void, but it needs to return
|
||||
%(return_type)s. Please tell it *what* to return. Perhaps you can use
|
||||
the pattern DoAll(some_action, Return(some_value))?"""
|
||||
return _GenericDiagnoser(
|
||||
'NRS',
|
||||
'Need to Return Something',
|
||||
[(gcc_regex, diagnosis % {'return_type': '*something*'}),
|
||||
(clang_regex1, diagnosis),
|
||||
(clang_regex2, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _NeedToReturnNothingDiagnoser(msg):
|
||||
"""Diagnoses the NRN disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gmock-actions\.h.*error: instantiation of '
|
||||
r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' '
|
||||
r'as type \'void\'')
|
||||
clang_regex1 = (r'error: field has incomplete type '
|
||||
r'\'Result\' \(aka \'void\'\)(\r)?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
|
||||
r'of function template specialization '
|
||||
r'\'testing::internal::ReturnAction<(?P<return_type>.*)>'
|
||||
r'::operator Action<void \(.*\)>\' requested here')
|
||||
clang_regex2 = (r'error: field has incomplete type '
|
||||
r'\'Result\' \(aka \'void\'\)(\r)?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
|
||||
r'of function template specialization '
|
||||
r'\'testing::internal::DoBothAction<.*>'
|
||||
r'::operator Action<(?P<return_type>.*) \(.*\)>\' '
|
||||
r'requested here')
|
||||
diagnosis = """
|
||||
You are using an action that returns %(return_type)s, but it needs to return
|
||||
void. Please use a void-returning action instead.
|
||||
|
||||
All actions but the last in DoAll(...) must return void. Perhaps you need
|
||||
to re-arrange the order of actions in a DoAll(), if you are using one?"""
|
||||
return _GenericDiagnoser(
|
||||
'NRN',
|
||||
'Need to Return Nothing',
|
||||
[(gcc_regex, diagnosis % {'return_type': '*something*'}),
|
||||
(clang_regex1, diagnosis),
|
||||
(clang_regex2, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _IncompleteByReferenceArgumentDiagnoser(msg):
|
||||
"""Diagnoses the IBRA disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gtest-printers\.h.*error: invalid application of '
|
||||
r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
|
||||
|
||||
clang_regex = (r'.*gtest-printers\.h.*error: invalid application of '
|
||||
r'\'sizeof\' to an incomplete type '
|
||||
r'\'(?P<type>.*)( const)?\'\r?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'note: in instantiation of member function '
|
||||
r'\'testing::internal2::TypeWithoutFormatter<.*>::'
|
||||
r'PrintValue\' requested here')
|
||||
diagnosis = """
|
||||
In order to mock this function, Google Mock needs to see the definition
|
||||
of type "%(type)s" - declaration alone is not enough. Either #include
|
||||
the header that defines it, or change the argument to be passed
|
||||
by pointer."""
|
||||
|
||||
return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _OverloadedFunctionMatcherDiagnoser(msg):
|
||||
"""Diagnoses the OFM disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
|
||||
r'call to \'Truly\(<unresolved overloaded function type>\)')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function for '
|
||||
r'call to \'Truly')
|
||||
diagnosis = """
|
||||
The argument you gave to Truly() is an overloaded function. Please tell
|
||||
your compiler which overloaded version you want to use.
|
||||
|
||||
For example, if you want to use the version whose signature is
|
||||
bool Foo(int n);
|
||||
you should write
|
||||
Truly(static_cast<bool (*)(int n)>(Foo))"""
|
||||
return _GenericDiagnoser('OFM', 'Overloaded Function Matcher',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _OverloadedFunctionActionDiagnoser(msg):
|
||||
"""Diagnoses the OFA disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for call to '
|
||||
r'\'Invoke\(<unresolved overloaded function type>')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching '
|
||||
r'function for call to \'Invoke\'\r?\n'
|
||||
r'(.*\n)*?'
|
||||
r'.*\bgmock-generated-actions\.h:\d+:\d+:\s+'
|
||||
r'note: candidate template ignored:\s+'
|
||||
r'couldn\'t infer template argument \'FunctionImpl\'')
|
||||
diagnosis = """
|
||||
Function you are passing to Invoke is overloaded. Please tell your compiler
|
||||
which overloaded version you want to use.
|
||||
|
||||
For example, if you want to use the version whose signature is
|
||||
bool MyFunction(int n, double x);
|
||||
you should write something like
|
||||
Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))"""
|
||||
return _GenericDiagnoser('OFA', 'Overloaded Function Action',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _OverloadedMethodActionDiagnoser(msg):
|
||||
"""Diagnoses the OMA disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
|
||||
r'call to \'Invoke\(.+, <unresolved overloaded function '
|
||||
r'type>\)')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function '
|
||||
r'for call to \'Invoke\'\r?\n'
|
||||
r'(.*\n)*?'
|
||||
r'.*\bgmock-generated-actions\.h:\d+:\d+: '
|
||||
r'note: candidate function template not viable: '
|
||||
r'requires .*, but 2 (arguments )?were provided')
|
||||
diagnosis = """
|
||||
The second argument you gave to Invoke() is an overloaded method. Please
|
||||
tell your compiler which overloaded version you want to use.
|
||||
|
||||
For example, if you want to use the version whose signature is
|
||||
class Foo {
|
||||
...
|
||||
bool Bar(int n, double x);
|
||||
};
|
||||
you should write something like
|
||||
Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
|
||||
return _GenericDiagnoser('OMA', 'Overloaded Method Action',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _MockObjectPointerDiagnoser(msg):
|
||||
"""Diagnoses the MOP disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: request for member '
|
||||
r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
|
||||
r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE + r'error: member reference type '
|
||||
r'\'(?P<class_name>.*?) *\' is a pointer; '
|
||||
r'(did you mean|maybe you meant) to use \'->\'\?')
|
||||
diagnosis = """
|
||||
The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
|
||||
not a *pointer* to it. Please write '*(%(mock_object)s)' instead of
|
||||
'%(mock_object)s' as your first argument.
|
||||
|
||||
For example, given the mock class:
|
||||
|
||||
class %(class_name)s : public ... {
|
||||
...
|
||||
MOCK_METHOD0(%(method)s, ...);
|
||||
};
|
||||
|
||||
and the following mock instance:
|
||||
|
||||
%(class_name)s* mock_ptr = ...
|
||||
|
||||
you should use the EXPECT_CALL like this:
|
||||
|
||||
EXPECT_CALL(*mock_ptr, %(method)s(...));"""
|
||||
|
||||
return _GenericDiagnoser(
|
||||
'MOP',
|
||||
'Mock Object Pointer',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis % {'mock_object': 'mock_object',
|
||||
'method': 'method',
|
||||
'class_name': '%(class_name)s'})],
|
||||
msg)
|
||||
|
||||
|
||||
def _NeedToUseSymbolDiagnoser(msg):
|
||||
"""Diagnoses the NUS disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' '
|
||||
r'(was not declared in this scope|has not been declared)')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE +
|
||||
r'error: (use of undeclared identifier|unknown type name|'
|
||||
r'no template named) \'(?P<symbol>[^\']+)\'')
|
||||
diagnosis = """
|
||||
'%(symbol)s' is defined by Google Mock in the testing namespace.
|
||||
Did you forget to write
|
||||
using testing::%(symbol)s;
|
||||
?"""
|
||||
for m in (list(_FindAllMatches(gcc_regex, msg)) +
|
||||
list(_FindAllMatches(clang_regex, msg))):
|
||||
symbol = m.groupdict()['symbol']
|
||||
if symbol in _COMMON_GMOCK_SYMBOLS:
|
||||
yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict())
|
||||
|
||||
|
||||
def _NeedToUseReturnNullDiagnoser(msg):
|
||||
"""Diagnoses the NRNULL disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = ('instantiated from \'testing::internal::ReturnAction<R>'
|
||||
'::operator testing::Action<Func>\(\) const.*\n' +
|
||||
_GCC_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*error: no matching function for call to \'ImplicitCast_\('
|
||||
r'(:?long )?int&\)')
|
||||
clang_regex = (r'\bgmock-actions.h:.* error: no matching function for '
|
||||
r'call to \'ImplicitCast_\'\r?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
|
||||
r'of function template specialization '
|
||||
r'\'testing::internal::ReturnAction<(int|long)>::operator '
|
||||
r'Action<(?P<type>.*)\(\)>\' requested here')
|
||||
diagnosis = """
|
||||
You are probably calling Return(NULL) and the compiler isn't sure how to turn
|
||||
NULL into %(type)s. Use ReturnNull() instead.
|
||||
Note: the line number may be off; please fix all instances of Return(NULL)."""
|
||||
return _GenericDiagnoser(
|
||||
'NRNULL', 'Need to use ReturnNull',
|
||||
[(clang_regex, diagnosis),
|
||||
(gcc_regex, diagnosis % {'type': 'the right type'})],
|
||||
msg)
|
||||
|
||||
|
||||
def _TypeInTemplatedBaseDiagnoser(msg):
|
||||
"""Diagnoses the TTB disease, given the error messages by the compiler."""
|
||||
|
||||
# This version works when the type is used as the mock function's return
|
||||
# type.
|
||||
gcc_4_3_1_regex_type_in_retval = (
|
||||
r'In member function \'int .*\n' + _GCC_FILE_LINE_RE +
|
||||
r'error: a function call cannot appear in a constant-expression')
|
||||
gcc_4_4_0_regex_type_in_retval = (
|
||||
r'error: a function call cannot appear in a constant-expression'
|
||||
+ _GCC_FILE_LINE_RE + r'error: template argument 1 is invalid\n')
|
||||
# This version works when the type is used as the mock function's sole
|
||||
# parameter type.
|
||||
gcc_regex_type_of_sole_param = (
|
||||
_GCC_FILE_LINE_RE +
|
||||
r'error: \'(?P<type>.+)\' was not declared in this scope\n'
|
||||
r'.*error: template argument 1 is invalid\n')
|
||||
# This version works when the type is used as a parameter of a mock
|
||||
# function that has multiple parameters.
|
||||
gcc_regex_type_of_a_param = (
|
||||
r'error: expected `;\' before \'::\' token\n'
|
||||
+ _GCC_FILE_LINE_RE +
|
||||
r'error: \'(?P<type>.+)\' was not declared in this scope\n'
|
||||
r'.*error: template argument 1 is invalid\n'
|
||||
r'.*error: \'.+\' was not declared in this scope')
|
||||
clang_regex_type_of_retval_or_sole_param = (
|
||||
_CLANG_FILE_LINE_RE +
|
||||
r'error: use of undeclared identifier \'(?P<type>.*)\'\n'
|
||||
r'(.*\n)*?'
|
||||
r'(?P=file):(?P=line):\d+: error: '
|
||||
r'non-friend class member \'Result\' cannot have a qualified name'
|
||||
)
|
||||
clang_regex_type_of_a_param = (
|
||||
_CLANG_FILE_LINE_RE +
|
||||
r'error: C\+\+ requires a type specifier for all declarations\n'
|
||||
r'(.*\n)*?'
|
||||
r'(?P=file):(?P=line):(?P=column): error: '
|
||||
r'C\+\+ requires a type specifier for all declarations'
|
||||
)
|
||||
clang_regex_unknown_type = (
|
||||
_CLANG_FILE_LINE_RE +
|
||||
r'error: unknown type name \'(?P<type>[^\']+)\''
|
||||
)
|
||||
|
||||
diagnosis = """
|
||||
In a mock class template, types or typedefs defined in the base class
|
||||
template are *not* automatically visible. This is how C++ works. Before
|
||||
you can use a type or typedef named %(type)s defined in base class Base<T>, you
|
||||
need to make it visible. One way to do it is:
|
||||
|
||||
typedef typename Base<T>::%(type)s %(type)s;"""
|
||||
|
||||
for diag in _GenericDiagnoser(
|
||||
'TTB', 'Type in Template Base',
|
||||
[(gcc_4_3_1_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
|
||||
(gcc_4_4_0_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
|
||||
(gcc_regex_type_of_sole_param, diagnosis),
|
||||
(gcc_regex_type_of_a_param, diagnosis),
|
||||
(clang_regex_type_of_retval_or_sole_param, diagnosis),
|
||||
(clang_regex_type_of_a_param, diagnosis % {'type': 'Foo'})],
|
||||
msg):
|
||||
yield diag
|
||||
# Avoid overlap with the NUS pattern.
|
||||
for m in _FindAllMatches(clang_regex_unknown_type, msg):
|
||||
type_ = m.groupdict()['type']
|
||||
if type_ not in _COMMON_GMOCK_SYMBOLS:
|
||||
yield ('TTB', 'Type in Template Base', diagnosis % m.groupdict())
|
||||
|
||||
|
||||
def _WrongMockMethodMacroDiagnoser(msg):
|
||||
"""Diagnoses the WMM disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE +
|
||||
r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
|
||||
r'.*\n'
|
||||
r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
|
||||
clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'error:.*array.*negative.*r?\n'
|
||||
r'(.*\n)*?'
|
||||
r'(?P=file):(?P=line):(?P=column): error: too few arguments '
|
||||
r'to function call, expected (?P<args>\d+), '
|
||||
r'have (?P<wrong_args>\d+)')
|
||||
clang11_re = (_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'.*this_method_does_not_take_'
|
||||
r'(?P<wrong_args>\d+)_argument.*')
|
||||
diagnosis = """
|
||||
You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
|
||||
%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
|
||||
MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
|
||||
return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang11_re, diagnosis % {'wrong_args': 'm',
|
||||
'args': 'n'}),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _WrongParenPositionDiagnoser(msg):
|
||||
"""Diagnoses the WPP disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE +
|
||||
r'error:.*testing::internal::MockSpec<.* has no member named \''
|
||||
r'(?P<method>\w+)\'')
|
||||
clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'error: no member named \'(?P<method>\w+)\' in '
|
||||
r'\'testing::internal::MockSpec<.*>\'')
|
||||
diagnosis = """
|
||||
The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
|
||||
".%(method)s". For example, you should write:
|
||||
EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
|
||||
instead of:
|
||||
EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
|
||||
return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
_DIAGNOSERS = [
|
||||
_IncompleteByReferenceArgumentDiagnoser,
|
||||
_MockObjectPointerDiagnoser,
|
||||
_NeedToReturnNothingDiagnoser,
|
||||
_NeedToReturnReferenceDiagnoser,
|
||||
_NeedToReturnSomethingDiagnoser,
|
||||
_NeedToUseReturnNullDiagnoser,
|
||||
_NeedToUseSymbolDiagnoser,
|
||||
_OverloadedFunctionActionDiagnoser,
|
||||
_OverloadedFunctionMatcherDiagnoser,
|
||||
_OverloadedMethodActionDiagnoser,
|
||||
_TypeInTemplatedBaseDiagnoser,
|
||||
_WrongMockMethodMacroDiagnoser,
|
||||
_WrongParenPositionDiagnoser,
|
||||
]
|
||||
|
||||
|
||||
def Diagnose(msg):
|
||||
"""Generates all possible diagnoses given the compiler error message."""
|
||||
|
||||
msg = re.sub(r'\x1b\[[^m]*m', '', msg) # Strips all color formatting.
|
||||
# Assuming the string is using the UTF-8 encoding, replaces the left and
|
||||
# the right single quote characters with apostrophes.
|
||||
msg = re.sub(r'(\xe2\x80\x98|\xe2\x80\x99)', "'", msg)
|
||||
|
||||
diagnoses = []
|
||||
for diagnoser in _DIAGNOSERS:
|
||||
for diag in diagnoser(msg):
|
||||
diagnosis = '[%s - %s]\n%s' % diag
|
||||
if not diagnosis in diagnoses:
|
||||
diagnoses.append(diagnosis)
|
||||
return diagnoses
|
||||
|
||||
|
||||
def main():
|
||||
print ('Google Mock Doctor v%s - '
|
||||
'diagnoses problems in code using Google Mock.' % _VERSION)
|
||||
|
||||
if sys.stdin.isatty():
|
||||
print ('Please copy and paste the compiler errors here. Press c-D when '
|
||||
'you are done:')
|
||||
else:
|
||||
print ('Waiting for compiler errors on stdin . . .')
|
||||
|
||||
msg = sys.stdin.read().strip()
|
||||
diagnoses = Diagnose(msg)
|
||||
count = len(diagnoses)
|
||||
if not count:
|
||||
print ("""
|
||||
Your compiler complained:
|
||||
8<------------------------------------------------------------
|
||||
%s
|
||||
------------------------------------------------------------>8
|
||||
|
||||
Uh-oh, I'm not smart enough to figure out what the problem is. :-(
|
||||
However...
|
||||
If you send your source code and the compiler's error messages to
|
||||
%s, you can be helped and I can get smarter --
|
||||
win-win for us!""" % (msg, _EMAIL))
|
||||
else:
|
||||
print ('------------------------------------------------------------')
|
||||
print ('Your code appears to have the following',)
|
||||
if count > 1:
|
||||
print ('%s diseases:' % (count,))
|
||||
else:
|
||||
print ('disease:')
|
||||
i = 0
|
||||
for d in diagnoses:
|
||||
i += 1
|
||||
if count > 1:
|
||||
print ('\n#%s:' % (i,))
|
||||
print (d)
|
||||
print ("""
|
||||
How did I do? If you think I'm wrong or unhelpful, please send your
|
||||
source code and the compiler's error messages to %s.
|
||||
Then you can be helped and I can get smarter -- I promise I won't be upset!""" %
|
||||
_EMAIL)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -1,18 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2007 Google Inc.
|
||||
# Copyright 2009, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# * 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.
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# 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.
|
||||
|
||||
"""Tool for uploading diffs from a version control system to the codereview app.
|
||||
|
||||
|
@ -73,6 +73,7 @@ using testing::Return;
|
||||
using testing::ReturnNull;
|
||||
using testing::ReturnRef;
|
||||
using testing::ReturnRefOfCopy;
|
||||
using testing::ReturnRoundRobin;
|
||||
using testing::SetArgPointee;
|
||||
using testing::SetArgumentPointee;
|
||||
using testing::Unused;
|
||||
@ -670,6 +671,31 @@ TEST(ReturnRefOfCopyTest, IsCovariant) {
|
||||
EXPECT_NE(&derived, &a.Perform(std::make_tuple()));
|
||||
}
|
||||
|
||||
// Tests that ReturnRoundRobin(v) works with initializer lists
|
||||
TEST(ReturnRoundRobinTest, WorksForInitList) {
|
||||
Action<int()> ret = ReturnRoundRobin({1, 2, 3});
|
||||
|
||||
EXPECT_EQ(1, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(2, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(3, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(1, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(2, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(3, ret.Perform(std::make_tuple()));
|
||||
}
|
||||
|
||||
// Tests that ReturnRoundRobin(v) works with vectors
|
||||
TEST(ReturnRoundRobinTest, WorksForVector) {
|
||||
std::vector<double> v = {4.4, 5.5, 6.6};
|
||||
Action<double()> ret = ReturnRoundRobin(v);
|
||||
|
||||
EXPECT_EQ(4.4, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(5.5, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(6.6, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(4.4, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(5.5, ret.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(6.6, ret.Perform(std::make_tuple()));
|
||||
}
|
||||
|
||||
// Tests that DoDefault() does the default action for the mock method.
|
||||
|
||||
class MockClass {
|
||||
|
5
googletest/scripts/README.md
Normal file
5
googletest/scripts/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Please Note:
|
||||
|
||||
Files in this directory are no longer supported by the maintainers. They
|
||||
represent mosty historical artifacts and supported by the community only. There
|
||||
is no guarantee whatsoever that these scripts still work.
|
@ -111,6 +111,8 @@ def HeaderPreamble(n):
|
||||
// '%(command)s'. DO NOT EDIT BY HAND!
|
||||
//
|
||||
// Implements a family of generic predicate assertion macros.
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||
@ -246,8 +248,10 @@ AssertionResult AssertPred%(n)sHelper(const char* pred_text""" % DEFS
|
||||
|
||||
impl += ' << ") evaluates to false, where"'
|
||||
|
||||
impl += Iter(n, """
|
||||
<< "\\n" << e%s << " evaluates to " << v%s""")
|
||||
impl += Iter(
|
||||
n, """
|
||||
<< "\\n" << e%s << " evaluates to " << ::testing::PrintToString(v%s)"""
|
||||
)
|
||||
|
||||
impl += """;
|
||||
}
|
||||
@ -510,7 +514,7 @@ struct PredFormatFunctor%(n)s {
|
||||
|
||||
class Predicate%(n)sTest : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
void SetUp() override {
|
||||
expected_to_finish_ = true;
|
||||
finished_ = false;""" % DEFS
|
||||
|
||||
@ -520,7 +524,7 @@ class Predicate%(n)sTest : public testing::Test {
|
||||
"""
|
||||
|
||||
tests += """
|
||||
virtual void TearDown() {
|
||||
void TearDown() override {
|
||||
// Verifies that each of the predicate's arguments was evaluated
|
||||
// exactly once."""
|
||||
|
||||
@ -588,7 +592,7 @@ typedef Predicate%(n)sTest ASSERT_PRED%(n)sTest;
|
||||
|
||||
if use_assert:
|
||||
assrt = 'ASSERT' # 'assert' is reserved, so we cannot use
|
||||
# that identifier here.
|
||||
# that identifier here.
|
||||
else:
|
||||
assrt = 'EXPECT'
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2.7
|
||||
#
|
||||
# Copyright 2008, Google Inc.
|
||||
# All rights reserved.
|
||||
@ -62,7 +62,7 @@ GRAMMAR:
|
||||
EXPRESSION has Python syntax.
|
||||
"""
|
||||
|
||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import re
|
||||
@ -246,7 +246,7 @@ def ParseToken(lines, pos, regex, token_type):
|
||||
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)
|
||||
print('ERROR: %s expected at %s.' % (token_type, pos))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@ -453,8 +453,8 @@ def PushFront(a_list, 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,)
|
||||
print('ERROR: %s expected at %s' % (token_type, token.start))
|
||||
print('ERROR: %s found instead' % (token,))
|
||||
sys.exit(1)
|
||||
|
||||
return token
|
||||
@ -616,16 +616,16 @@ class Env:
|
||||
if identifier == var:
|
||||
return value
|
||||
|
||||
print 'ERROR: meta variable %s is undefined.' % (identifier,)
|
||||
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))
|
||||
except Exception as e: # pylint: disable=broad-except
|
||||
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
|
||||
|
||||
@ -634,7 +634,7 @@ class Env:
|
||||
if identifier == var:
|
||||
return (lower, upper)
|
||||
|
||||
print 'ERROR: range %s is undefined.' % (identifier,)
|
||||
print('ERROR: range %s is undefined.' % (identifier,))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@ -694,8 +694,8 @@ def RunAtomicCode(env, node, output):
|
||||
elif isinstance(node, CodeNode):
|
||||
RunCode(env.Clone(), node, output)
|
||||
else:
|
||||
print 'BAD'
|
||||
print node
|
||||
print('BAD')
|
||||
print(node)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@ -830,7 +830,7 @@ def ConvertFromPumpSource(src_text):
|
||||
|
||||
def main(argv):
|
||||
if len(argv) == 1:
|
||||
print __doc__
|
||||
print(__doc__)
|
||||
sys.exit(1)
|
||||
|
||||
file_path = argv[-1]
|
||||
@ -840,7 +840,7 @@ def main(argv):
|
||||
else:
|
||||
output_file_path = '-'
|
||||
if output_file_path == '-':
|
||||
print output_str,
|
||||
print(output_str,)
|
||||
else:
|
||||
output_file = file(output_file_path, 'w')
|
||||
output_file.write('// This file was GENERATED by command:\n')
|
||||
|
32
googletest/scripts/run_with_path.py
Executable file
32
googletest/scripts/run_with_path.py
Executable file
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2010 Google Inc. All Rights Reserved.
|
||||
|
||||
"""Runs program specified in the command line with the substituted PATH.
|
||||
|
||||
This script is needed for to support building under Pulse which is unable
|
||||
to override the existing PATH variable.
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
SUBST_PATH_ENV_VAR_NAME = "SUBST_PATH"
|
||||
|
||||
def main():
|
||||
if SUBST_PATH_ENV_VAR_NAME in os.environ:
|
||||
os.environ["PATH"] = os.environ[SUBST_PATH_ENV_VAR_NAME]
|
||||
|
||||
exit_code = subprocess.Popen(sys.argv[1:]).wait()
|
||||
|
||||
# exit_code is negative (-signal) if the process has been terminated by
|
||||
# a signal. Returning negative exit code is not portable and so we return
|
||||
# 100 instead.
|
||||
if exit_code < 0:
|
||||
exit_code = 100
|
||||
|
||||
sys.exit(exit_code)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,18 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2007 Google Inc.
|
||||
# Copyright 2007, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
# * 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.
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# 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.
|
||||
|
||||
"""Tool for uploading diffs from a version control system to the codereview app.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user