aboutsummaryrefslogtreecommitdiffstats
path: root/googlemock/test/gmock-internal-utils_test.cc
blob: 9c2423ecd344a5130075effc85a586328ebd36be (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
138
139
140
141pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# Haptic Feedback

## Haptic feedback rules.mk options

The following options are currently available for haptic feedback in `rule.mk`:

`HAPTIC_ENABLE += DRV2605L`

`HAPTIC_ENABLE += SOLENOID`

## Known Supported Hardware

| Name               | Description                                     |
|--------------------|-------------------------------------------------|
| [LV061228B-L65-A](https://www.digikey.com/product-detail/en/jinlong-machinery-electronics-inc/LV061228B-L65-A/1670-1050-ND/7732325) | z-axis 2v LRA |
| [Mini Motor Disc](https://www.adafruit.com/product/1201)  | small 2-5v ERM |

## Haptic Keycodes

Not all keycodes below will work depending on which haptic mechanism you have chosen.

| Name      | Description                                           |
|-----------|-------------------------------------------------------|
|`HPT_ON`   | Turn haptic feedback on                               |
|`HPT_OFF`  | Turn haptic feedback on                               |
|`HPT_TOG`  | Toggle haptic feedback on/off                         |
|`HPT_RST`  | Reset haptic feedback config to default               |
|`HPT_FBK`  | Toggle feedback to occur on keypress, release or both |
|`HPT_BUZ`  | Toggle solenoid buzz on/off                           |
|`HPT_MODI` | Go to next DRV2605L waveform                          |
|`HPT_MODD` | Go to previous DRV2605L waveform                      |
|`HPT_DWLI` | Increase Solenoid dwell time                          |
|`HPT_DWLD` | Decrease Solenoid dwell time                          |

### Solenoids

First you will need a build a circuit to drive the solenoid through a mosfet as most MCU will not be able to provide the current needed to drive the coil in the solenoid.

[Wiring diagram provided by Adafruit](https://playground.arduino.cc/uploads/Learning/solenoid_driver.pdf)

Select a pin that has PWM for the signal pin

```
#define SOLENOID_PIN *pin*
```

Beware that some pins may be powered during bootloader (ie. A13 on the STM32F303 chip) and will result in the solenoid kept in the on state through the whole flashing process. This may overheat and damage the solenoid. If you find that the pin the solenoid is connected to is triggering the solenoid during bootloader/DFU, select another pin.

### DRV2605L

DRV2605L is controlled over i2c protocol, and has to be connected to the SDA and SCL pins, these varies depending on the MCU in use.

#### Feedback motor setup

This driver supports 2 different feedback motors. Set the following in your `config.h` based on which motor you have selected.

##### ERM

Eccentric Rotating Mass vibration motors (ERM) is motor with a off-set weight attached so when drive signal is attached, the off-set weight spins and causes a sinusoidal wave that translate into vibrations.

```
#define FB_ERM_LRA 0
#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
#define FB_LOOPGAIN 1 /* For  Low:0, Medium:1, High:2, Very High:3 */

/* Please refer to your datasheet for the optimal setting for your specific motor. */
#define RATED_VOLTAGE 3
#define V_PEAK 5
```
##### LRA

Linear resonant actuators (LRA, also know as a linear vibrator) works different from a ERM. A LRA has a weight and magnet suspended by springs and a voice coil. When the drive signal is applied, the weight would be vibrate on a single axis (side to side or up and down). Since the weight is attached to a spring, there is a resonance effect at a specific frequency. This frequency is where the LRA will operate the most efficiently. Refer to the motor's datasheet for the recommanded range for this frequency.

``` 
#define FB_ERM_LRA 1
#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
#define FB_LOOPGAIN 1 /* For  Low:0, Medium:1, High:2, Very High:3 */

/* Please refer to your datasheet for the optimal setting for your specific motor. */
#define RATED_VOLTAGE 2
#define V_PEAK 2.8
#define V_RMS 2.0 
#define V_PEAK 2.1
#define F_LRA 205 /* resonance freq */
```

#### DRV2605L waveform library

DRV2605L comes with preloaded library of various waveform sequences that can be called and played. If writing a macro, these waveforms can be played using `DRV_pulse(*sequence name or number*)`

List of waveform sequences from the datasheet:

|seq# | Sequence name          |seq# | Sequence name                  |seq# |Sequence name                           |
|-----|---------------------|-----|-----------------------------------|-----|--------------------------------------|
| 1   | strong_click 		| 43  | lg_dblclick_med_60                | 85  | transition_rampup_med_smooth2        |
| 2   | strong_click_60 	| 44  | lg_dblsharp_tick                  | 86  | transition_rampup_short_smooth1      |
| 3   | strong_click_30 	| 45  | lg_dblsharp_tick_80               | 87  | transition_rampup_short_smooth2      |
| 4   | sharp_click 		| 46  | lg_dblsharp_tick_60               | 88  | transition_rampup_long_sharp1        |
| 5   | sharp_click_60      | 47  | buzz                              | 89  | transition_rampup_long_sharp2        |
| 6   | sharp_click_30      | 48  | buzz_80				              | 90  | transition_rampup_med_sharp1         |
| 7   | soft_bump           | 49  | buzz_60		                      | 91  | transition_rampup_med_sharp2         |
| 8   | soft_bump_60        | 50  | buzz_40				              | 92  | transition_rampup_short_sharp1       |
| 9   | soft_bump_30        | 51  | buzz_20				              | 93  | transition_rampup_short_sharp2       |
| 10  | dbl_click           | 52  | pulsing_strong                    | 94  | transition_rampdown_long_smooth1_50  |
| 11  | dbl_click_60        | 53  | pulsing_strong_80                 | 95  | transition_rampdown_long_smooth2_50  |
| 12  | trp_click           | 54  | pulsing_medium                    | 96  | transition_rampdown_med_smooth1_50   |
| 13  | soft_fuzz           | 55  | pulsing_medium_80                 | 97  | transition_rampdown_med_smooth2_50   |
| 14  | strong_buzz         | 56  | pulsing_sharp                     | 98  | transition_rampdown_short_smooth1_50 |
| 15  | alert_750ms         | 57  | pulsing_sharp_80                  | 99  | transition_rampdown_short_smooth2_50 |
| 16  | alert_1000ms        | 58  | transition_click	              | 100 | transition_rampdown_long_sharp1_50   |
| 17  | strong_click1       | 59  | transition_click_80               | 101 | transition_rampdown_long_sharp2_50   |
| 18  | strong_click2_80    | 60  | transition_click_60	              | 102 | transition_rampdown_med_sharp1_50    |
| 19  | strong_click3_60    | 61  | transition_click_40	              | 103 | transition_rampdown_med_sharp2_50    |
| 20  | strong_click4_30    | 62  | transition_click_20	              | 104 | transition_rampdown_short_sharp1_50  |
| 21  | medium_click1       | 63  | transition_click_10	              | 105 | transition_rampdown_short_sharp2_50  |
| 22  | medium_click2_80    | 64  | transition_hum                    | 106 | transition_rampup_long_smooth1_50    |
| 23  | medium_click3_60    | 65  | transition_hum_80                 | 107 | transition_rampup_long_smooth2_50    |
| 24  | sharp_tick1         | 66  | transition_hum_60                 | 108 | transition_rampup_med_smooth1_50     |
| 25  | sharp_tick2_80      | 67  | transition_hum_40                 | 109 | transition_rampup_med_smooth2_50     |
| 26  | sharp_tick3_60      | 68  | transition_hum_20                 | 110 | transition_rampup_short_smooth1_50   |
| 27  | sh_dblclick_str     | 69  | transition_hum_10                 | 111 | transition_rampup_short_smooth2_50   |
| 28  | sh_dblclick_str_80  | 70  | transition_rampdown_long_smooth1  | 112 | transition_rampup_long_sharp1_50     |
| 29  | sh_dblclick_str_60  | 71  | transition_rampdown_long_smooth2  | 113 | transition_rampup_long_sharp2_50     |
| 30  | sh_dblclick_str_30  | 72  | transition_rampdown_med_smooth1   | 114 | transition_rampup_med_sharp1_50      |
| 31  | sh_dblclick_med     | 73  | transition_rampdown_med_smooth2   | 115 | transition_rampup_med_sharp2_50      |
| 32  | sh_dblclick_med_80  | 74  | transition_rampdown_short_smooth1 | 116 | transition_rampup_short_sharp1_50    |
| 33  | sh_dblclick_med_60  | 75  | transition_rampdown_short_smooth2 | 117 | transition_rampup_short_sharp2_50    |
| 34  | sh_dblsharp_tick    | 76  | transition_rampdown_long_sharp1   | 118 | long_buzz_for_programmatic_stopping  |
| 35  | sh_dblsharp_tick_80 | 77  | transition_rampdown_long_sharp2   | 119 | smooth_hum1_50                       |
| 36  | sh_dblsharp_tick_60 | 78  | transition_rampdown_med_sharp1    | 120 | smooth_hum2_40                       |
| 37  | lg_dblclick_str     | 79  | transition_rampdown_med_sharp2    | 121 | smooth_hum3_30                       |
| 38  | lg_dblclick_str_80  | 80  | transition_rampdown_short_sharp1  | 122 | smooth_hum4_20                       |
| 39  | lg_dblclick_str_60  | 81  | transition_rampdown_short_sharp2  | 123 | smooth_hum5_10                       |
| 40  | lg_dblclick_str_30  | 82  | transition_rampup_long_smooth1    |     |                                      |
| 41  | lg_dblclick_med     | 83  | transition_rampup_long_smooth2    |     |                                      |
| 42  | lg_dblclick_med_80  | 84  | transition_rampup_med_smooth1     |     |                                      |
### Optional DRV2605L defines

```
#define DRV_GREETING *sequence name or number*
```
If haptic feedback is enabled, the keyboard will vibrate to a specific sqeuence during startup. That can be selected using the following define:

```
#define DRV_MODE_DEFAULT *sequence name or number*
```
This will set what sequence HPT_RST will set as the active mode. If not defined, mode will be set to 1 when HPT_RST is pressed.
ef='#n632'>632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
// Copyright 2007, 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)

// Google Mock - a framework for writing C++ mock classes.
//
// This file tests the internal utilities.

#include "gmock/internal/gmock-internal-utils.h"
#include <stdlib.h>
#include <map>
#include <memory>
#include <string>
#include <sstream>
#include <vector>
#include "gmock/gmock.h"
#include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h"
#include "gtest/gtest-spi.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_

#if GTEST_OS_CYGWIN
# include <sys/types.h>  // For ssize_t. NOLINT
#endif

class ProtocolMessage;

namespace proto2 {
class Message;
}  // namespace proto2

namespace testing {
namespace internal {

namespace {

TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsNoWord) {
  EXPECT_EQ("", ConvertIdentifierNameToWords(""));
  EXPECT_EQ("", ConvertIdentifierNameToWords("_"));
  EXPECT_EQ("", ConvertIdentifierNameToWords("__"));
}

TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsDigits) {
  EXPECT_EQ("1", ConvertIdentifierNameToWords("_1"));
  EXPECT_EQ("2", ConvertIdentifierNameToWords("2_"));
  EXPECT_EQ("34", ConvertIdentifierNameToWords("_34_"));
  EXPECT_EQ("34 56", ConvertIdentifierNameToWords("_34_56"));
}

TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContainsCamelCaseWords) {
  EXPECT_EQ("a big word", ConvertIdentifierNameToWords("ABigWord"));
  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("FooBar"));
  EXPECT_EQ("foo", ConvertIdentifierNameToWords("Foo_"));
  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("_Foo_Bar_"));
  EXPECT_EQ("foo and bar", ConvertIdentifierNameToWords("_Foo__And_Bar"));
}

TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameContains_SeparatedWords) {
  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("foo_bar"));
  EXPECT_EQ("foo", ConvertIdentifierNameToWords("_foo_"));
  EXPECT_EQ("foo bar", ConvertIdentifierNameToWords("_foo_bar_"));
  EXPECT_EQ("foo and bar", ConvertIdentifierNameToWords("_foo__and_bar"));
}

