Merge lp:~marcustomlinson/v8-cpp/test-coverage into lp:v8-cpp

Proposed by Marcus Tomlinson on 2015-07-07
Status: Merged
Merged at revision: 13
Proposed branch: lp:~marcustomlinson/v8-cpp/test-coverage
Merge into: lp:v8-cpp
Diff against target: 1067 lines (+772/-31)
26 files modified
CMakeLists.txt (+34/-3)
cmake/EnableCoverageReport.cmake (+166/-0)
cmake/FindLcov.cmake (+29/-0)
cmake/Findgcovr.cmake (+31/-0)
cmake/ParseArguments.cmake (+52/-0)
src/class.h (+2/-8)
src/internal/require.h (+11/-12)
src/run.h (+10/-1)
tests/CMakeLists.txt (+2/-0)
tests/errors/CMakeLists.txt (+49/-0)
tests/errors/fail-module.cpp (+1/-0)
tests/errors/module.cpp (+27/-0)
tests/errors/scripts/fail.js (+1/-0)
tests/errors/test.cpp (+183/-0)
tests/errors/test.h (+25/-0)
tests/methods/CMakeLists.txt (+2/-2)
tests/methods/module.cpp (+2/-0)
tests/methods/test.cpp (+9/-0)
tests/methods/test.h (+14/-3)
tests/objects/CMakeLists.txt (+2/-2)
tests/run/CMakeLists.txt (+37/-0)
tests/run/module.cpp (+26/-0)
tests/run/scripts/test.js (+3/-0)
tests/run/scripts/test2.js (+7/-0)
tests/run/test.cpp (+27/-0)
tests/run/test.h (+20/-0)
To merge this branch: bzr merge lp:~marcustomlinson/v8-cpp/test-coverage
Reviewer Review Type Date Requested Status
Marcus Tomlinson Pending
Review via email: mp+264025@code.launchpad.net

Commit message

