aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/generator/cpp/gmock_class_test.py
blob: ae00800fa7efb296564821b36cd9bafa27cb5e00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env python
#
# Copyright 2009 Neal Norwitz All Rights Reserved.
# Portions 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
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# 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.

"""Tests for gmock.scripts.generator.cpp.gmock_class."""

__author__ = 'nnorwitz@google.com (Neal Norwitz)'


import os
import sys
import unittest

# Allow the cpp imports below to work when run as a standalone script.
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

from cpp import ast
from cpp import gmock_class


class TestCase(unittest.TestCase):
  """Helper class that adds assert methods."""

  def assertEqualIgnoreLeadingWhitespace(self, expected_lines, lines):
    """Specialized assert that ignores the indent level."""
    stripped_lines = '\n'.join([s.lstrip() for s in lines.split('\n')])
    self.assertEqual(expected_lines, stripped_lines)


class GenerateMethodsTest(TestCase):

  def GenerateMethodSource(self, cpp_source):
    """Helper method to convert C++ source to gMock output source lines."""
    method_source_lines = []
    # <test> is a pseudo-filename, it is not read or written.
    builder = ast.BuilderFromSource(cpp_source, '<test>')
    ast_list = list(builder.Generate())
    gmock_class._GenerateMethods(method_source_lines, cpp_source, ast_list[0])
    return ''.join(method_source_lines)

  def testStrangeNewlineInParameter(self):
    source = """
class Foo {
 public:
  virtual void Bar(int
a) = 0;
};
"""
    self.assertEqualIgnoreLeadingWhitespace(
        'MOCK_METHOD1(Bar,\nvoid(int a));',
        self.GenerateMethodSource(source))

  def testDoubleSlashCommentsInParameterListAreRemoved(self):
    source = """
class Foo {
 public:
  virtual void Bar(int a,  // inline comments should be elided.
                   int b   // inline comments should be elided.
                   ) const = 0;
};
"""
    self.assertEqualIgnoreLeadingWhitespace(
        'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));',
        self.GenerateMethodSource(source))

  def testCStyleCommentsInParameterListAreNotRemoved(self):
    # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these
    # comments.  Also note that C style comments after the last parameter
    # are still elided.
    source = """
class Foo {
 public:
  virtual const string& Bar(int /* keeper */, int b);
};
"""
    self.assertEqualIgnoreLeadingWhitespace(
        'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));',
        self.GenerateMethodSource(source))


class GenerateMocksTest(TestCase):

  def GenerateMocks(self, cpp_source):
    """Helper method to convert C++ source to complete gMock output source."""
    # <test> is a pseudo-filename, it is not read or written.
    filename = '<test>'
    builder = ast.BuilderFromSource(cpp_source, filename)
    ast_list = list(builder.Generate())
    lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None)
    return '\n'.join(lines)

  def testNamespaces(self):
    source = """
namespace Foo {
namespace Bar { class Forward; }
namespace Baz {

class Test {
 public:
  virtual void Foo();
};

}  // namespace Baz
}  // namespace Foo
"""
    expected = """\
namespace Foo {
namespace Baz {

class MockTest : public Test {
public:
MOCK_METHOD0(Foo,
void());
};

}  // namespace Baz
}  // namespace Foo
"""
    self.assertEqualIgnoreLeadingWhitespace(
        expected, self.GenerateMocks(source))


if __name__ == '__main__':
  unittest.main()