TEST(ConvertIdentifierNameToWordsTest, WorksWhenNameIsMixture) {
  EXPECT_EQ("foo bar 123", ConvertIdentifierNameToWords("Foo_bar123"));
  EXPECT_EQ("chapter 11 section 1",
            ConvertIdentifierNameToWords("_Chapter11Section_1_"));
}

TEST(PointeeOfTest, WorksForSmartPointers) {
  CompileAssertTypesEqual<const char,
      PointeeOf<internal::linked_ptr<const char> >::type>();
#if GTEST_HAS_STD_UNIQUE_PTR_
  CompileAssertTypesEqual<int, PointeeOf<std::unique_ptr<int> >::type>();
#endif  // GTEST_HAS_STD_UNIQUE_PTR_
#if GTEST_HAS_STD_SHARED_PTR_
  CompileAssertTypesEqual<std::string,
                          PointeeOf<std::shared_ptr<std::string> >::type>();
#endif  // GTEST_HAS_STD_SHARED_PTR_
}

TEST(PointeeOfTest, WorksForRawPointers) {
  CompileAssertTypesEqual<int, PointeeOf<int*>::type>();
  CompileAssertTypesEqual<const char, PointeeOf<const char*>::type>();
  CompileAssertTypesEqual<void, PointeeOf<void*>::type>();
}

