summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2022-01-20 11:30:21 -0800
committerGitHub <noreply@github.com>2022-01-20 11:30:21 -0800
commita1b38c796629f8042d1e1accf4708a6a86bfd408 (patch)
treeafdb4093b6312009777d768a25a54f7a9698f3ea
parentc918679ec50d4a404bd06244e79691651bdee95b (diff)
downloadbinaryen-a1b38c796629f8042d1e1accf4708a6a86bfd408.tar.gz
binaryen-a1b38c796629f8042d1e1accf4708a6a86bfd408.tar.bz2
binaryen-a1b38c796629f8042d1e1accf4708a6a86bfd408.zip
Introduce gtest (#4466)
Add gtest as a git submodule in third_party and integrate it into the build the same way WABT does. Adds a new executable, `binaryen-unittests`, to execute `gtest_main`. As a nontrivial example test, port one of the `TypeBuilder` tests from example/ to gtest/. Using gtest has a number of advantages over the current example tests: - Tests are compiled and linked at build time rather than runtime, surfacing errors earlier and speeding up test execution. - Tests are all built into a single binary, reducing overall link time and further reducing test overhead. - Tests are built from the same CMake project as the rest of Binaryen, so compiler settings (e.g. sanitizers) are applied uniformly rather than having to be separately set via the COMPILER_FLAGS environment variable. - Using the industry-standard gtest rather than our own script reduces our maintenance burden. Using gtest will lower the barrier to writing C++ tests and will hopefully lead to us having more proper unit tests.
-rw-r--r--.flake82
-rw-r--r--.github/workflows/ci.yml18
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt13
-rwxr-xr-xcheck.py20
-rw-r--r--src/tools/CMakeLists.txt10
-rw-r--r--test/example/type-builder.cpp65
-rw-r--r--test/example/type-builder.txt44
-rw-r--r--test/gtest/CMakeLists.txt8
-rw-r--r--test/gtest/type-builder.cpp64
-rw-r--r--third_party/CMakeLists.txt13
m---------third_party/googletest0
12 files changed, 138 insertions, 122 deletions
diff --git a/.flake8 b/.flake8
index d1abdcdce..83735a2f0 100644
--- a/.flake8
+++ b/.flake8
@@ -3,4 +3,4 @@ ignore =
E501, # line too long
E241, # space after comma (ignored for list in gen-s-parser.py)
W504 # line break after binary operator
-exclude = ./test/emscripten,./test/spec,./test/wasm-install,./test/lit
+exclude = third_party,./test/emscripten,./test/spec,./test/wasm-install,./test/lit
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d9d7d8c53..48f771367 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,6 +20,8 @@ jobs:
with:
python-version: '3.x'
- uses: actions/checkout@v1
+ with:
+ submodules: true
- name: install tools
run: |
sudo pip3 install -r requirements-dev.txt
@@ -45,6 +47,8 @@ jobs:
with:
python-version: '3.x'
- uses: actions/checkout@v1
+ with:
+ submodules: true
- name: install Python dev dependencies
run: pip3 install -r requirements-dev.txt
@@ -111,6 +115,8 @@ jobs:
with:
python-version: '3.x'
- uses: actions/checkout@v1
+ with:
+ submodules: true
- name: install ninja
run: sudo apt-get install ninja-build
- name: install Python dev dependencies
@@ -138,6 +144,8 @@ jobs:
with:
python-version: '3.x'
- uses: actions/checkout@v1
+ with:
+ submodules: true
- name: install ninja
run: sudo apt-get install ninja-build
- name: install Python dev dependencies
@@ -162,6 +170,8 @@ jobs:
with:
python-version: '3.x'
- uses: actions/checkout@v1
+ with:
+ submodules: true
- name: start docker
run: |
docker run -w /src -dit --name alpine -v $PWD:/src node:lts-alpine
@@ -200,6 +210,8 @@ jobs:
with:
python-version: '3.x'
- uses: actions/checkout@v1
+ with:
+ submodules: true
- name: install ninja
run: sudo apt-get install ninja-build
- name: install Python dev dependencies
@@ -225,6 +237,8 @@ jobs:
with:
python-version: '3.x'
- uses: actions/checkout@v1
+ with:
+ submodules: true
- name: install ninja
run: sudo apt-get install ninja-build
- name: install Python dev dependencies
@@ -247,6 +261,8 @@ jobs:
with:
python-version: '3.x'
- uses: actions/checkout@v1
+ with:
+ submodules: true
- name: install ninja
run: sudo apt-get install ninja-build
- name: emsdk install
@@ -272,6 +288,8 @@ jobs:
with:
python-version: '3.x'
- uses: actions/checkout@v1
+ with:
+ submodules: true
- name: cmake
run: |
mkdir -p out
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..5a4e85a51
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "third_party/googletest"]
+ path = third_party/googletest
+ url = https://github.com/google/googletest.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ead819559..bc51d7515 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -105,6 +105,16 @@ function(binaryen_setup_rpath name)
${_install_name_dir})
endfunction()
+function(binaryen_add_executable name sources)
+ add_executable(${name} ${sources})
+ target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
+ target_link_libraries(${name} binaryen)
+ set_property(TARGET ${name} PROPERTY CXX_STANDARD ${CXX_STANDARD})
+ set_property(TARGET ${name} PROPERTY CXX_STANDARD_REQUIRED ON)
+ binaryen_setup_rpath(${name})
+ install(TARGETS ${name} DESTINATION ${CMAKE_INSTALL_BINDIR})
+endfunction()
+
# Options
option(BUILD_STATIC_LIB "Build as a static library" OFF)
@@ -306,6 +316,9 @@ add_subdirectory(third_party)
# Configure lit tests
add_subdirectory(test/lit)
+# Configure GTest unit tests
+add_subdirectory(test/gtest)
+
# Object files
set(binaryen_objs
$<TARGET_OBJECTS:passes>
diff --git a/check.py b/check.py
index 6b4d1833a..c3233b8f7 100755
--- a/check.py
+++ b/check.py
@@ -42,9 +42,12 @@ def get_changelog_version():
def run_version_tests():
print('[ checking --version ... ]\n')
- not_executable_suffix = ['.DS_Store', '.txt', '.js', '.ilk', '.pdb', '.dll', '.wasm', '.manifest', 'binaryen-lit']
+ not_executable_suffix = ['.DS_Store', '.txt', '.js', '.ilk', '.pdb', '.dll', '.wasm', '.manifest']
+ not_executable_prefix = ['binaryen-lit', 'binaryen-unittests']
bin_files = [os.path.join(shared.options.binaryen_bin, f) for f in os.listdir(shared.options.binaryen_bin)]
- executables = [f for f in bin_files if os.path.isfile(f) and not any(f.endswith(s) for s in not_executable_suffix)]
+ executables = [f for f in bin_files if os.path.isfile(f) and
+ not any(f.endswith(s) for s in not_executable_suffix) and
+ not any(os.path.basename(f).startswith(s) for s in not_executable_prefix)]
executables = sorted(executables)
assert len(executables)
@@ -337,6 +340,18 @@ def run_lit():
shared.with_pass_debug(run)
+def run_gtest():
+ def run():
+ gtest = os.path.join(shared.options.binaryen_bin, 'binaryen-unittests')
+ result = subprocess.run(gtest)
+ if result.returncode != 0:
+ shared.num_failures += 1
+ if shared.options.abort_on_first_failure and shared.num_failures:
+ raise Exception("gtest test failed")
+
+ shared.with_pass_debug(run)
+
+
TEST_SUITES = OrderedDict([
('version', run_version_tests),
('wasm-opt', wasm_opt.test_wasm_opt),
@@ -355,6 +370,7 @@ TEST_SUITES = OrderedDict([
('binaryenjs', binaryenjs.test_binaryen_js),
('binaryenjs_wasm', binaryenjs.test_binaryen_wasm),
('lit', run_lit),
+ ('gtest', run_gtest),
])
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index ac8927d54..7953eeeca 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -1,13 +1,3 @@
-function(binaryen_add_executable name sources)
- add_executable(${name} ${sources})
- target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
- target_link_libraries(${name} binaryen)
- set_property(TARGET ${name} PROPERTY CXX_STANDARD ${CXX_STANDARD})
- set_property(TARGET ${name} PROPERTY CXX_STANDARD_REQUIRED ON)
- binaryen_setup_rpath(${name})
- install(TARGETS ${name} DESTINATION ${CMAKE_INSTALL_BINDIR})
-endfunction()
-
include_directories(fuzzing)
FILE(GLOB fuzzing_HEADERS fuzzing/*h)
set(fuzzing_SOURCES
diff --git a/test/example/type-builder.cpp b/test/example/type-builder.cpp
index d86643cf0..0fba565f1 100644
--- a/test/example/type-builder.cpp
+++ b/test/example/type-builder.cpp
@@ -5,70 +5,6 @@
using namespace wasm;
-// Construct Signature, Struct, and Array heap types using undefined types.
-void test_builder() {
- std::cout << ";; Test TypeBuilder\n";
-
- // (type $sig (func (param (ref $struct)) (result (ref $array) i32)))
- // (type $struct (struct (field (ref null $array) (mut rtt 0 $array))))
- // (type $array (array (mut externref)))
-
- TypeBuilder builder;
- assert(builder.size() == 0);
- builder.grow(3);
- assert(builder.size() == 3);
-
- Type refSig = builder.getTempRefType(builder[0], NonNullable);
- Type refStruct = builder.getTempRefType(builder[1], NonNullable);
- Type refArray = builder.getTempRefType(builder[2], NonNullable);
- Type refNullArray = builder.getTempRefType(builder[2], Nullable);
- Type rttArray = builder.getTempRttType(Rtt(0, builder[2]));
- Type refNullExt(HeapType::ext, Nullable);
-
- Signature sig(refStruct, builder.getTempTupleType({refArray, Type::i32}));
- Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)});
- Array array(Field(refNullExt, Mutable));
-
- std::cout << "Before setting heap types:\n";
- std::cout << "(ref $sig) => " << refSig << "\n";
- std::cout << "(ref $struct) => " << refStruct << "\n";
- std::cout << "(ref $array) => " << refArray << "\n";
- std::cout << "(ref null $array) => " << refNullArray << "\n";
- std::cout << "(rtt 0 $array) => " << rttArray << "\n\n";
-
- builder[0] = sig;
- builder[1] = struct_;
- builder[2] = array;
-
- std::cout << "After setting heap types:\n";
- std::cout << "(ref $sig) => " << refSig << "\n";
- std::cout << "(ref $struct) => " << refStruct << "\n";
- std::cout << "(ref $array) => " << refArray << "\n";
- std::cout << "(ref null $array) => " << refNullArray << "\n";
- std::cout << "(rtt 0 $array) => " << rttArray << "\n\n";
-
- std::vector<HeapType> built = builder.build();
-
- Type newRefSig = Type(built[0], NonNullable);
- Type newRefStruct = Type(built[1], NonNullable);
- Type newRefArray = Type(built[2], NonNullable);
- Type newRefNullArray = Type(built[2], Nullable);
- Type newRttArray = Type(Rtt(0, built[2]));
-
- assert(refSig != newRefSig);
- assert(refStruct != newRefStruct);
- assert(refArray != newRefArray);
- assert(refNullArray != newRefNullArray);
- assert(rttArray != newRttArray);
-
- std::cout << "After building types:\n";
- std::cout << "(ref $sig) => " << newRefSig << "\n";
- std::cout << "(ref $struct) => " << newRefStruct << "\n";
- std::cout << "(ref $array) => " << newRefArray << "\n";
- std::cout << "(ref null $array) => " << newRefNullArray << "\n";
- std::cout << "(rtt 0 $array) => " << newRttArray << "\n\n";
-}
-
// Check that the builder works when there are duplicate definitions
void test_canonicalization() {
std::cout << ";; Test canonicalization\n";
@@ -496,7 +432,6 @@ int main() {
// Run the tests twice to ensure things still work when the global stores are
// already populated.
for (size_t i = 0; i < 2; ++i) {
- test_builder();
test_canonicalization();
test_basic();
test_recursive();
diff --git a/test/example/type-builder.txt b/test/example/type-builder.txt
index a219816e6..df67b599d 100644
--- a/test/example/type-builder.txt
+++ b/test/example/type-builder.txt
@@ -1,25 +1,3 @@
-;; Test TypeBuilder
-Before setting heap types:
-(ref $sig) => [T](ref [T](func))
-(ref $struct) => [T](ref [T](func))
-(ref $array) => [T](ref [T](func))
-(ref null $array) => [T](ref null [T](func))
-(rtt 0 $array) => [T](rtt 0 [T](func))
-
-After setting heap types:
-(ref $sig) => [T](ref [T](func (param [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))) (result [T](ref [T](array (mut externref))) i32)))
-(ref $struct) => [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))
-(ref $array) => [T](ref [T](array (mut externref)))
-(ref null $array) => [T](ref null [T](array (mut externref)))
-(rtt 0 $array) => [T](rtt 0 [T](array (mut externref)))
-
-After building types:
-(ref $sig) => (ref (func (param (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))) (result (ref (array (mut externref))) i32)))
-(ref $struct) => (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))
-(ref $array) => (ref (array (mut externref)))
-(ref null $array) => (ref null (array (mut externref)))
-(rtt 0 $array) => (rtt 0 (array (mut externref)))
-
;; Test canonicalization
;; Test basic
;; Test recursive types
@@ -48,28 +26,6 @@ After building types:
(func (param anyref) (result (ref null ...1)))
;; Test LUBs
-;; Test TypeBuilder
-Before setting heap types:
-(ref $sig) => [T](ref [T](func))
-(ref $struct) => [T](ref [T](func))
-(ref $array) => [T](ref [T](func))
-(ref null $array) => [T](ref null [T](func))
-(rtt 0 $array) => [T](rtt 0 [T](func))
-
-After setting heap types:
-(ref $sig) => [T](ref [T](func (param [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))) (result [T](ref [T](array (mut externref))) i32)))
-(ref $struct) => [T](ref [T](struct (field [T](ref null [T](array (mut externref))) (mut [T](rtt 0 [T](array (mut externref)))))))
-(ref $array) => [T](ref [T](array (mut externref)))
-(ref null $array) => [T](ref null [T](array (mut externref)))
-(rtt 0 $array) => [T](rtt 0 [T](array (mut externref)))
-
-After building types:
-(ref $sig) => (ref (func (param (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))) (result (ref (array (mut externref))) i32)))
-(ref $struct) => (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))
-(ref $array) => (ref (array (mut externref)))
-(ref null $array) => (ref null (array (mut externref)))
-(rtt 0 $array) => (rtt 0 (array (mut externref)))
-
;; Test canonicalization
;; Test basic
;; Test recursive types
diff --git a/test/gtest/CMakeLists.txt b/test/gtest/CMakeLists.txt
new file mode 100644
index 000000000..c58827a21
--- /dev/null
+++ b/test/gtest/CMakeLists.txt
@@ -0,0 +1,8 @@
+include_directories(../../third_party/googletest/googletest/include)
+
+set(unittest_SOURCES
+ type-builder.cpp
+)
+
+binaryen_add_executable(binaryen-unittests "${unittest_SOURCES}")
+target_link_libraries(binaryen-unittests gtest gtest_main)
diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp
new file mode 100644
index 000000000..37e47c148
--- /dev/null
+++ b/test/gtest/type-builder.cpp
@@ -0,0 +1,64 @@
+#include <gtest/gtest.h>
+#include <wasm-type.h>
+
+using namespace wasm;
+
+TEST(TypeBuilder, Growth) {
+ TypeBuilder builder;
+ EXPECT_EQ(builder.size(), size_t{0});
+ builder.grow(3);
+ EXPECT_EQ(builder.size(), size_t{3});
+}
+
+TEST(TypeBuilder, Basics) {
+ // (type $sig (func (param (ref $struct)) (result (ref $array) i32)))
+ // (type $struct (struct (field (ref null $array) (mut rtt 0 $array))))
+ // (type $array (array (mut externref)))
+
+ TypeBuilder builder(3);
+ ASSERT_EQ(builder.size(), size_t{3});
+
+ Type refSig = builder.getTempRefType(builder[0], NonNullable);
+ Type refStruct = builder.getTempRefType(builder[1], NonNullable);
+ Type refArray = builder.getTempRefType(builder[2], NonNullable);
+ Type refNullArray = builder.getTempRefType(builder[2], Nullable);
+ Type rttArray = builder.getTempRttType(Rtt(0, builder[2]));
+ Type refNullExt(HeapType::ext, Nullable);
+
+ Signature sig(refStruct, builder.getTempTupleType({refArray, Type::i32}));
+ Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)});
+ Array array(Field(refNullExt, Mutable));
+
+ builder[0] = sig;
+ builder[1] = struct_;
+ builder[2] = array;
+
+ std::vector<HeapType> built = builder.build();
+ ASSERT_EQ(built.size(), size_t{3});
+
+ // The built types should have the correct kinds.
+ ASSERT_TRUE(built[0].isSignature());
+ ASSERT_TRUE(built[1].isStruct());
+ ASSERT_TRUE(built[2].isArray());
+
+ // The built types should have the correct structure.
+ Type newRefSig = Type(built[0], NonNullable);
+ Type newRefStruct = Type(built[1], NonNullable);
+ Type newRefArray = Type(built[2], NonNullable);
+ Type newRefNullArray = Type(built[2], Nullable);
+ Type newRttArray = Type(Rtt(0, built[2]));
+
+ EXPECT_EQ(built[0].getSignature(),
+ Signature(newRefStruct, {newRefArray, Type::i32}));
+ EXPECT_EQ(
+ built[1].getStruct(),
+ Struct({Field(newRefNullArray, Immutable), Field(newRttArray, Mutable)}));
+ EXPECT_EQ(built[2].getArray(), Array(Field(refNullExt, Mutable)));
+
+ // The built types should be different from the temporary types.
+ EXPECT_NE(newRefSig, refSig);
+ EXPECT_NE(newRefStruct, refStruct);
+ EXPECT_NE(newRefArray, refArray);
+ EXPECT_NE(newRefNullArray, refNullArray);
+ EXPECT_NE(newRttArray, rttArray);
+}
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index 40d5b09bb..49a710615 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -1,3 +1,16 @@
if(BUILD_LLVM_DWARF)
add_subdirectory(llvm-project)
endif()
+
+include_directories(
+ googletest/googletest
+ googletest/googletest/include
+)
+
+add_library(gtest STATIC
+ googletest/googletest/src/gtest-all.cc
+)
+
+add_library(gtest_main STATIC
+ googletest/googletest/src/gtest_main.cc
+)
diff --git a/third_party/googletest b/third_party/googletest
new file mode 160000
+Subproject e2239ee6043f73722e7aa812a459f54a2855292