std::string throws typemaps

Go, Guile, Racket, Scilab: Add throws typemaps for std::string so that
thrown string exception messages can be seen.

Test all language for std::string throws typemaps
This commit is contained in:
William S Fulton 2022-09-18 20:20:21 +01:00
parent 4a29229bab
commit ed333b6b97
24 changed files with 225 additions and 12 deletions

View File

@ -7,6 +7,14 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress)
===========================
2022-09-17: wsfulton
[Go, Guile, Racket, Scilab] Add throws typemaps for std::string so that thrown
string exception messages can be seen.
2022-09-17: wsfulton
[Racket] Add throws typemaps for char * so that thrown string exception
messages can be seen from Racket.
2022-09-17: wsfulton
[Javascript, Octave, R] Improve exceptions for %catches and exception
specifications for native types. String exception messages are shown as

View File

@ -3,11 +3,15 @@
%include <std_string.i>
%catches(const char *) StringsThrower::charstring;
%catches(std::string) StringsThrower::stdstring;
%inline %{
struct StringsThrower {
static void charstring() {
throw "charstring message";
}
static void stdstring() {
throw std::string("stdstring message");
}
};
%}

View File

@ -16,5 +16,17 @@ public class catches_strings_runme {
if (!exception_thrown)
throw new ApplicationException("Should have thrown an exception");
}
{
bool exception_thrown = false;
try {
StringsThrower.stdstring();
} catch (ApplicationException e) {
if (!e.Message.Contains("stdstring message"))
throw new ApplicationException("incorrect exception message:" + e);
exception_thrown = true;
}
if (!exception_thrown)
throw new ApplicationException("Should have thrown an exception");
}
}
}

View File

@ -17,4 +17,16 @@ void main() {
if (!exception_thrown)
throw new Exception("Should have thrown an exception");
}
{
bool exception_thrown = false;
try {
StringsThrower.stdstring();
} catch (Exception e) {
if (!canFind(e.msg, "stdstring message"))
throw new Exception("incorrect exception message:" ~ e.msg);
exception_thrown = true;
}
if (!exception_thrown)
throw new Exception("Should have thrown an exception");
}
}

View File

@ -17,4 +17,16 @@ void main() {
if (!exception_thrown)
throw new Exception("Should have thrown an exception");
}
{
bool exception_thrown = false;
try {
StringsThrower.stdstring();
} catch (Exception e) {
if (!canFind(e.msg, "stdstring message"))
throw new Exception("incorrect exception message:" ~ e.msg);
exception_thrown = true;
}
if (!exception_thrown)
throw new Exception("Should have thrown an exception");
}
}

View File