TEST(GetRawPointerTest, WorksForSmartPointers) {
#if GTEST_HAS_STD_UNIQUE_PTR_
  const char* const raw_p1 = new const char('a');  // NOLINT
  const std::unique_ptr<const char> p1(raw_p1);
  EXPECT_EQ(raw_p1, GetRawPointer(p1));
#endif  // GTEST_HAS_STD_UNIQUE_PTR_
#if GTEST_HAS_STD_SHARED_PTR_
  double* const raw_p2 = new double(2.5);  // NOLINT
  const std::shared_ptr<double> p2(raw_p2);
  EXPECT_EQ(raw_p2, GetRawPointer(p2));
#endif  // GTEST_HAS_STD_SHARED_PTR_

  const char* const raw_p4 = new const char('a');  // NOLINT
  const internal::linked_ptr<const char> p4(raw_p4);
  EXPECT_EQ(raw_p4, GetRawPointer(p4));
}

TEST(GetRawPointerTest, WorksForRawPointers) {
  int* p = NULL;
  // Don't use EXPECT_EQ as no NULL-testing magic on Symbian.
  EXPECT_TRUE(NULL == GetRawPointer(p));
  int n = 1;
  EXPECT_EQ(&n, GetRawPointer(&n));
}

// Tests KindOf<T>.