class="n">test; /* * Pointers to the spawned threads. */ Thread *threads[MAX_THREADS]; /* * Pointers to the working areas. */ void * ROMCONST wa[5] = {test.wa.T0, test.wa.T1, test.wa.T2, test.wa.T3, test.wa.T4}; /* * Console output. */ static BaseChannel *chp; /** * @brief Prints a decimal unsigned number. * * @param[in] n the number to be printed */ void test_printn(uint32_t n) { char buf[16], *p; if (!n) chIOPut(chp, '0'); else { p = buf; while (n) *p++ = (n % 10) + '0', n /= 10; while (p > buf) chIOPut(chp, *--p); } } /** * @brief Prints a line without final end-of-line. * * @param[in] msgp the message */ void test_print(const char *msgp) { while (*msgp) chIOPut(chp, *msgp++); } /** * @brief Prints a line. * * @param[in] msgp the message */ void test_println(const char *msgp) { test_print(msgp); chIOPut(chp, '\r'); chIOPut(chp, '\n'); } /* * Tokens. */ static void clear_tokens(void) { tokp = tokens_buffer; } static void print_tokens(void) { char *cp = tokens_buffer; while (cp < tokp) chIOPut(chp, *cp++); } /** * @brief Emits a token into the tokens buffer. * * @param[in] token the token as a char */ void test_emit_token(char token) { chSysLock(); *tokp++ = token; chSysUnlock(); } /* * Assertions. */ bool_t _test_fail(unsigned point) { local_fail = TRUE; global_fail = TRUE; failpoint = point; return TRUE; } bool_t _test_assert(unsigned point, bool_t condition) { if (!condition) return _test_fail(point); return FALSE; } bool_t _test_assert_sequence(unsigned point, char *expected) { char *cp = tokens_buffer; while (cp < tokp) { if (*cp++ != *expected++) return _test_fail(point); } if (*expected) return _test_fail(point); clear_tokens(); return FALSE; } bool_t _test_assert_time_window(unsigned point, systime_t start, systime_t end) { return _test_assert(point, chTimeIsWithin(start, end)); } /* * Threads utils. */ /** * @brief Sets a termination request in all the test-spawned threads. */ void test_terminate_threads(void) { int i; for (i = 0; i < MAX_THREADS; i++) if (threads[i]) chThdTerminate(threads[i]); } /** * @brief Waits for the completion of all the test-spawned threads. */ void test_wait_threads(void) { int i; for (i = 0; i < MAX_THREADS; i++) if (threads[i] != NULL) { chThdWait(threads[i]); threads[i] = NULL; } } #if CH_DBG_THREADS_PROFILING /** * @brief CPU pulse. * @note The current implementation is not totally reliable. * * @param[in] duration CPU pulse duration in milliseconds */ void test_cpu_pulse(unsigned duration) { systime_t start, end, now; start = chThdSelf()->p_time; end = start + MS2ST(duration); do { now = chThdSelf()->p_time; #if defined(SIMULATOR) ChkIntSources(); #endif } while (end > start ? (now >= start) && (now < end) : (now >= start) || (now < end)); } #endif /** * @brief Delays execution until next system time tick. * * @return The system time. */ systime_t test_wait_tick(void) { chThdSleep(1); return chTimeNow(); } /* * Timer utils. */ /** * @brief Set to @p TRUE when the test timer reaches its deadline. */ bool_t test_timer_done; static VirtualTimer vt; static void tmr(void *p) { (void)p; test_timer_done = TRUE; } /** * @brief Starts the test timer. * * @param[in] ms time in milliseconds */ void test_start_timer(unsigned ms) { systime_t duration = MS2ST(ms); test_timer_done = FALSE; chSysLock(); chVTSetI(&vt, duration, tmr, NULL); chSysUnlock(); } /* * Test suite execution. */ static void execute_test(const struct testcase *tcp) { int i; /* Initialization */ clear_tokens(); local_fail = FALSE; for (i = 0; i < MAX_THREADS; i++) threads[i] = NULL; if (tcp->setup != NULL) tcp->setup(); tcp->execute(); if (tcp->teardown != NULL) tcp->teardown(); test_wait_threads(); } static void print_line(void) { unsigned i; for (i = 0; i < 76; i++) chIOPut(chp, '-'); chIOPut(chp, '\r'); chIOPut(chp, '\n'); } /** * @brief Test execution thread function. * * @param[in] p pointer to a @p BaseChannel object for test output * @return A failure boolean value. */ msg_t TestThread(void *p) { int i, j; chp = p; test_println(""); test_println("*** ChibiOS/RT test suite"); test_println("***"); test_print("*** Kernel: "); test_println(CH_KERNEL_VERSION); #ifdef CH_COMPILER_NAME test_print("*** Compiler: "); test_println(CH_COMPILER_NAME); #endif test_print("*** Architecture: "); test_println(CH_ARCHITECTURE_NAME); #ifdef CH_CORE_VARIANT_NAME test_print("*** Core Variant: "); test_println(CH_CORE_VARIANT_NAME); #endif #ifdef CH_PORT_INFO test_print("*** Port Info: "); test_println(CH_PORT_INFO); #endif #ifdef PLATFORM_NAME test_print("*** Platform: "); test_println(PLATFORM_NAME); #endif #ifdef BOARD_NAME test_print("*** Test Board: "); test_println(BOARD_NAME); #endif test_println(""); global_fail = FALSE; i = 0; while (patterns[i]) { j = 0; while (patterns[i][j]) { print_line(); test_print("--- Test Case "); test_printn(i + 1); test_print("."); test_printn(j + 1); test_print(" ("); test_print(patterns[i][j]->name); test_println(")"); #if DELAY_BETWEEN_TESTS > 0 chThdSleepMilliseconds(DELAY_BETWEEN_TESTS); #endif execute_test(patterns[i][j]); if (local_fail) { test_print("--- Result: FAILURE (#"); test_printn(failpoint); test_print(" ["); print_tokens(); test_println("])"); } else test_println("--- Result: SUCCESS"); j++; } i++; } print_line(); test_println(""); test_print("Final result: "); if (global_fail) test_println("FAILURE"); else test_println("SUCCESS"); return (msg_t)global_fail; } /** @} */