@ -4,14 +4,29 @@ import "strings"
import . "swigtests/catches_strings"
func main() {
exception_thrown := false
func() {
defer func() {
exception_thrown = strings.Index(recover().(string), "charstring message") == 0
{
exception_thrown := false
func() {
defer func() {
exception_thrown = strings.Index(recover().(string), "charstring message") == 0
}()
StringsThrowerCharstring()
}()
StringsThrowerCharstring()
}()
if !exception_thrown {
panic(0)
if !exception_thrown {
panic(0)
}
}
{
exception_thrown := false
func() {
defer func() {
exception_thrown = strings.Index(recover().(string), "stdstring message") == 0
}()
StringsThrowerStdstring()
}()
if !exception_thrown {
panic(0)
}
}
}

View File

@ -24,5 +24,18 @@ public class catches_strings_runme {
if (!exception_thrown)
throw new RuntimeException("Should have thrown an exception");
}
{
boolean exception_thrown = false;
try {
StringsThrower.stdstring();
} catch (RuntimeException e) {
if (!e.getMessage().contains("stdstring message"))
throw new RuntimeException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new RuntimeException("Should have thrown an exception");
}
}
}

View File

@ -4,12 +4,20 @@ exception_thrown = false;
try {
catches_strings.StringsThrower.charstring();
} catch (e) {
console.log(typeof(e))
console.log(e.constructor.name)
console.log(typeof(e.message))
if (!e.message.includes("charstring message"))
throw new Error("incorrect exception message " + e.message);
exception_thrown = true;
}
if (!exception_thrown)
throw new Error("Should have thrown an exception");
exception_thrown = false;
try {
catches_strings.StringsThrower.stdstring();
} catch (e) {
if (!e.message.includes("stdstring message"))
throw new Error("incorrect exception message " + e.message);
exception_thrown = true;
}
if (!exception_thrown)
throw new Error("Should have thrown an exception");

View File

@ -8,3 +8,6 @@ setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i
s, msg = pcall(function() catches_strings.StringsThrower.charstring() end)
assert(s == false and msg:find("charstring message", 1, true))
s, msg = pcall(function() catches_strings.StringsThrower.stdstring() end)
assert(s == false and msg:find("stdstring message", 1, true))

View File

@ -8,4 +8,11 @@
(unless (string-contains? exception_thrown "charstring message")
(error (format "incorrect exception message: ~a" exception_thrown)))
(define exception_thrown "no exception thrown for kin")
(with-handlers ([exn:fail? (lambda (exn)
(set! exception_thrown (exn-message exn)))])
(StringsThrower-stdstring))
(unless (string-contains? exception_thrown "stdstring message")
(error (format "incorrect exception message: ~a" exception_thrown)))
(exit 0)

View File

@ -6,3 +6,9 @@ let _ =
ignore (_StringsThrower_charstring (C_void)); assert false
with Failure s ->
assert (s = "charstring message")
let _ =
try
ignore (_StringsThrower_stdstring (C_void)); assert false
with Failure s ->
assert (s = "stdstring message")

View File

@ -17,3 +17,16 @@ end_try_catch
if (!exception_thrown)
error("Should have thrown an exception");
endif
exception_thrown = false;
try
StringsThrower.stdstring();
catch e
if (isempty(strfind(e.message, "stdstring message")))
error("incorrect exception message: %s", e.message)
endif
exception_thrown = true;
end_try_catch
if (!exception_thrown)
error("Should have thrown an exception");
endif

View File

@ -1,6 +1,6 @@
use strict;
use warnings;
use Test::More tests => 3;
use Test::More tests => 4;
BEGIN { use_ok('catches_strings') }
require_ok('catches_strings');
@ -8,3 +8,8 @@ eval {
catches_strings::StringsThrower::charstring();
};
like($@, qr/\bcharstring message/, "Should have thrown an exception");
eval {
catches_strings::StringsThrower::stdstring();
};
like($@, qr/\bstdstring message/, "Should have thrown an exception");

View File

@ -11,4 +11,13 @@ try {
}
check::equal($exception_thrown, true, "Should have thrown an exception");
$exception_thrown = false;
try {
StringsThrower::stdstring();
} catch (Exception $e) {
check::str_contains($e->getMessage(), "stdstring message", "incorrect exception message: {$e->getMessage()}");
$exception_thrown = true;
}
check::equal($exception_thrown, true, "Should have thrown an exception");
check::done();

View File

@ -9,3 +9,13 @@ except RuntimeError as e:
exception_thrown = True
if not exception_thrown:
raise RuntimeError("Should have thrown an exception")
exception_thrown = False
try:
StringsThrower.stdstring()
except RuntimeError as e:
if "stdstring message" not in str(e):
raise RuntimeError("incorrect exception message:" + str(e))
exception_thrown = True
if not exception_thrown:
raise RuntimeError("Should have thrown an exception")

View File

@ -13,3 +13,12 @@ tryCatch({
}
)
unittest(exception_thrown, TRUE)
exception_thrown = FALSE
tryCatch({
StringsThrower_stdstring()
}, error = function(e) {
exception_thrown <<- grepl(e$message, "stdstring message", fixed=TRUE)
}
)
unittest(exception_thrown, TRUE)

View File

@ -16,3 +16,16 @@ end
if (!exception_thrown)
raise RuntimeError, "Should have thrown an exception"
end
exception_thrown = false
begin
Catches_strings::StringsThrower.stdstring()
rescue RuntimeError => e
if (!e.to_s.include? "stdstring message")
raise RuntimeError, "incorrect exception message: #{e.to_s}"
end
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "Should have thrown an exception"
end

View File

@ -2,4 +2,8 @@
(StringsThrower-charstring))
; TODO: check the exception message
(expect-throw 'swig-exception
(StringsThrower-stdstring))
; TODO: check the exception message
(exit 0)

View File

@ -7,4 +7,11 @@ if (strstr(lasterror(), "charstring message") == '')
exit(1)
end
ierr = execstr("StringsThrower_stdstring()", 'errcatch');
checkequal(ierr, 20000, "wrong/no exception thrown")
if (strstr(lasterror(), "stdstring message") == '')
printf("Should have thrown an exception")
exit(1)
end
exec("swigtest.quit", -1);

View File

@ -16,3 +16,16 @@ if [ catch {
if {!$exception_thrown} {
error "Should have thrown an exception"
}
set exception_thrown 0
if [ catch {
StringsThrower_stdstring
} e ] {
if {[string first "stdstring message" $e] == -1} {
error "incorrect exception message: $e"
}
set exception_thrown 1
}
if {!$exception_thrown} {
error "Should have thrown an exception"
}

View File

@ -52,6 +52,9 @@ class string;
%typemap(godirectorin,fragment="CopyString") string
%{ $result = swigCopyString($input) %}
%typemap(throws) string
%{ _swig_gopanic($1.c_str()); %}
%typemap(in) const string &
%{
$*1_ltype $1_str($input.p, $input.n);
@ -88,6 +91,9 @@ class string;
%typemap(godirectorin,fragment="CopyString") const string &
%{ $result = swigCopyString($input) %}
%typemap(throws) const string &
%{ _swig_gopanic($1.c_str()); %}
%typemap(gotype) string * "*string"

View File

@ -83,4 +83,13 @@ namespace std {
$result = SWIG_str02scm($1.c_str());
}
%typemap(throws) string {
scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
scm_list_n(SWIG_str02scm($1.c_str()), SCM_UNDEFINED));
}
%typemap(throws) const string & {
scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
scm_list_n(SWIG_str02scm($1.c_str()), SCM_UNDEFINED));
}
}

View File

@ -52,6 +52,13 @@ namespace std {
$result = scheme_make_string($1->c_str());
}
%typemap(throws) string {
scheme_signal_error("%s: %s", FUNC_NAME, $1.c_str());
}
%typemap(throws) const string & {
scheme_signal_error("%s: %s", FUNC_NAME, $1.c_str());
}
}

View File

@ -37,3 +37,11 @@ SWIG_From_dec(std::string)(std::string pstValue) {
}
%include <typemaps/std_string.swg>
%typemap(throws, noblock=1) std::string {
SWIG_Scilab_Raise_Ex($1.c_str(), "$type", $&descriptor);
}
%typemap(throws, noblock=1) const std::string & {
SWIG_Scilab_Raise_Ex($1.c_str(), "$type", $descriptor);
}