class Base {};
class Derived : public Base {};

TEST(KindOfTest, Bool) {
  EXPECT_EQ(kBool, GMOCK_KIND_OF_(bool));  // NOLINT
}

TEST(KindOfTest, Integer) {
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(char));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(signed char));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned char));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(short));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned short));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(int));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned int));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(long));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned long));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(wchar_t));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(Int64));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(UInt64));  // NOLINT
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(size_t));  // NOLINT
#if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN
  // ssize_t is not defined on Windows and possibly some other OSes.
  EXPECT_EQ(kInteger, GMOCK_KIND_OF_(ssize_t));  // NOLINT
#endif
}

TEST(KindOfTest, FloatingPoint) {
  EXPECT_EQ(kFloatingPoint, GMOCK_KIND_OF_(float));  // NOLINT
  EXPECT_EQ(kFloatingPoint, GMOCK_KIND_OF_(double));  // NOLINT
  EXPECT_EQ(kFloatingPoint, GMOCK_KIND_OF_(long double));  // NOLINT
}

TEST(KindOfTest, Other) {
  EXPECT_EQ(kOther, GMOCK_KIND_OF_(void*));  // NOLINT
  EXPECT_EQ(kOther, GMOCK_KIND_OF_(char**));  // NOLINT
  EXPECT_EQ(kOther, GMOCK_KIND_OF_(Base));  // NOLINT
}

// Tests LosslessArithmeticConvertible<T, U>.

TEST(LosslessArithmeticConvertibleTest, BoolToBool) {
  EXPECT_TRUE((LosslessArithmeticConvertible<bool, bool>::value));
}

TEST(LosslessArithmeticConvertibleTest, BoolToInteger) {
  EXPECT_TRUE((LosslessArithmeticConvertible<bool, char>::value));
  EXPECT_TRUE((LosslessArithmeticConvertible<bool, int>::value));
  EXPECT_TRUE(
      (LosslessArithmeticConvertible<bool, unsigned long>::value));  // NOLINT
}

TEST(LosslessArithmeticConvertibleTest, BoolToFloatingPoint) {
  EXPECT_TRUE((LosslessArithmeticConvertible<bool, float>::value));
  EXPECT_TRUE((LosslessArithmeticConvertible<bool, double>::value));
}

TEST(LosslessArithmeticConvertibleTest, IntegerToBool) {
  EXPECT_FALSE((LosslessArithmeticConvertible<unsigned char, bool>::value));
  EXPECT_FALSE((LosslessArithmeticConvertible<int, bool>::value));
}

TEST(LosslessArithmeticConvertibleTest, IntegerToInteger) {
  // Unsigned => larger signed is fine.
  EXPECT_TRUE((LosslessArithmeticConvertible<unsigned char, int>::value));

  // Unsigned => larger unsigned is fine.
  EXPECT_TRUE(
      (LosslessArithmeticConvertible<unsigned short, UInt64>::value)); // NOLINT

  // Signed => unsigned is not fine.
  EXPECT_FALSE((LosslessArithmeticConvertible<short, UInt64>::value)); // NOLINT
  EXPECT_FALSE((LosslessArithmeticConvertible<
      signed char, unsigned int>::value));  // NOLINT

  // Same size and same signedness: fine too.
  EXPECT_TRUE((LosslessArithmeticConvertible<
               unsigned char, unsigned char>::value));
  EXPECT_TRUE((LosslessArithmeticConvertible<int, int>::value));
  EXPECT_TRUE((LosslessArithmeticConvertible<wchar_t, wchar_t>::value));
  EXPECT_TRUE((LosslessArithmeticConvertible<
               unsigned long, unsigned long>::value));  // NOLINT

  // Same size, different signedness: not fine.
  EXPECT_FALSE((LosslessArithmeticConvertible<
                unsigned char, signed char>::value));
  EXPECT_FALSE((LosslessArithmeticConvertible<int, unsigned int>::value));
  EXPECT_FALSE((LosslessArithmeticConvertible<UInt64, Int64>::value));

  // Larger size => smaller size is not fine.
  EXPECT_FALSE((LosslessArithmeticConvertible<long, char>::value));  // NOLINT
  EXPECT_FALSE((LosslessArithmeticConvertible<int, signed char>::value));
  EXPECT_FALSE((LosslessArithmeticConvertible<Int64, unsigned int>::value));
}