Added coverage report and more tests to achieve better coverage.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-07-02 11:46:38 +0000
3+++ CMakeLists.txt 2015-07-07 10:47:30 +0000
4@@ -1,6 +1,6 @@
5 cmake_minimum_required(VERSION 2.8)
6
7-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
8+# Configure project environment
9
10 project(v8-cpp CXX)
11
12@@ -13,6 +13,24 @@
13 -fPIC
14 )
15
16+# Configure CMake environment
17+
18+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
19+
20+string(TOLOWER "${CMAKE_BUILD_TYPE}" cmake_build_type_lower) # Build types should always be lowercase but sometimes they are not.
21+
22+if(cmake_build_type_lower MATCHES coverage)
23+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -g")
24+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -g")
25+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --coverage -g")
26+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage -g")
27+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage -g")
28+endif()
29+
30+include(EnableCoverageReport)
31+
32+# Add includes
33+
34 include_directories(
35 ${CMAKE_CURRENT_SOURCE_DIR}/src
36 ${CMAKE_CURRENT_SOURCE_DIR}/deps/v8/include
37@@ -21,9 +39,22 @@
38 ${CMAKE_CURRENT_SOURCE_DIR}/deps/v8/out/native/obj.target/tools/gyp
39 )
40
41+# Add sources
42+
43+enable_testing()
44+
45 add_subdirectory(example)
46 add_subdirectory(src)
47+add_subdirectory(tests)
48 add_subdirectory(v8runner)
49
50-enable_testing()
51-add_subdirectory(tests)
52+# Enable coverage report
53+
54+if (cmake_build_type_lower MATCHES coverage)
55+ ENABLE_COVERAGE_REPORT(TARGETS v8-cpp
56+ FILTER /usr/include
57+ ${CMAKE_CURRENT_SOURCE_DIR}/deps/*
58+ ${CMAKE_CURRENT_SOURCE_DIR}/example/*
59+ ${CMAKE_CURRENT_SOURCE_DIR}/tests/*
60+ ${CMAKE_BINARY_DIR}/*)
61+endif()
62
63=== added file 'cmake/EnableCoverageReport.cmake'
64--- cmake/EnableCoverageReport.cmake 1970-01-01 00:00:00 +0000
65+++ cmake/EnableCoverageReport.cmake 2015-07-07 10:47:30 +0000
66@@ -0,0 +1,166 @@
67+# - Creates a special coverage build type and target on GCC.
68+#
69+# Defines a function ENABLE_COVERAGE_REPORT which generates the coverage target
70+# for selected targets. Optional arguments to this function are used to filter
71+# unwanted results using globbing expressions. Moreover targets with tests for
72+# the source code can be specified to trigger regenerating the report if the
73+# test has changed
74+#
75+# ENABLE_COVERAGE_REPORT(TARGETS target... [FILTER filter...] [TESTS test targets...])
76+#
77+# To generate a coverage report first build the project with
78+# CMAKE_BUILD_TYPE=coverage, then call make test and afterwards make coverage.
79+#
80+# The coverage report is based on gcov. Depending on the availability of lcov
81+# a HTML report will be generated and/or an XML report of gcovr is found.
82+# The generated coverage target executes all found solutions. Special targets
83+# exist to create e.g. only the xml report: coverage-xml.
84+#
85+# Copyright (C) 2010 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
86+#
87+# This program is free software; you can redistribute it
88+# and/or modify it under the terms of the GNU General
89+# Public License as published by the Free Software Foundation;
90+# either version 2, or (at your option)
91+# any later version.
92+#
93+# This program is distributed in the hope that it will be useful,
94+# but WITHOUT ANY WARRANTY; without even the implied warranty of
95+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96+# GNU General Public License for more details.
97+#
98+
99+INCLUDE(ParseArguments)
100+
101+FIND_PACKAGE(Lcov)
102+FIND_PACKAGE(gcovr)
103+
104+FUNCTION(ENABLE_COVERAGE_REPORT)
105+
106+ # argument parsing
107+ PARSE_ARGUMENTS(ARG "FILTER;TARGETS;TESTS" "" ${ARGN})
108+
109+ SET(COVERAGE_RAW_FILE "${CMAKE_BINARY_DIR}/coverage.raw.info")
110+ SET(COVERAGE_FILTERED_FILE "${CMAKE_BINARY_DIR}/coverage.info")
111+ SET(COVERAGE_REPORT_DIR "${CMAKE_BINARY_DIR}/coveragereport")
112+ SET(COVERAGE_XML_FILE "${CMAKE_BINARY_DIR}/coverage.xml")
113+ SET(COVERAGE_XML_COMMAND_FILE "${CMAKE_BINARY_DIR}/coverage-xml.cmake")
114+
115+ # decide if there is any tool to create coverage data
116+ SET(TOOL_FOUND FALSE)
117+ IF(LCOV_FOUND OR GCOVR_FOUND)
118+ SET(TOOL_FOUND TRUE)
119+ ENDIF()
120+ IF(NOT TOOL_FOUND)
121+ MESSAGE(STATUS "Cannot enable coverage targets because neither lcov nor gcovr are found.")
122+ ENDIF()
123+
124+ STRING(TOLOWER "${CMAKE_BUILD_TYPE}" COVERAGE_BUILD_TYPE)
125+ IF(CMAKE_COMPILER_IS_GNUCXX AND TOOL_FOUND AND "${COVERAGE_BUILD_TYPE}" MATCHES "coverage")
126+
127+ MESSAGE(STATUS "Coverage support enabled for targets: ${ARG_TARGETS}")
128+
129+ # create coverage build type
130+ SET(CMAKE_CXX_FLAGS_COVERAGE ${CMAKE_CXX_FLAGS_DEBUG} PARENT_SCOPE)
131+ SET(CMAKE_C_FLAGS_COVERAGE ${CMAKE_C_FLAGS_DEBUG} PARENT_SCOPE)
132+ SET(CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES} coverage PARENT_SCOPE)
133+
134+ # instrument targets
135+ SET_TARGET_PROPERTIES(${ARG_TARGETS} PROPERTIES COMPILE_FLAGS --coverage
136+ LINK_FLAGS --coverage)
137+
138+ # html report
139+ IF (LCOV_FOUND)
140+
141+ MESSAGE(STATUS "Enabling HTML coverage report")
142+
143+ # set up coverage target
144+
145+ ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_RAW_FILE}
146+ COMMAND ${LCOV_EXECUTABLE} -c -d ${CMAKE_BINARY_DIR} -o ${COVERAGE_RAW_FILE}
147+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
148+ COMMENT "Collecting coverage data"
149+ DEPENDS ${ARG_TARGETS} ${ARG_TESTS}
150+ VERBATIM)
151+
152+ # filter unwanted stuff
153+ LIST(LENGTH ARG_FILTER FILTER_LENGTH)
154+ IF(${FILTER_LENGTH} GREATER 0)
155+ SET(FILTER COMMAND ${LCOV_EXECUTABLE})
156+ FOREACH(F ${ARG_FILTER})
157+ SET(FILTER ${FILTER} -r ${COVERAGE_FILTERED_FILE} ${F})
158+ ENDFOREACH()
159+ SET(FILTER ${FILTER} -o ${COVERAGE_FILTERED_FILE})
160+ ELSE()
161+ SET(FILTER "")
162+ ENDIF()
163+
164+ ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_FILTERED_FILE}
165+ COMMAND ${LCOV_EXECUTABLE} -e ${COVERAGE_RAW_FILE} "${CMAKE_SOURCE_DIR}*" -o ${COVERAGE_FILTERED_FILE}
166+ ${FILTER}
167+ DEPENDS ${COVERAGE_RAW_FILE}
168+ COMMENT "Filtering recorded coverage data for project-relevant entries"
169+ VERBATIM)
170+ ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_REPORT_DIR}
171+ COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_REPORT_DIR}
172+ COMMAND ${GENHTML_EXECUTABLE} --legend --show-details -t "${PROJECT_NAME} test coverage" -o ${COVERAGE_REPORT_DIR} ${COVERAGE_FILTERED_FILE}
173+ DEPENDS ${COVERAGE_FILTERED_FILE}
174+ COMMENT "Generating HTML coverage report in ${COVERAGE_REPORT_DIR}"
175+ VERBATIM)
176+
177+ ADD_CUSTOM_TARGET(coverage-html
178+ DEPENDS ${COVERAGE_REPORT_DIR})
179+
180+ ENDIF()
181+
182+ # xml coverage report
183+ IF(GCOVR_FOUND)
184+
185+ MESSAGE(STATUS "Enabling XML coverage report")
186+
187+ # filter unwanted stuff
188+ SET(GCOV_FILTER "")
189+ LIST(LENGTH ARG_FILTER FILTER_LENGTH)
190+ IF(${FILTER_LENGTH} GREATER 0)
191+ FOREACH(F ${ARG_FILTER})
192+ SET(GCOV_FILTER "${GCOV_FILTER} -e \"${F}\"")
193+ ENDFOREACH()
194+ ENDIF()
195+
196+ # gcovr cannot write directly to a file so the execution needs to
197+ # be wrapped in a cmake file that generates the file output
198+ FILE(WRITE ${COVERAGE_XML_COMMAND_FILE}
199+ "SET(ENV{LANG} en)\n")
200+ FILE(APPEND ${COVERAGE_XML_COMMAND_FILE}
201+ "EXECUTE_PROCESS(COMMAND \"${GCOVR_EXECUTABLE}\" -x -r \"${CMAKE_SOURCE_DIR}\" ${GCOV_FILTER} OUTPUT_FILE \"${COVERAGE_XML_FILE}\" WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}\")\n")
202+
203+ ADD_CUSTOM_COMMAND(OUTPUT ${COVERAGE_XML_FILE}
204+ COMMAND ${CMAKE_COMMAND} ARGS -P ${COVERAGE_XML_COMMAND_FILE}
205+ COMMENT "Generating coverage XML report"
206+ VERBATIM)
207+
208+ ADD_CUSTOM_TARGET(coverage-xml
209+ DEPENDS ${COVERAGE_XML_FILE})
210+
211+ ENDIF()
212+
213+ # provide a global coverage target executing both steps if available
214+ SET(GLOBAL_DEPENDS "")
215+ IF(LCOV_FOUND)
216+ LIST(APPEND GLOBAL_DEPENDS ${COVERAGE_REPORT_DIR})
217+ ENDIF()
218+ IF(GCOVR_FOUND)
219+ LIST(APPEND GLOBAL_DEPENDS ${COVERAGE_XML_FILE})
220+ ENDIF()
221+ IF(LCOV_FOUND OR GCOVR_FOUND)
222+ ADD_CUSTOM_TARGET(coverage
223+ DEPENDS ${GLOBAL_DEPENDS})
224+ ENDIF()
225+
226+ ENDIF()
227+
228+ # This gets rid of any stale .gcda files. Run this if a running a binary causes lots of messages about
229+ # about a "merge mismatch for summaries".
230+ ADD_CUSTOM_TARGET(clean-coverage COMMAND find ${CMAKE_BINARY_DIR} -name '*.gcda' | xargs rm -f)
231+
232+ENDFUNCTION()
233
234=== added file 'cmake/FindLcov.cmake'
235--- cmake/FindLcov.cmake 1970-01-01 00:00:00 +0000
236+++ cmake/FindLcov.cmake 2015-07-07 10:47:30 +0000
237@@ -0,0 +1,29 @@
238+# - Find lcov
239+# Will define:
240+#
241+# LCOV_EXECUTABLE - the lcov binary
242+# GENHTML_EXECUTABLE - the genhtml executable
243+#
244+# Copyright (C) 2010 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
245+#
246+# This program is free software; you can redistribute it
247+# and/or modify it under the terms of the GNU General
248+# Public License as published by the Free Software Foundation;
249+# either version 2, or (at your option)
250+# any later version.
251+#
252+# This program is distributed in the hope that it will be useful,
253+# but WITHOUT ANY WARRANTY; without even the implied warranty of
254+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
255+# GNU General Public License for more details.
256+#
257+
258+INCLUDE(FindPackageHandleStandardArgs)
259+
260+FIND_PROGRAM(LCOV_EXECUTABLE lcov)
261+FIND_PROGRAM(GENHTML_EXECUTABLE genhtml)
262+
263+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lcov DEFAULT_MSG LCOV_EXECUTABLE GENHTML_EXECUTABLE)
264+
265+# only visible in advanced view
266+MARK_AS_ADVANCED(LCOV_EXECUTABLE GENHTML_EXECUTABLE)
267
268=== added file 'cmake/Findgcovr.cmake'
269--- cmake/Findgcovr.cmake 1970-01-01 00:00:00 +0000
270+++ cmake/Findgcovr.cmake 2015-07-07 10:47:30 +0000
271@@ -0,0 +1,31 @@
272+# - Find gcovr scrip
273+# Will define:
274+#
275+# GCOVR_EXECUTABLE - the gcovr script
276+#
277+# Uses:
278+#
279+# GCOVR_ROOT - root to search for the script
280+#
281+# Copyright (C) 2011 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
282+#
283+# This program is free software; you can redistribute it
284+# and/or modify it under the terms of the GNU General
285+# Public License as published by the Free Software Foundation;
286+# either version 2, or (at your option)
287+# any later version.
288+#
289+# This program is distributed in the hope that it will be useful,
290+# but WITHOUT ANY WARRANTY; without even the implied warranty of
291+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
292+# GNU General Public License for more details.
293+#
294+
295+INCLUDE(FindPackageHandleStandardArgs)
296+
297+FIND_PROGRAM(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin")
298+
299+FIND_PACKAGE_HANDLE_STANDARD_ARGS(gcovr DEFAULT_MSG GCOVR_EXECUTABLE)
300+
301+# only visible in advanced view
302+MARK_AS_ADVANCED(GCOVR_EXECUTABLE)
303
304=== added file 'cmake/ParseArguments.cmake'
305--- cmake/ParseArguments.cmake 1970-01-01 00:00:00 +0000
306+++ cmake/ParseArguments.cmake 2015-07-07 10:47:30 +0000
307@@ -0,0 +1,52 @@
308+# Parse arguments passed to a function into several lists separated by
309+# upper-case identifiers and options that do not have an associated list e.g.:
310+#
311+# SET(arguments
312+# hello OPTION3 world
313+# LIST3 foo bar
314+# OPTION2
315+# LIST1 fuz baz
316+# )
317+# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments})
318+#
319+# results in 7 distinct variables:
320+# * ARG_DEFAULT_ARGS: hello;world
321+# * ARG_LIST1: fuz;baz
322+# * ARG_LIST2:
323+# * ARG_LIST3: foo;bar
324+# * ARG_OPTION1: FALSE
325+# * ARG_OPTION2: TRUE
326+# * ARG_OPTION3: TRUE
327+#
328+# taken from http://www.cmake.org/Wiki/CMakeMacroParseArguments
329+
330+MACRO(PARSE_ARGUMENTS prefix arg_names option_names)
331+ SET(DEFAULT_ARGS)
332+ FOREACH(arg_name ${arg_names})
333+ SET(${prefix}_${arg_name})
334+ ENDFOREACH(arg_name)
335+ FOREACH(option ${option_names})
336+ SET(${prefix}_${option} FALSE)
337+ ENDFOREACH(option)
338+
339+ SET(current_arg_name DEFAULT_ARGS)
340+ SET(current_arg_list)
341+ FOREACH(arg ${ARGN})
342+ SET(larg_names ${arg_names})
343+ LIST(FIND larg_names "${arg}" is_arg_name)
344+ IF (is_arg_name GREATER -1)
345+ SET(${prefix}_${current_arg_name} ${current_arg_list})
346+ SET(current_arg_name ${arg})
347+ SET(current_arg_list)
348+ ELSE (is_arg_name GREATER -1)
349+ SET(loption_names ${option_names})
350+ LIST(FIND loption_names "${arg}" is_option)
351+ IF (is_option GREATER -1)
352+ SET(${prefix}_${arg} TRUE)
353+ ELSE (is_option GREATER -1)
354+ SET(current_arg_list ${current_arg_list} ${arg})
355+ ENDIF (is_option GREATER -1)
356+ ENDIF (is_arg_name GREATER -1)
357+ ENDFOREACH(arg)
358+ SET(${prefix}_${current_arg_name} ${current_arg_list})
359+ENDMACRO(PARSE_ARGUMENTS)
360
361=== modified file 'src/class.h'
362--- src/class.h 2015-06-11 05:51:30 +0000
363+++ src/class.h 2015-07-07 10:47:30 +0000
364@@ -72,22 +72,16 @@
365
366 // Add class member
367 template <typename P>
368- Class& add_member(char const* name, P property, bool readonly = false)
369+ Class& add_member(char const* name, P property)
370 {
371 v8::HandleScope scope(class_.isolate());
372
373 v8::AccessorGetterCallback getter = &internal::Class<T>::template get_member<P>;
374 v8::AccessorSetterCallback setter = &internal::Class<T>::template set_member<P>;
375- if (readonly)
376- {
377- setter = nullptr;
378- }
379-
380 v8::Handle<v8::Value> data = internal::export_value(class_.isolate(), property);
381- v8::PropertyAttribute prop_attrs = v8::PropertyAttribute(v8::DontDelete | (setter ? 0 : v8::ReadOnly));
382
383 class_.class_template()->PrototypeTemplate()->SetAccessor(to_v8(class_.isolate(), name), getter, setter, data,
384- v8::DEFAULT, prop_attrs);
385+ v8::DEFAULT, v8::DontDelete);
386 return *this;
387 }
388
389
390=== modified file 'src/internal/require.h'
391--- src/internal/require.h 2015-07-02 11:58:21 +0000
392+++ src/internal/require.h 2015-07-07 10:47:30 +0000
393@@ -63,27 +63,28 @@
394 {
395 for (int i = 0; i < args.Length(); ++i)
396 {
397- if (args[i]->IsInt32())
398- {
399- std::cout << v8cpp::from_v8<int>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
400- }
401 if (args[i]->IsUint32())
402 {
403- std::cout << v8cpp::from_v8<unsigned int>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
404+ std::cout << v8cpp::from_v8<unsigned int>(v8::Isolate::GetCurrent(), args[i]);
405+ }
406+ else if (args[i]->IsInt32())
407+ {
408+ std::cout << v8cpp::from_v8<int>(v8::Isolate::GetCurrent(), args[i]);
409 }
410 else if (args[i]->IsNumber())
411 {
412- std::cout << v8cpp::from_v8<float>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
413+ std::cout << v8cpp::from_v8<float>(v8::Isolate::GetCurrent(), args[i]);
414 }
415 else if (args[i]->IsBoolean())
416 {
417- std::cout << v8cpp::from_v8<bool>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
418+ std::cout << v8cpp::from_v8<bool>(v8::Isolate::GetCurrent(), args[i]);
419 }
420 else if (args[i]->IsString())
421 {
422- std::cout << v8cpp::from_v8<std::string>(v8::Isolate::GetCurrent(), args[i]) << std::endl;
423+ std::cout << v8cpp::from_v8<std::string>(v8::Isolate::GetCurrent(), args[i]);
424 }
425 }
426+ std::cout << std::endl;
427 std::cout.flush();
428 }
429 };
430@@ -108,8 +109,7 @@
431 module = dlopen(suffixed_module_path.c_str(), RTLD_LAZY);
432 if (!module)
433 {
434- std::cerr << "dlopen failed: " << dlerror() << std::endl;
435- return exports;
436+ throw std::runtime_error("dlopen failed: " + std::string(dlerror()));
437 }
438 }
439 }
440@@ -123,8 +123,7 @@
441 auto v8cpp_init_func = (ModuleInitFunc*)dlsym(module, "init_module");
442 if (!v8cpp_init_func)
443 {
444- std::cerr << "dlsym failed: " << dlerror() << std::endl;
445- return exports;
446+ throw std::runtime_error("dlsym failed: " + std::string(dlerror()));
447 }
448
449 v8cpp_init_func(exports);
450
451=== modified file 'src/run.h'
452--- src/run.h 2015-07-02 11:59:20 +0000
453+++ src/run.h 2015-07-07 10:47:30 +0000
454@@ -77,7 +77,16 @@
455 }
456 }
457
458- return v8cpp::from_v8<T>(isolate, script->Run());
459+ v8::TryCatch try_catch;
460+
461+ auto result = script->Run();
462+
463+ if (try_catch.HasCaught())
464+ {
465+ throw std::runtime_error(v8cpp::from_v8<std::string>(isolate, try_catch.Message()->Get()));
466+ }
467+
468+ return v8cpp::from_v8<T>(isolate, result);
469 }
470
471 template <typename T = v8::Handle<v8::Value>>
472
473=== modified file 'tests/CMakeLists.txt'
474--- tests/CMakeLists.txt 2015-07-01 11:55:28 +0000
475+++ tests/CMakeLists.txt 2015-07-07 10:47:30 +0000
476@@ -6,7 +6,9 @@
477 ${TEST_INCLUDE_DIRS}
478 )
479
480+add_subdirectory(errors)
481 add_subdirectory(functions)
482 add_subdirectory(members)
483 add_subdirectory(methods)
484 add_subdirectory(objects)
485+add_subdirectory(run)
486
487=== added directory 'tests/errors'
488=== added file 'tests/errors/CMakeLists.txt'
489--- tests/errors/CMakeLists.txt 1970-01-01 00:00:00 +0000
490+++ tests/errors/CMakeLists.txt 2015-07-07 10:47:30 +0000
491@@ -0,0 +1,49 @@
492+# MODULE
493+add_library(
494+ test-errors-module SHARED
495+ module.cpp
496+)
497+
498+# This line sets the output binary name to "<target_name>.so"
499+set_target_properties(
500+ test-errors-module
501+ PROPERTIES
502+ PREFIX ""
503+)
504+
505+# FAIL-MODULE
506+add_library(
507+ test-errors-fail-module SHARED
508+ fail-module.cpp
509+)
510+
511+# This line sets the output binary name to "<target_name>.so"
512+set_target_properties(
513+ test-errors-fail-module
514+ PROPERTIES
515+ PREFIX ""
516+)
517+
518+# TEST
519+configure_file(scripts/fail.js scripts/fail.js)
520+
521+add_executable(
522+ test-errors
523+ test.h
524+ test.cpp
525+)
526+
527+target_link_libraries(
528+ test-errors
529+
530+ v8-cpp
531+
532+ ${GTEST_BOTH_LIBRARIES}
533+ ${GMOCK_LIBRARIES}
534+ ${TEST_LDFLAGS}
535+)
536+
537+add_test(
538+ test-errors
539+ test-errors
540+)
541
542=== added file 'tests/errors/fail-module.cpp'
543--- tests/errors/fail-module.cpp 1970-01-01 00:00:00 +0000
544+++ tests/errors/fail-module.cpp 2015-07-07 10:47:30 +0000
545@@ -0,0 +1,1 @@
546+// Intentionally blank
547
548=== added file 'tests/errors/module.cpp'
549--- tests/errors/module.cpp 1970-01-01 00:00:00 +0000
550+++ tests/errors/module.cpp 2015-07-07 10:47:30 +0000
551@@ -0,0 +1,27 @@
552+#include "test.h"
553+
554+#include <v8-cpp.h>
555+
556+using namespace v8;
557+
558+void InitAll(Handle<Object> exports)
559+{
560+ // Get current isolate
561+ Isolate* isolate = Isolate::GetCurrent();
562+
563+ // Prepare TestClass binding
564+ v8cpp::Class<TestClass> testclass(isolate);
565+ testclass
566+ .set_constructor<int, int>()
567+ .add_method("i", &TestClass::i)
568+ .add_method("throw_ex", &TestClass::throw_ex);
569+
570+ // Prepare module
571+ v8cpp::Module module(isolate);
572+
573+ module.add_class("TestClass", testclass);
574+
575+ exports->SetPrototype(module.create_prototype());
576+}
577+
578+V8CPP_MODULE(addon, InitAll)
579
580=== added directory 'tests/errors/scripts'
581=== added file 'tests/errors/scripts/fail.js'
582--- tests/errors/scripts/fail.js 1970-01-01 00:00:00 +0000
583+++ tests/errors/scripts/fail.js 2015-07-07 10:47:30 +0000
584@@ -0,0 +1,1 @@
585+#!/usr/bin/env sh
586
587=== added file 'tests/errors/test.cpp'
588--- tests/errors/test.cpp 1970-01-01 00:00:00 +0000
589+++ tests/errors/test.cpp 2015-07-07 10:47:30 +0000
590@@ -0,0 +1,183 @@
591+#include "test.h"
592+
593+#include <v8-cpp.h>
594+
595+#include <gtest/gtest.h>
596+
597+TEST(Test, non_existent_script)
598+{
599+ v8::Isolate* isolate = v8::Isolate::New();
600+
601+ try
602+ {
603+ v8cpp::run_script_file(isolate, "./scripts/noexist.js");
604+ }
605+ catch (std::exception const& e)
606+ {
607+ EXPECT_STREQ(e.what(), "run_script_file(): Failed to locate script file: \"./scripts/noexist.js\"");
608+ }
609+
610+ isolate->Dispose();
611+}
612+
613+TEST(Test, non_existent_module)
614+{
615+ v8::Isolate* isolate = v8::Isolate::New();
616+
617+ try
618+ {
619+ v8cpp::run_script(isolate, "require('./noexist-module')");
620+ }
621+ catch (std::exception const& e)
622+ {
623+ EXPECT_STREQ(e.what(), "Uncaught Error: dlopen failed: ./noexist-module: cannot open shared object file: No such file or directory");
624+ }
625+
626+ isolate->Dispose();
627+}
628+
629+TEST(Test, failing_module)
630+{
631+ v8::Isolate* isolate = v8::Isolate::New();
632+
633+ try
634+ {
635+ v8cpp::run_script(isolate, "require('./test-errors-fail-module')");
636+ }
637+ catch (std::exception const& e)
638+ {
639+ EXPECT_STREQ(e.what(), "Uncaught Error: dlsym failed: ./test-errors-fail-module.so: undefined symbol: init_module");
640+ }
641+
642+ isolate->Dispose();
643+}
644+
645+TEST(Test, failing_script)
646+{
647+ v8::Isolate* isolate = v8::Isolate::New();
648+
649+ try
650+ {
651+ v8cpp::run_script(isolate, "#!/usr/bin/env sh");
652+ }
653+ catch (std::exception const& e)
654+ {
655+ EXPECT_STREQ(e.what(), "run_script(): Failed to compile script.");
656+ }
657+
658+ isolate->Dispose();
659+}
660+
661+TEST(Test, failing_script_file)
662+{
663+ v8::Isolate* isolate = v8::Isolate::New();
664+
665+ try
666+ {
667+ v8cpp::run_script_file(isolate, "./scripts/fail.js");
668+ }
669+ catch (std::exception const& e)
670+ {
671+ EXPECT_STREQ(e.what(), "run_script(): Failed to compile script file: \"./scripts/fail.js\"");
672+ }
673+
674+ isolate->Dispose();
675+}
676+
677+TEST(Test, incorrect_function_args)
678+{
679+ v8::Isolate* isolate = v8::Isolate::New();
680+
681+ try
682+ {
683+ v8cpp::run_script(isolate,
684+ R"(
685+ var module = require("./test-errors-module");
686+ var test_object = new module.TestClass(1);
687+ test_object.i();
688+ )");
689+ }
690+ catch (std::exception const& e)
691+ {
692+ EXPECT_STREQ(e.what(), "Uncaught Error: argument count does not match the corresponding C++ function definition");
693+ }
694+
695+ isolate->Dispose();
696+}
697+
698+TEST(Test, conversion_errors)
699+{
700+ v8::Isolate* isolate = v8::Isolate::New();
701+
702+ try
703+ {
704+ v8cpp::run_script<std::string>(isolate, "1");
705+ }
706+ catch (std::exception const& e)
707+ {
708+ EXPECT_STREQ(e.what(), "expected string value");
709+ }
710+ try
711+ {
712+ v8cpp::run_script<bool>(isolate, "'hello'");
713+ }
714+ catch (std::exception const& e)
715+ {
716+ EXPECT_STREQ(e.what(), "expected bool value");
717+ }
718+ try
719+ {
720+ v8cpp::run_script<int>(isolate, "'hello'");
721+ }
722+ catch (std::exception const& e)
723+ {
724+ EXPECT_STREQ(e.what(), "expected integer value");
725+ }
726+ try
727+ {
728+ v8cpp::run_script<float>(isolate, "'hello'");
729+ }
730+ catch (std::exception const& e)
731+ {
732+ EXPECT_STREQ(e.what(), "expected float value");
733+ }
734+ try
735+ {
736+ v8cpp::run_script<std::vector<char>>(isolate, "1");
737+ }
738+ catch (std::exception const& e)
739+ {
740+ EXPECT_STREQ(e.what(), "expected array value");
741+ }
742+ try
743+ {
744+ v8cpp::run_script<TestClass>(isolate, "1");
745+ }
746+ catch (std::exception const& e)
747+ {
748+ EXPECT_STREQ(e.what(), "expected an object");
749+ }
750+
751+ isolate->Dispose();
752+}
753+
754+TEST(Test, throw_from_module)
755+{
756+ v8::Isolate* isolate = v8::Isolate::New();
757+
758+ try
759+ {
760+ v8cpp::run_script(isolate,
761+ R"(
762+ var module = require("./test-errors-module");
763+ var test_object = new module.TestClass(1, 2);
764+ test_object.throw_ex();
765+ )");
766+ }
767+ catch (std::exception const& e)
768+ {
769+ EXPECT_STREQ(e.what(), "Uncaught Error: BOOM!");
770+ }
771+
772+ isolate->Dispose();
773+}
774
775=== added file 'tests/errors/test.h'
776--- tests/errors/test.h 1970-01-01 00:00:00 +0000
777+++ tests/errors/test.h 2015-07-07 10:47:30 +0000
778@@ -0,0 +1,25 @@
779+#pragma once
780+
781+#include <gtest/gtest.h>
782+
783+class TestClass
784+{
785+public:
786+ TestClass(int a, int b)
787+ {
788+ i_ = a + b;
789+ }
790+
791+ int i() const
792+ {
793+ return i_;
794+ }
795+
796+ void throw_ex()
797+ {
798+ throw std::runtime_error("BOOM!");
799+ }
800+
801+private:
802+ int i_;
803+};
804
805=== modified file 'tests/methods/CMakeLists.txt'
806--- tests/methods/CMakeLists.txt 2015-07-01 11:55:28 +0000
807+++ tests/methods/CMakeLists.txt 2015-07-07 10:47:30 +0000
808@@ -4,12 +4,12 @@
809 module.cpp
810 )
811
812-# This line sets the output binary name to "<target_name>.node"
813+# This line sets the output binary name to "<target_name>.so"
814 set_target_properties(
815 test-methods-module
816 PROPERTIES
817 PREFIX ""
818- SUFFIX ".node"
819+ SUFFIX ".so"
820 )
821
822 # TEST
823
824=== modified file 'tests/methods/module.cpp'
825--- tests/methods/module.cpp 2015-07-02 09:43:58 +0000
826+++ tests/methods/module.cpp 2015-07-07 10:47:30 +0000
827@@ -12,12 +12,14 @@
828 // Prepare TestClass binding
829 v8cpp::Class<TestClass_OL> testclass(isolate);
830 testclass
831+ .add_inheritance<BaseBaseTestClass>()
832 .add_inheritance<BaseTestClass>()
833 .add_inheritance<TestClass>()
834 .set_constructor()
835 .add_method("regular_method", &TestClass::regular_method)
836 .add_method("static_method", &TestClass::static_method)
837 .add_method("base_method", &BaseTestClass::base_method)
838+ .add_method("base_base_method", &BaseBaseTestClass::base_base_method)
839 .add_method("virtual_method", &TestClass::virtual_method)
840 .add_method("overload_method", &TestClass_OL::overload_method);
841
842
843=== modified file 'tests/methods/test.cpp'
844--- tests/methods/test.cpp 2015-07-02 09:58:48 +0000
845+++ tests/methods/test.cpp 2015-07-07 10:47:30 +0000
846@@ -55,6 +55,15 @@
847
848 EXPECT_EQ(result, 1);
849
850+ result = v8cpp::run_script<int>(isolate,
851+ R"(
852+ var module = require("./test-methods-module");
853+ var test_object = new module.TestClass();
854+ test_object.base_base_method();
855+ )");
856+
857+ EXPECT_EQ(result, 0);
858+
859 isolate->Dispose();
860 }
861
862
863=== modified file 'tests/methods/test.h'
864--- tests/methods/test.h 2015-07-02 11:25:17 +0000
865+++ tests/methods/test.h 2015-07-07 10:47:30 +0000
866@@ -4,7 +4,20 @@
867
868 #include <v8-cpp.h>
869
870-class BaseTestClass
871+class BaseBaseTestClass
872+{
873+public:
874+ virtual ~BaseBaseTestClass() = default;
875+
876+ int base_base_method()
877+ {
878+ return 0;
879+ }
880+
881+ virtual int virtual_method() = 0;
882+};
883+
884+class BaseTestClass : public BaseBaseTestClass
885 {
886 public:
887 virtual ~BaseTestClass() = default;
888@@ -13,8 +26,6 @@
889 {
890 return 1;
891 }
892-
893- virtual int virtual_method() = 0;
894 };
895
896 class TestClass : public BaseTestClass
897
898=== modified file 'tests/objects/CMakeLists.txt'
899--- tests/objects/CMakeLists.txt 2015-07-01 11:55:28 +0000
900+++ tests/objects/CMakeLists.txt 2015-07-07 10:47:30 +0000
901@@ -4,12 +4,12 @@
902 module.cpp
903 )
904
905-# This line sets the output binary name to "<target_name>.node"
906+# This line sets the output binary name to "<target_name>"
907 set_target_properties(
908 test-objects-module
909 PROPERTIES
910 PREFIX ""
911- SUFFIX ".node"
912+ SUFFIX ""
913 )
914
915 # TEST
916
917=== added directory 'tests/run'
918=== added file 'tests/run/CMakeLists.txt'
919--- tests/run/CMakeLists.txt 1970-01-01 00:00:00 +0000
920+++ tests/run/CMakeLists.txt 2015-07-07 10:47:30 +0000
921@@ -0,0 +1,37 @@
922+# MODULE
923+add_library(
924+ test-run-module SHARED
925+ module.cpp
926+)
927+
928+# This line sets the output binary name to "<target_name>.so"
929+set_target_properties(
930+ test-run-module
931+ PROPERTIES
932+ PREFIX ""
933+)
934+
935+# TEST
936+configure_file(scripts/test.js scripts/test.js)
937+configure_file(scripts/test2.js scripts/test2.js)
938+
939+add_executable(
940+ test-run
941+ test.h
942+ test.cpp
943+)
944+
945+target_link_libraries(
946+ test-run
947+
948+ v8-cpp
949+
950+ ${GTEST_BOTH_LIBRARIES}
951+ ${GMOCK_LIBRARIES}
952+ ${TEST_LDFLAGS}
953+)
954+
955+add_test(
956+ test-run
957+ test-run
958+)
959
960=== added file 'tests/run/module.cpp'
961--- tests/run/module.cpp 1970-01-01 00:00:00 +0000
962+++ tests/run/module.cpp 2015-07-07 10:47:30 +0000
963@@ -0,0 +1,26 @@
964+#include "test.h"
965+
966+#include <v8-cpp.h>
967+
968+using namespace v8;
969+
970+void InitAll(Handle<Object> exports)
971+{
972+ // Get current isolate
973+ Isolate* isolate = Isolate::GetCurrent();
974+
975+ // Prepare TestClass binding
976+ v8cpp::Class<TestClass> testclass(isolate);
977+ testclass
978+ .set_constructor<int, int>()
979+ .add_method("i", &TestClass::i);
980+
981+ // Prepare module
982+ v8cpp::Module module(isolate);
983+
984+ module.add_class("TestClass", testclass);
985+
986+ exports->SetPrototype(module.create_prototype());
987+}
988+
989+V8CPP_MODULE(addon, InitAll)
990
991=== added directory 'tests/run/scripts'
992=== added file 'tests/run/scripts/test.js'
993--- tests/run/scripts/test.js 1970-01-01 00:00:00 +0000
994+++ tests/run/scripts/test.js 2015-07-07 10:47:30 +0000
995@@ -0,0 +1,3 @@
996+var module = require("../test-run-module");
997+var test_object = new module.TestClass(1, 2);
998+test_object;
999
1000=== added file 'tests/run/scripts/test2.js'
1001--- tests/run/scripts/test2.js 1970-01-01 00:00:00 +0000
1002+++ tests/run/scripts/test2.js 2015-07-07 10:47:30 +0000
1003@@ -0,0 +1,7 @@
1004+console.log(6354, " > ", -23);
1005+console.log(-9.21, " < ", 0.359);
1006+console.log(true, " > ", false);
1007+console.log("hello", " ", "there");
1008+
1009+var module = require("../test-run-module");
1010+new module.TestClass(3, 4);
1011
1012=== added file 'tests/run/test.cpp'
1013--- tests/run/test.cpp 1970-01-01 00:00:00 +0000
1014+++ tests/run/test.cpp 2015-07-07 10:47:30 +0000
1015@@ -0,0 +1,27 @@
1016+#include "test.h"
1017+
1018+#include <v8-cpp.h>
1019+
1020+#include <gtest/gtest.h>
1021+
1022+TEST(Test, run_test_script)
1023+{
1024+ v8::Isolate* isolate = v8::Isolate::New();
1025+
1026+ auto test_object = v8cpp::run_script_file<TestClass>(isolate, "./scripts/test.js");
1027+
1028+ EXPECT_EQ(test_object.i(), 3);
1029+
1030+ isolate->Dispose();
1031+}
1032+
1033+TEST(Test, run_test_script_2)
1034+{
1035+ v8::Isolate* isolate = v8::Isolate::New();
1036+
1037+ auto test_object = v8cpp::run_script_file<TestClass>(isolate, "./scripts/test2.js");
1038+
1039+ EXPECT_EQ(test_object.i(), 7);
1040+
1041+ isolate->Dispose();
1042+}
1043
1044=== added file 'tests/run/test.h'
1045--- tests/run/test.h 1970-01-01 00:00:00 +0000
1046+++ tests/run/test.h 2015-07-07 10:47:30 +0000
1047@@ -0,0 +1,20 @@
1048+#pragma once
1049+
1050+#include <gtest/gtest.h>
1051+
1052+class TestClass
1053+{
1054+public:
1055+ TestClass(int a, int b)
1056+ {
1057+ i_ = a + b;
1058+ }
1059+
1060+ int i() const
1061+ {
1062+ return i_;
1063+ }
1064+
1065+private:
1066+ int i_;
1067+};

Subscribers

People subscribed via source and target branches

to all changes: