diff --git a/Src/IronRuby.Tests/RubyTests.cs b/Src/IronRuby.Tests/RubyTests.cs
index d04fb77a5..71564ec72 100644
--- a/Src/IronRuby.Tests/RubyTests.cs
+++ b/Src/IronRuby.Tests/RubyTests.cs
@@ -857,6 +857,12 @@ public Tests(Driver/*!*/ driver) {
File_StatPredicatesToIo2,
IO_SysOpenArguments1,
IO_SysOpenPermission1,
+ String_BrokenPattern1,
+ Thread_StopAlone1,
+ Thread_HostMainThread1,
+ Thread_HostMainThread2,
+ Windows_NotImplementedAndLinks1,
+ Windows_SymLinks1,
Range_IntegerFastPaths1,
Io_BuiltinReaders1,
Io_LineReaders2,
diff --git a/Src/IronRuby.Tests/Runtime/MiscTests.cs b/Src/IronRuby.Tests/Runtime/MiscTests.cs
index d17a92833..f95a30f2f 100644
--- a/Src/IronRuby.Tests/Runtime/MiscTests.cs
+++ b/Src/IronRuby.Tests/Runtime/MiscTests.cs
@@ -2808,6 +2808,308 @@ public void IO_SysOpenPermission1() {
");
}
+ ///
+ /// A String pattern whose bytes are not valid in its encoding, as MRI treats it: #sub, #gsub, their
+ /// bang forms and #scan raise Regexp.new's RegexpError (string.c's get_pat_quoted), where IronRuby said
+ /// ArgumentError or, with a valid receiver, matched nothing; the searches - #index, #rindex, #byteindex,
+ /// #byterindex, #[], #slice, #slice!, #[]=, #partition, #rpartition - find nothing (rb_strseq_index),
+ /// where IronRuby found the bytes.
+ ///
+ public void String_BrokenPattern1() {
+ TestOutput(@"
+require 'ruby4'
+def show(l); v = begin; yield; rescue Exception => e; ""#{e.class}: #{e.message}""; end; puts ""#{l}: #{v.inspect}""; end
+s = ""a\xffb\xffc""; pat = ""\xff""
+show(""Regexp.new"") { Regexp.new(pat) }
+show(""sub"") { s.sub(pat, ""Z"") }
+show(""sub!"") { s.dup.sub!(pat, ""Z"") }
+show(""sub blk"") { s.sub(pat) { ""Z"" } }
+show(""gsub"") { s.gsub(pat, ""Z"") }
+show(""gsub!"") { s.dup.gsub!(pat) { ""Z"" } }
+show(""gsub enum"") { s.gsub(pat).to_a }
+show(""gsub enum is lazy"") { [""abc"".gsub(pat).class, ""abc"".dup.gsub!(pat).class] }
+show(""gsub hash"") { s.gsub(pat, {}) }
+show(""scan"") { s.scan(pat) }
+show(""scan blk"") { s.scan(pat) { } }
+show(""split"") { s.split(pat) }
+show(""index"") { s.index(pat) }
+show(""include?"") { s.include?(pat) }
+show(""start_with?"") { s.start_with?(pat) }
+show(""partition"") { s.partition(pat) }
+show(""count"") { s.count(pat) }
+show(""binary ok"") { ""a\xffb"".b.gsub(""\xff"".b, ""Z"") }
+show(""other enc broken"") { ""a\xffb"".force_encoding(""EUC-JP"").gsub(""\xff"".force_encoding(""EUC-JP""), ""Z"") }
+show(""to_str broken"") { o = Object.new; def o.to_str; ""\xff""; end; ""a"".gsub(o, ""Z"") }
+show(""valid receiver"") { ""abc"".gsub(""\xff"", ""Z"") }
+show(""mid"") { ""x"".sub(""a\xe3b"", ""Z"") }
+show(""index"") { s.index(pat) }
+show(""index off"") { s.index(pat, 2) }
+show(""rindex"") { s.rindex(pat) }
+show(""byteindex"") { s.byteindex(pat) }
+show(""byterindex"") { s.byterindex(pat) }
+show(""include?"") { s.include?(pat) }
+show(""[]"") { s[pat] }
+show(""slice"") { s.slice(pat) }
+show(""slice!"") { t = s.dup; [t.slice!(pat), t] }
+show(""[]="") { t = s.dup; t[pat] = ""Z""; t }
+show(""partition"") { s.partition(pat) }
+show(""rpartition"") { s.rpartition(pat) }
+show(""valid in broken"") { s.index(""b"") }
+show(""broken mid"") { ""ab\xe3"".index(""\xe3"") }
+", @"
+Regexp.new: ""RegexpError: invalid multibyte character: /\\xFF/""
+sub: ""RegexpError: invalid multibyte character: /\\xFF/""
+sub!: ""RegexpError: invalid multibyte character: /\\xFF/""
+sub blk: ""RegexpError: invalid multibyte character: /\\xFF/""
+gsub: ""RegexpError: invalid multibyte character: /\\xFF/""
+gsub!: ""RegexpError: invalid multibyte character: /\\xFF/""
+gsub enum: ""RegexpError: invalid multibyte character: /\\xFF/""
+gsub enum is lazy: [Enumerator, Enumerator]
+gsub hash: ""RegexpError: invalid multibyte character: /\\xFF/""
+scan: ""RegexpError: invalid multibyte character: /\\xFF/""
+scan blk: ""RegexpError: invalid multibyte character: /\\xFF/""
+split: ""ArgumentError: invalid byte sequence in UTF-8""
+index: nil
+include?: false
+start_with?: false
+partition: [""a\xFFb\xFFc"", """", """"]
+count: ""ArgumentError: invalid byte sequence in UTF-8""
+binary ok: ""aZb""
+other enc broken: ""RegexpError: invalid multibyte character: /\\xFF/""
+to_str broken: ""RegexpError: invalid multibyte character: /\\xFF/""
+valid receiver: ""RegexpError: invalid multibyte character: /\\xFF/""
+mid: ""RegexpError: invalid multibyte character: /a\\xE3b/""
+index: nil
+index off: nil
+rindex: nil
+byteindex: nil
+byterindex: nil
+include?: false
+[]: nil
+slice: nil
+slice!: [nil, ""a\xFFb\xFFc""]
+[]=: ""IndexError: string not matched""
+partition: [""a\xFFb\xFFc"", """", """"]
+rpartition: ["""", """", ""a\xFFb\xFFc""]
+valid in broken: 2
+broken mid: nil
+");
+ }
+
+ ///
+ /// A host that creates the runtime on one thread and runs Ruby on another: the creating
+ /// thread is Thread.main and is listed even though no Ruby code ever ran on it.
+ ///
+ public void Thread_HostMainThread1() {
+ Microsoft.Scripting.Hosting.ScriptEngine engine = null;
+ var created = new System.Threading.ManualResetEvent(false);
+ var done = new System.Threading.ManualResetEvent(false);
+ var creator = new System.Threading.Thread(() => {
+ engine = Ruby.CreateEngine();
+ created.Set();
+ done.WaitOne();
+ });
+ creator.IsBackground = true;
+ creator.Start();
+ try {
+ Assert(created.WaitOne(30000));
+ var result = engine.Execute