TEST(LosslessArithmeticConvertibleTest, IntegerToFloatingPoint) {
  // Integers cannot be losslessly converted to floating-points, as
  // the format of the latter is implementation-defined.
  EXPECT_FALSE((LosslessArithmeticConvertible<char, float>::value));
  EXPECT_FALSE((LosslessArithmeticConvertible<int, double>::value));
  EXPECT_FALSE((LosslessArithmeticConvertible<
                short, long double>::value));  // NOLINT
}

TEST(LosslessArithmeticConvertibleTest, FloatingPointToBool) {
  EXPECT_FALSE((LosslessArithmeticConvertible<float, bool>::value));
  EXPECT_FALSE((LosslessArithmeticConvertible<double, bool>::value));
}

TEST(LosslessArithmeticConvertibleTest, FloatingPointToInteger) {
  EXPECT_FALSE((LosslessArithmeticConvertible<float, long>::value));  // NOLINT
  EXPECT_FALSE((LosslessArithmeticConvertible<double, Int64>::value));
  EXPECT_FALSE((LosslessArithmeticConvertible<long double, int>::value));
}

TEST(LosslessArithmeticConvertibleTest, FloatingPointToFloatingPoint) {
  // Smaller size => larger size is fine.
  EXPECT_TRUE((LosslessArithmeticConvertible<float, double>::value));
  EXPECT_TRUE((LosslessArithmeticConvertible<float, long double>::value));
  EXPECT_TRUE((LosslessArithmeticConvertible<double, long double>::value));

  // Same size: fine.
  EXPECT_TRUE((LosslessArithmeticConvertible<float, float>::value));
  EXPECT_TRUE((LosslessArithmeticConvertible<double, double>::value));

  // Larger size => smaller size is not fine.
  EXPECT_FALSE((LosslessArithmeticConvertible<double, float>::value));
  GTEST_INTENTIONAL_CONST_COND_PUSH_()
  if (sizeof(double) == sizeof(long double)) {  // NOLINT
  GTEST_INTENTIONAL_CONST_COND_POP_()
    // In some implementations (e.g. MSVC), double and long double
    // have the same size.
    EXPECT_TRUE((LosslessArithmeticConvertible<long double, double>::value));
  } else {
    EXPECT_FALSE((LosslessArithmeticConvertible<long double, double>::value));
  }
}

// Tests the TupleMatches() template function.

TEST(TupleMatchesTest, WorksForSize0) {
  tuple<> matchers;
  tuple<> values;

  EXPECT_TRUE(TupleMatches(matchers, values));
}

TEST(TupleMatchesTest, WorksForSize1) {
  tuple<Matcher<int> > matchers(Eq(1));
  tuple<int> values1(1),
      values2(2);

  EXPECT_TRUE(TupleMatches(matchers, values1));
  EXPECT_FALSE(TupleMatches(matchers, values2));
}

TEST(TupleMatchesTest, WorksForSize2) {
  tuple<Matcher<int>, Matcher<char> > matchers(Eq(1), Eq('a'));
  tuple<int, char> values1(1, 'a'),
      values2(1, 'b'),
      values3(2, 'a'),
      values4(2, 'b');

  EXPECT_TRUE(TupleMatches(matchers, values1));
  EXPECT_FALSE(TupleMatches(matchers, values2));
  EXPECT_FALSE(TupleMatches(matchers, values3));
  EXPECT_FALSE(TupleMatches(matchers, values4));
}

TEST(TupleMatchesTest, WorksForSize5) {
  tuple<Matcher<int>, Matcher<char>, Matcher<bool>, Matcher<long>,  // NOLINT
        Matcher<std::string> >
      matchers(Eq(1), Eq('a'), Eq(true), Eq(2L), Eq("hi"));
  tuple<int, char, bool, long, std::string>  // NOLINT
      values1(1, 'a', true, 2L, "hi"), values2(1, 'a', true, 2L, "hello"),
      values3(2, 'a', true, 2L, "hi");

  EXPECT_TRUE(TupleMatches(matchers, values1));
  EXPECT_FALSE(TupleMatches(matchers, values2));
  EXPECT_FALSE(TupleMatches(matchers, values3));
}

// Tests that Assert(true, ...) succeeds.
TEST(AssertTest, SucceedsOnTrue) {
  Assert(true, __FILE__, __LINE__, "This should succeed.");
  Assert(true, __FILE__, __LINE__);  // This should succeed too.
}

// Tests that Assert(false, ...) generates a fatal failure.
TEST(AssertTest, FailsFatallyOnFalse) {
  EXPECT_DEATH_IF_SUPPORTED({
    Assert(false, __FILE__, __LINE__, "This should fail.");
  }, "");

  EXPECT_DEATH_IF_SUPPORTED({
    Assert(false, __FILE__, __LINE__);
  }, "");
}

// Tests that Expect(true, ...) succeeds.
TEST(ExpectTest, SucceedsOnTrue) {
  Expect(true, __FILE__, __LINE__, "This should succeed.");
  Expect(true, __FILE__, __LINE__);  // This should succeed too.
}

// Tests that Expect(false, ...) generates a non-fatal failure.
TEST(ExpectTest, FailsNonfatallyOnFalse) {
  EXPECT_NONFATAL_FAILURE({  // NOLINT
    Expect(false, __FILE__, __LINE__, "This should fail.");
  }, "This should fail");

  EXPECT_NONFATAL_FAILURE({  // NOLINT
    Expect(false, __FILE__, __LINE__);
  }, "Expectation failed");
}

// Tests LogIsVisible().

class LogIsVisibleTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    original_verbose_ = GMOCK_FLAG(verbose);
  }

  virtual void TearDown() { GMOCK_FLAG(verbose) = original_verbose_; }

  std::string original_verbose_;
};

TEST_F(LogIsVisibleTest, AlwaysReturnsTrueIfVerbosityIsInfo) {
  GMOCK_FLAG(verbose) = kInfoVerbosity;
  EXPECT_TRUE(LogIsVisible(kInfo));
  EXPECT_TRUE(LogIsVisible(kWarning));
}

TEST_F(LogIsVisibleTest, AlwaysReturnsFalseIfVerbosityIsError) {
  GMOCK_FLAG(verbose) = kErrorVerbosity;
  EXPECT_FALSE(LogIsVisible(kInfo));
  EXPECT_FALSE(LogIsVisible(kWarning));
}

TEST_F(LogIsVisibleTest, WorksWhenVerbosityIsWarning) {
  GMOCK_FLAG(verbose) = kWarningVerbosity;
  EXPECT_FALSE(LogIsVisible(kInfo));
  EXPECT_TRUE(LogIsVisible(kWarning));
}

#if GTEST_HAS_STREAM_REDIRECTION

// Tests the Log() function.

// Verifies that Log() behaves correctly for the given verbosity level
// and log severity.
void TestLogWithSeverity(const std::string& verbosity, LogSeverity severity,
                         bool should_print) {
  const std::string old_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = verbosity;
  CaptureStdout();
  Log(severity, "Test log.\n", 0);
  if (should_print) {
    EXPECT_THAT(GetCapturedStdout().c_str(),
                ContainsRegex(
                    severity == kWarning ?
                    "^\nGMOCK WARNING:\nTest log\\.\nStack trace:\n" :
                    "^\nTest log\\.\nStack trace:\n"));
  } else {
    EXPECT_STREQ("", GetCapturedStdout().c_str());
  }
  GMOCK_FLAG(verbose) = old_flag;
}

// Tests that when the stack_frames_to_skip parameter is negative,
// Log() doesn't include the stack trace in the output.
TEST(LogTest, NoStackTraceWhenStackFramesToSkipIsNegative) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = kInfoVerbosity;
  CaptureStdout();
  Log(kInfo, "Test log.\n", -1);
  EXPECT_STREQ("\nTest log.\n", GetCapturedStdout().c_str());
  GMOCK_FLAG(verbose) = saved_flag;
}

struct MockStackTraceGetter : testing::internal::OsStackTraceGetterInterface {
  virtual std::string CurrentStackTrace(int max_depth, int skip_count) {
    return (testing::Message() << max_depth << "::" << skip_count << "\n")
        .GetString();
  }
  virtual void UponLeavingGTest() {}
};

// Tests that in opt mode, a positive stack_frames_to_skip argument is
// treated as 0.
TEST(LogTest, NoSkippingStackFrameInOptMode) {
  MockStackTraceGetter* mock_os_stack_trace_getter = new MockStackTraceGetter;
  GetUnitTestImpl()->set_os_stack_trace_getter(mock_os_stack_trace_getter);

  CaptureStdout();
  Log(kWarning, "Test log.\n", 100);
  const std::string log = GetCapturedStdout();

  std::string expected_trace =
      (testing::Message() << GTEST_FLAG(stack_trace_depth) << "::").GetString();
  std::string expected_message =
      "\nGMOCK WARNING:\n"
      "Test log.\n"
      "Stack trace:\n" +
      expected_trace;
  EXPECT_THAT(log, HasSubstr(expected_message));
  int skip_count = atoi(log.substr(expected_message.size()).c_str());

# if defined(NDEBUG)
  // In opt mode, no stack frame should be skipped.
  const int expected_skip_count = 0;
# else
  // In dbg mode, the stack frames should be skipped.
  const int expected_skip_count = 100;
# endif

  // Note that each inner implementation layer will +1 the number to remove
  // itself from the trace. This means that the value is a little higher than
  // expected, but close enough.
  EXPECT_THAT(skip_count,
              AllOf(Ge(expected_skip_count), Le(expected_skip_count + 10)));

  // Restores the default OS stack trace getter.
  GetUnitTestImpl()->set_os_stack_trace_getter(NULL);
}

