Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added GMock to UT project compilation #1902

Merged
merged 1 commit into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 48 additions & 21 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# Points to the root of Google Test, relative to where this file is.
# Remember to tweak this if you move this file.
GTEST_DIR = ../lib/googletest/googletest
GMOCK_DIR = ../lib/googletest/googlemock

# Where to find user code.
USER_DIR = ../src
Expand All @@ -24,11 +25,14 @@ INCLUDES = -I$(USER_DIR) -I.
# Flags passed to the preprocessor.
# Set Google Test's header directory as a system directory, such that
# the compiler doesn't generate warnings in Google Test headers.
CPPFLAGS += -isystem $(GTEST_DIR)/include -DUNIT_TEST -D_IR_LOCALE_=en-AU
CPPFLAGS += -isystem $(GTEST_DIR)/include -isystem $(GMOCK_DIR)/include -DUNIT_TEST -D_IR_LOCALE_=en-AU

# Flags passed to the C++ compiler.
CXXFLAGS += -g -Wall -Wextra -Werror -pthread -std=gnu++11

# Google Test libraries
GTEST_LIBS = gtest.a gtest_main.a gmock.a gmock_main.a

# All tests produced by this Makefile. generated from all *_test.cpp files
TESTS = $(patsubst %.cpp,%,$(wildcard *_test.cpp))

Expand All @@ -37,12 +41,19 @@ TESTS = $(patsubst %.cpp,%,$(wildcard *_test.cpp))
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h

# All Google Mock headers. Note that all Google Test headers are
# included here too, as they are #included by Google Mock headers.
# Usually you shouldn't change this definition.
GMOCK_HEADERS = $(GMOCK_DIR)/include/gmock/*.h \
$(GMOCK_DIR)/include/gmock/internal/*.h \
$(GTEST_HEADERS)

# House-keeping build targets.

all : $(TESTS)
all : $(GTEST_LIBS) $(TESTS)

clean :
rm -f $(TESTS) gtest.a gtest_main.a *.o
rm -f $(GTEST_LIBS) $(TESTS) *.o

# Build and run all the tests.
run : all
Expand All @@ -67,11 +78,12 @@ install-googletest :
rm -rf ../lib/googletest
git clone -b v1.8.x https://github.com/google/googletest.git ../lib/googletest

# Builds gtest.a and gtest_main.a.
# Builds gtest.a, gtest_main.a, gmock.a, gmock_main.a.

# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
GMOCK_SRCS_ = $(GMOCK_DIR)/src/*.cc $(GMOCK_HEADERS)

# All the IR protocol object files.
PROTOCOL_OBJS = $(patsubst %.cpp,%.o,$(wildcard $(USER_DIR)/ir_*.cpp))
Expand All @@ -82,7 +94,7 @@ PROTOCOLS_H = $(wildcard $(USER_DIR)/ir_*.h)

# Common object files
COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o IRac.o ir_GlobalCache.o \
IRtext.o $(PROTOCOLS) gtest_main.a
IRtext.o $(PROTOCOLS) gtest_main.a gmock_main.a
# Common dependencies
COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \
$(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h \
Expand All @@ -92,24 +104,39 @@ COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \
# Common test dependencies
COMMON_TEST_DEPS = $(COMMON_DEPS) IRrecv_test.h IRsend_test.h

# For simplicity and to avoid depending on Google Test's
# implementation details, the dependencies specified below are
# conservative and not optimized. This is fine as Google Test
# compiles fast and for ordinary users its source rarely changes.
# For simplicity and to avoid depending on implementation details of
# Google Mock and Google Test, the dependencies specified below are
# conservative and not optimized. This is fine as Google Mock and
# Google Test compile fast and for ordinary users their source rarely
# changes.
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest-all.cc

gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest_main.cc

gmock-all.o : $(GMOCK_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is possible to use wildcard rules here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely, though these "GMock" Makefile receipes are fairly generic and written this way.
See https://github.com/ceph/gmock/blob/master/make/Makefile for example

-c $(GMOCK_DIR)/src/gmock-all.cc

gmock_main.o : $(GMOCK_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
-c $(GMOCK_DIR)/src/gmock_main.cc

gtest.a : gtest-all.o
$(AR) $(ARFLAGS) $@ $^

gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) $@ $^

gmock.a : gmock-all.o
$(AR) $(ARFLAGS) $@ $^

gmock_main.a : gmock_main.o
$(AR) $(ARFLAGS) $@ $^

# Keep all intermediate files.
.SECONDARY:

Expand All @@ -123,10 +150,10 @@ IRtext.o : $(USER_DIR)/IRtext.cpp $(USER_DIR)/IRtext.h $(USER_DIR)/IRremoteESP82
IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h $(USER_DIR)/i18n.h $(USER_DIR)/IRtext.cpp $(USER_DIR)/IRtext.h $(USER_DIR)/locale/*.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRutils.cpp

IRutils_test.o : IRutils_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
IRutils_test.o : IRutils_test.cpp $(COMMON_TEST_DEPS) $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRutils_test.cpp

IRutils_test : IRutils_test.o ir_NEC.o ir_Nikai.o ir_Toshiba.o IRtext.o $(COMMON_OBJ) gtest_main.a
IRutils_test : IRutils_test.o ir_NEC.o ir_Nikai.o ir_Toshiba.o IRtext.o $(COMMON_OBJ) $(GTEST_LIBS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@

IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h
Expand All @@ -135,19 +162,19 @@ IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h
IRsend.o : $(USER_DIR)/IRsend.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRremoteESP8266.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRsend.cpp

IRsend_test.o : IRsend_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend_test.h $(GTEST_HEADERS)
IRsend_test.o : IRsend_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend_test.h $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRsend_test.cpp

IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP8266.h $(GTEST_HEADERS)
IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP8266.h $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRrecv.cpp

IRrecv_test.o : IRrecv_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend_test.h $(GTEST_HEADERS)
IRrecv_test.o : IRrecv_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend_test.h $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRrecv_test.cpp

IRac.o : $(USER_DIR)/IRac.cpp $(USER_DIR)/IRac.h $(COMMON_DEPS) $(GTEST_HEADERS)
IRac.o : $(USER_DIR)/IRac.cpp $(USER_DIR)/IRac.h $(COMMON_DEPS) $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRac.cpp

IRac_test.o : IRac_test.cpp $(USER_DIR)/IRac.h $(COMMON_DEPS) $(GTEST_HEADERS)
IRac_test.o : IRac_test.cpp $(USER_DIR)/IRac.h $(COMMON_DEPS) $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c IRac_test.cpp

# new specific targets goes above this line
Expand All @@ -158,11 +185,11 @@ ir_%.o : $(USER_DIR)/ir_%.h $(USER_DIR)/ir_%.cpp $(COMMON_DEPS)
ir_%.o : $(USER_DIR)/ir_%.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_$*.cpp

ir_%_test.o : ir_%_test.cpp $(USER_DIR)/ir_$%.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
ir_%_test.o : ir_%_test.cpp $(USER_DIR)/ir_$%.h $(COMMON_TEST_DEPS) $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_$*_test.cpp

ir_%_test.o : ir_%_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
ir_%_test.o : ir_%_test.cpp $(COMMON_TEST_DEPS) $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_$*_test.cpp

%_test : $(COMMON_OBJ) %_test.o
%_test : $(COMMON_OBJ) %_test.o $(GTEST_LIBS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
11 changes: 7 additions & 4 deletions test/ir_Argo_test.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright 2019 David Conran
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "ir_Argo.h"
#include "IRac.h"
#include "IRrecv.h"
#include "IRrecv_test.h"
#include "IRsend.h"
#include "IRsend_test.h"
#include "gtest/gtest.h"


TEST(TestArgoACClass, toCommon) {
Expand Down Expand Up @@ -50,9 +51,11 @@ TEST(TestArgoACClass, MessageConstructon) {
ac.setNight(true);

// Don't implicitly trust this. It's just a guess.
uint8_t expected[kArgoStateLength] = {
0xAC, 0xF5, 0x00, 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xD6, 0x01};
EXPECT_STATE_EQ(expected, ac.getRaw(), kArgoBits);
auto expected = std::vector<uint8_t>({
0xAC, 0xF5, 0x00, 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xD6, 0x01});
auto actual = ac.getRaw();
EXPECT_THAT(std::vector<uint8_t>(actual, actual + kArgoBits / 8),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly to prove out that CI links w/ GMock correctly.
The benefit in using ::ElementsAreArray over EXPECT_STATE_EQ is marginal in this case (the only material difference is GMock's matcher would spit out all differences, and not stop on first error).


The wrapping into vector is there, mostly to include readability (I don't believe the extra copy for UT hurts anything).
In theory this could be written like so:

  EXPECT_THAT(*reinterpret_cast<uint8_t(*)[kArgoBits / 8]>(ac.getRaw()),
              ::testing::ElementsAreArray(expected));

Anyways, this is mostly a sample to prove integration works. As long as the i-face is a C-Style array, use of fancy matchers doesn't bring much benefit (but they start to shine once STL containers get used)

::testing::ElementsAreArray(expected));
EXPECT_EQ(
"Power: On, Mode: 0 (Cool), Fan: 0 (Auto), Temp: 20C, Room Temp: 21C, "
"Max: On, IFeel: On, Night: On",
Expand Down