-
Notifications
You must be signed in to change notification settings - Fork 193
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
Fix #5162 - Capture exit
from Ruby
#5166
Changes from all commits
4146cf7
28d8bf3
dfb0f22
5be26e6
7b398cb
456cb37
56b0b6a
00eb71c
ce60443
2d8a2d6
0775550
3b70376
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,7 +75,13 @@ void RubyEngine::setupEmbeddedGems(const std::vector<openstudio::path>& includeD | |
} | ||
|
||
RubyEngine::~RubyEngine() { | ||
ruby_finalize(); | ||
// ruby_cleanup calls ruby_finalize | ||
int ex = ruby_cleanup(0); | ||
if (ex != 0) { | ||
fmt::print("RubyEngine return code was {}\n", ex); | ||
exit(ex); | ||
} | ||
//ruby_finalize(); | ||
Comment on lines
+78
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kbenne here is the most important change. Originally I had fixed it by using an at_exit block in executeRubyScriptCommand. THe Kernel.exit! was sufficient to propagate it to C++. But the issue was that this would be returning zero : at_exit {{
exit_code = ($! and $!.kind_of? SystemExit) ? $!.status : 0
STDOUT.flush
STDERR.flush
if exit_code != 0
Kernel.exit!(exit_code)
end
}} |
||
} | ||
|
||
ScriptObject RubyEngine::eval(std::string_view sv) { | ||
|
@@ -95,30 +101,56 @@ void* RubyEngine::getAs_impl(ScriptObject& obj, const std::type_info& ti) { | |
|
||
void* return_value = nullptr; | ||
|
||
// TODO: this sucks, and probably needs memory management | ||
if (ti == typeid(std::string*)) { | ||
char* cstr = StringValuePtr(val); | ||
size_t size = RSTRING_LEN(val); // + 1; From trial and eror, if I had + 1 I get a string with one two many size | ||
return_value = new std::string(cstr, size); | ||
const auto& type_name = getRegisteredTypeName(ti); | ||
|
||
// std::string s = rb_string_value_cstr(&val); | ||
} else { | ||
const auto& type_name = getRegisteredTypeName(ti); | ||
auto* type = SWIG_TypeQuery(type_name.c_str()); | ||
auto* type = SWIG_TypeQuery(type_name.c_str()); | ||
|
||
if (!type) { | ||
throw std::runtime_error("Unable to find type in SWIG"); | ||
} | ||
if (!type) { | ||
throw std::runtime_error("Unable to find type in SWIG"); | ||
} | ||
|
||
const auto result = SWIG_ConvertPtr(val, &return_value, type, 0); | ||
const auto result = SWIG_ConvertPtr(val, &return_value, type, 0); | ||
|
||
if (!SWIG_IsOK(result)) { | ||
throw std::runtime_error("Error getting object from SWIG/Ruby"); | ||
} | ||
if (!SWIG_IsOK(result)) { | ||
throw std::runtime_error("Error getting object from SWIG/Ruby"); | ||
} | ||
return return_value; | ||
} | ||
|
||
bool RubyEngine::getAs_impl_bool(ScriptObject& obj) { | ||
auto val = std::any_cast<VALUE>(obj.object); | ||
return RB_TEST(val); | ||
} | ||
|
||
int RubyEngine::getAs_impl_int(ScriptObject& obj) { | ||
auto val = std::any_cast<VALUE>(obj.object); | ||
if (!RB_FIXNUM_P(val)) { | ||
throw std::runtime_error("VALUE is not a FIXNUM"); | ||
} | ||
|
||
return RB_NUM2INT(val); | ||
} | ||
double RubyEngine::getAs_impl_double(ScriptObject& obj) { | ||
auto val = std::any_cast<VALUE>(obj.object); | ||
if (!RB_FLOAT_TYPE_P(val)) { | ||
throw std::runtime_error("VALUE is not a FLOAT"); | ||
} | ||
|
||
return RB_NUM2INT(val); | ||
} | ||
|
||
std::string RubyEngine::getAs_impl_string(ScriptObject& obj) { | ||
auto val = std::any_cast<VALUE>(obj.object); | ||
|
||
if (!RB_TYPE_P(val, RUBY_T_STRING)) { | ||
throw std::runtime_error("VALUE is not a String"); | ||
} | ||
|
||
char* cstr = StringValuePtr(val); | ||
size_t size = RSTRING_LEN(val); // + 1; From trial and eror, if I had + 1 I get a string with one two many size | ||
return std::string{cstr, size}; | ||
} | ||
|
||
std::string RubyEngine::inferMeasureClassName(const openstudio::path& measureScriptPath) { | ||
|
||
auto inferClassNameCmd = fmt::format(R"ruby( | ||
|
@@ -161,7 +193,7 @@ ObjectSpace.garbage_collect | |
ScriptObject measureClassNameObject = eval("$measure_name"); | ||
// measureClassNameObject = rubyEngine->eval(fmt::format("{}.new()", className)); | ||
// ScriptObject measureClassNameObject = rubyEngine->eval(inferClassName); | ||
className = *getAs<std::string*>(measureClassNameObject); | ||
className = getAs<std::string>(measureClassNameObject); | ||
} catch (const RubyException& e) { | ||
auto msg = fmt::format("Failed to infer measure name from {}: {}\nlocation={}", measureScriptPath.generic_string(), e.what(), e.location()); | ||
fmt::print(stderr, "{}\n", msg); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -476,6 +476,17 @@ if(BUILD_TESTING) | |
message(AUTHOR_WARNING "Cannot run the python numpy test, as numpy isn't installed on your system python") | ||
endif() | ||
|
||
if (Python_EXECUTABLE) | ||
add_test(NAME OpenStudioCLI.minitest_fail | ||
COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test/run_minitest_fail.py" $<TARGET_FILE:openstudio> | ||
) | ||
if (SYSTEM_RUBY_EXECUTABLE) | ||
add_test(NAME RubyTest.minitest_fail | ||
COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/test/run_minitest_fail.py" "${SYSTEM_RUBY_EXECUTABLE}" | ||
) | ||
endif() | ||
endif() | ||
Comment on lines
+479
to
+488
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. new tests |
||
|
||
file(GLOB RUBY_TEST_SRC | ||
# find all CLI test | ||
"test/test*.rb" | ||
|
@@ -498,13 +509,16 @@ if(BUILD_TESTING) | |
string(REGEX MATCH "/?([A-Za-z_0-9 ]+)\\.rb" FILE_NAME ${f}) | ||
string(REGEX REPLACE "/?([A-Za-z_0-9 ]+)\\.rb" "\\1" FILE_NAME ${FILE_NAME}) | ||
|
||
set(CTEST_NAME "CLITest-${FILE_NAME}-${TEST_NAME}") | ||
|
||
add_test(NAME "CLITest-${FILE_NAME}-${TEST_NAME}" | ||
COMMAND "${CMAKE_COMMAND}" -E chdir "${CMAKE_CURRENT_BINARY_DIR}" | ||
"$<TARGET_FILE:openstudio>" "${f}" "--name=test_${TEST_NAME}" | ||
) | ||
add_test(NAME "${CTEST_NAME}" | ||
COMMAND "${CMAKE_COMMAND}" -E chdir "${CMAKE_CURRENT_BINARY_DIR}" | ||
"$<TARGET_FILE:openstudio>" "${f}" "--name=test_${TEST_NAME}" | ||
) | ||
|
||
set_tests_properties("CLITest-${FILE_NAME}-${TEST_NAME}" PROPERTIES TIMEOUT 660 ) | ||
set_tests_properties("${CTEST_NAME}" PROPERTIES TIMEOUT 660 ) | ||
endforeach() | ||
|
||
endforeach() | ||
|
||
endif() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
at_exit { | ||
exit 12 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
require 'minitest' | ||
require 'minitest/autorun' | ||
|
||
class MyTest < Minitest::Test | ||
def test_should_fail | ||
assert 0 == 1 | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
require 'minitest' | ||
require 'minitest/autorun' | ||
|
||
class MyTest < Minitest::Test | ||
def test_should_pass | ||
assert 0 == 0 | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jmarrec Did you mean to leave this in or was it for debugging? Seems weird that this is now printed.