// Tests that all logs are printed when the value of the
// --gmock_verbose flag is "info".
TEST(LogTest, AllLogsArePrintedWhenVerbosityIsInfo) {
  TestLogWithSeverity(kInfoVerbosity, kInfo, true);
  TestLogWithSeverity(kInfoVerbosity, kWarning, true);
}

// Tests that only warnings are printed when the value of the
// --gmock_verbose flag is "warning".
TEST(LogTest, OnlyWarningsArePrintedWhenVerbosityIsWarning) {
  TestLogWithSeverity(kWarningVerbosity, kInfo, false);
  TestLogWithSeverity(kWarningVerbosity, kWarning, true);
}

// Tests that no logs are printed when the value of the
// --gmock_verbose flag is "error".
TEST(LogTest, NoLogsArePrintedWhenVerbosityIsError) {
  TestLogWithSeverity(kErrorVerbosity, kInfo, false);
  TestLogWithSeverity(kErrorVerbosity, kWarning, false);
}

// Tests that only warnings are printed when the value of the
// --gmock_verbose flag is invalid.
TEST(LogTest, OnlyWarningsArePrintedWhenVerbosityIsInvalid) {
  TestLogWithSeverity("invalid", kInfo, false);
  TestLogWithSeverity("invalid", kWarning, true);
}

#endif  // GTEST_HAS_STREAM_REDIRECTION

TEST(TypeTraitsTest, true_type) {
  EXPECT_TRUE(true_type::value);
}

TEST(TypeTraitsTest, false_type) {
  EXPECT_FALSE(false_type::value);
}

TEST(TypeTraitsTest, is_reference) {
  EXPECT_FALSE(is_reference<int>::value);
  EXPECT_FALSE(is_reference<char*>::value);
  EXPECT_TRUE(is_reference<const int&>::value);
}

TEST(TypeTraitsTest, is_pointer) {
  EXPECT_FALSE(is_pointer<int>::value);
  EXPECT_FALSE(is_pointer<char&>::value);
  EXPECT_TRUE(is_pointer<const int*>::value);
}

TEST(TypeTraitsTest, type_equals) {
  EXPECT_FALSE((type_equals<int, const int>::value));
  EXPECT_FALSE((type_equals<int, int&>::value));
  EXPECT_FALSE((type_equals<int, double>::value));
  EXPECT_TRUE((type_equals<char, char>::value));
}

TEST(TypeTraitsTest, remove_reference) {
  EXPECT_TRUE((type_equals<char, remove_reference<char&>::type>::value));
  EXPECT_TRUE((type_equals<const int,
               remove_reference<const int&>::type>::value));
  EXPECT_TRUE((type_equals<int, remove_reference<int>::type>::value));
  EXPECT_TRUE((type_equals<double*, remove_reference<double*>::type>::value));
}

#if GTEST_HAS_STREAM_REDIRECTION

// Verifies that Log() behaves correctly for the given verbosity level
// and log severity.
std::string GrabOutput(void(*logger)(), const char* verbosity) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = verbosity;
  CaptureStdout();
  logger();
  GMOCK_FLAG(verbose) = saved_flag;
  return GetCapturedStdout();
}

class DummyMock {
 public:
  MOCK_METHOD0(TestMethod, void());
  MOCK_METHOD1(TestMethodArg, void(int dummy));
};

void ExpectCallLogger() {
  DummyMock mock;
  EXPECT_CALL(mock, TestMethod());
  mock.TestMethod();
};

// Verifies that EXPECT_CALL logs if the --gmock_verbose flag is set to "info".
TEST(ExpectCallTest, LogsWhenVerbosityIsInfo) {
  EXPECT_THAT(std::string(GrabOutput(ExpectCallLogger, kInfoVerbosity)),
              HasSubstr("EXPECT_CALL(mock, TestMethod())"));
}

// Verifies that EXPECT_CALL doesn't log
// if the --gmock_verbose flag is set to "warning".
TEST(ExpectCallTest, DoesNotLogWhenVerbosityIsWarning) {
  EXPECT_STREQ("", GrabOutput(ExpectCallLogger, kWarningVerbosity).c_str());
}

// Verifies that EXPECT_CALL doesn't log
// if the --gmock_verbose flag is set to "error".
TEST(ExpectCallTest,  DoesNotLogWhenVerbosityIsError) {
  EXPECT_STREQ("", GrabOutput(ExpectCallLogger, kErrorVerbosity).c_str());
}

void OnCallLogger() {
  DummyMock mock;
  ON_CALL(mock, TestMethod());
};

// Verifies that ON_CALL logs if the --gmock_verbose flag is set to "info".
TEST(OnCallTest, LogsWhenVerbosityIsInfo) {
  EXPECT_THAT(std::string(GrabOutput(OnCallLogger, kInfoVerbosity)),
              HasSubstr("ON_CALL(mock, TestMethod())"));
}

// Verifies that ON_CALL doesn't log
// if the --gmock_verbose flag is set to "warning".
TEST(OnCallTest, DoesNotLogWhenVerbosityIsWarning) {
  EXPECT_STREQ("", GrabOutput(OnCallLogger, kWarningVerbosity).c_str());
}

// Verifies that ON_CALL doesn't log if
// the --gmock_verbose flag is set to "error".
TEST(OnCallTest, DoesNotLogWhenVerbosityIsError) {
  EXPECT_STREQ("", GrabOutput(OnCallLogger, kErrorVerbosity).c_str());
}

void OnCallAnyArgumentLogger() {
  DummyMock mock;
  ON_CALL(mock, TestMethodArg(_));
}

// Verifies that ON_CALL prints provided _ argument.
TEST(OnCallTest, LogsAnythingArgument) {
  EXPECT_THAT(std::string(GrabOutput(OnCallAnyArgumentLogger, kInfoVerbosity)),
              HasSubstr("ON_CALL(mock, TestMethodArg(_)"));
}

#endif  // GTEST_HAS_STREAM_REDIRECTION

// Tests StlContainerView.

TEST(StlContainerViewTest, WorksForStlContainer) {
  StaticAssertTypeEq<std::vector<int>,
      StlContainerView<std::vector<int> >::type>();
  StaticAssertTypeEq<const std::vector<double>&,
      StlContainerView<std::vector<double> >::const_reference>();

  typedef std::vector<char> Chars;
  Chars v1;
  const Chars& v2(StlContainerView<Chars>::ConstReference(v1));
  EXPECT_EQ(&v1, &v2);

  v1.push_back('a');
  Chars v3 = StlContainerView<Chars>::Copy(v1);
  EXPECT_THAT(v3, Eq(v3));
}

TEST(StlContainerViewTest, WorksForStaticNativeArray) {
  StaticAssertTypeEq<NativeArray<int>,
      StlContainerView<int[3]>::type>();
  StaticAssertTypeEq<NativeArray<double>,
      StlContainerView<const double[4]>::type>();
  StaticAssertTypeEq<NativeArray<char[3]>,
      StlContainerView<const char[2][3]>::type>();

  StaticAssertTypeEq<const NativeArray<int>,
      StlContainerView<int[2]>::const_reference>();

  int a1[3] = { 0, 1, 2 };
  NativeArray<int> a2 = StlContainerView<int[3]>::ConstReference(a1);
  EXPECT_EQ(3U, a2.size());
  EXPECT_EQ(a1, a2.begin());

  const NativeArray<int> a3 = StlContainerView<int[3]>::Copy(a1);
  ASSERT_EQ(3U, a3.size());
  EXPECT_EQ(0, a3.begin()[0]);
  EXPECT_EQ(1, a3.begin()[1]);
  EXPECT_EQ(2, a3.begin()[2]);

  // Makes sure a1 and a3 aren't aliases.
  a1[0] = 3;
  EXPECT_EQ(0, a3.begin()[0]);
}

TEST(StlContainerViewTest, WorksForDynamicNativeArray) {
  StaticAssertTypeEq<NativeArray<int>,
      StlContainerView<tuple<const int*, size_t> >::type>();
  StaticAssertTypeEq<NativeArray<double>,
      StlContainerView<tuple<linked_ptr<double>, int> >::type>();

  StaticAssertTypeEq<const NativeArray<int>,
      StlContainerView<tuple<const int*, int> >::const_reference>();

  int a1[3] = { 0, 1, 2 };
  const int* const p1 = a1;
  NativeArray<int> a2 = StlContainerView<tuple<const int*, int> >::
      ConstReference(make_tuple(p1, 3));
  EXPECT_EQ(3U, a2.size());
  EXPECT_EQ(a1, a2.begin());

  const NativeArray<int> a3 = StlContainerView<tuple<int*, size_t> >::
      Copy(make_tuple(static_cast<int*>(a1), 3));
  ASSERT_EQ(3U, a3.size());
  EXPECT_EQ(0, a3.begin()[0]);
  EXPECT_EQ(1, a3.begin()[1]);
  EXPECT_EQ(2, a3.begin()[2]);

  // Makes sure a1 and a3 aren't aliases.
  a1[0] = 3;
  EXPECT_EQ(0, a3.begin()[0]);
}

}  // namespace
}  // namespace internal
}  // namespace testing