diff --git a/.gitignore b/.gitignore index 00c0b86..e0db9b7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ coverage rdoc pkg +ext/bert/c/Makefile +ext/bert/c/*.bundle +ext/bert/c/*.o diff --git a/History.txt b/History.txt index 33771dc..fab8756 100644 --- a/History.txt +++ b/History.txt @@ -1,3 +1,7 @@ += + * Major Changes + * Remove reliance on Erlectricity. + = 1.0.0 / 2009-10-19 * No changes. Production ready! diff --git a/Rakefile b/Rakefile index aff2f65..357d505 100644 --- a/Rakefile +++ b/Rakefile @@ -12,6 +12,9 @@ begin gem.authors = ["Tom Preston-Werner"] gem.add_dependency('erlectricity', '>= 1.1.0') gem.add_development_dependency("thoughtbot-shoulda") + gem.require_paths = ["lib", "ext"] + gem.files.include("ext") + gem.extensions << 'ext/bert/c/extconf.rb' # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings end rescue LoadError @@ -19,12 +22,32 @@ rescue LoadError end require 'rake/testtask' -Rake::TestTask.new(:test) do |test| +Rake::TestTask.new(:runtests) do |test| test.libs << 'lib' << 'test' test.pattern = 'test/**/*_test.rb' test.verbose = true end +task :test => :check_dependencies do + require 'fileutils' + + puts "\nCleaning extension build files and running all specs in native ruby mode..." + ['rm -f ext/bert/c/*.bundle', 'rm -f ext/bert/c/*.o'].each do |cmd| + `#{cmd}` && puts(cmd) + end + pid = fork do + exec 'rake runtests' + end + Process.waitpid(pid) + + puts "\nRunning `make` to build extensions and rerunning decoder specs..." + Dir.chdir('ext/bert/c') { `make` } + pid = fork do + exec 'rake runtests' + end + Process.waitpid(pid) +end + begin require 'rcov/rcovtask' Rcov::RcovTask.new do |test| @@ -38,8 +61,6 @@ rescue LoadError end end -task :test => :check_dependencies - task :default => :test require 'rake/rdoctask' diff --git a/ext/bert/c/decode.c b/ext/bert/c/decode.c new file mode 100644 index 0000000..a09e15d --- /dev/null +++ b/ext/bert/c/decode.c @@ -0,0 +1,352 @@ +#include "ruby.h" +#include + +#define ERL_VERSION 131 +#define ERL_SMALL_INT 97 +#define ERL_INT 98 +#define ERL_SMALL_BIGNUM 110 +#define ERL_LARGE_BIGNUM 111 +#define ERL_FLOAT 99 +#define ERL_ATOM 100 +#define ERL_SMALL_TUPLE 104 +#define ERL_LARGE_TUPLE 105 +#define ERL_NIL 106 +#define ERL_STRING 107 +#define ERL_LIST 108 +#define ERL_BIN 109 + +static VALUE mBERT; +static VALUE cDecode; +void Init_decode(); + +VALUE method_decode(VALUE klass, VALUE rString); + +VALUE read_any_raw(unsigned char **pData); + +// checkers + +void check_int(int num) { + char buf[17]; + sprintf(buf, "%u", num); + rb_raise(rb_eStandardError, buf); +} + +void check_str(char *str) { + rb_raise(rb_eStandardError, str); +} + +// string peekers/readers + +unsigned int peek_1(unsigned char **pData) { + return (unsigned int) **pData; +} + +unsigned int peek_2(unsigned char **pData) { + return (unsigned int) ((**pData << 8) + *(*pData + 1)); +} + +unsigned int peek_4(unsigned char **pData) { + return (unsigned int) ((**pData << 24) + (*(*pData + 1) << 16) + (*(*pData + 2) << 8) + *(*pData + 3)); +} + +unsigned int read_1(unsigned char **pData) { + unsigned int val = peek_1(pData); + *pData += 1; + return val; +} + +unsigned int read_2(unsigned char **pData) { + unsigned int val = peek_2(pData); + *pData += 2; + return val; +} + +unsigned int read_4(unsigned char **pData) { + unsigned int val = peek_4(pData); + *pData += 4; + return val; +} + +// tuples, lists + +VALUE read_small_tuple(unsigned char **pData) { + if(read_1(pData) != ERL_SMALL_TUPLE) { + rb_raise(rb_eStandardError, "Invalid Type, not a small tuple"); + } + + int arity = read_1(pData); + + VALUE array = rb_ary_new2(arity); + + int i; + for(i = 0; i < arity; ++i) { + rb_ary_store(array, i, read_any_raw(pData)); + } + + return array; +} + +VALUE read_large_tuple(unsigned char **pData) { + if(read_1(pData) != ERL_LARGE_TUPLE) { + rb_raise(rb_eStandardError, "Invalid Type, not a large tuple"); + } + + int arity = read_4(pData); + + VALUE array = rb_ary_new2(arity); + + int i; + for(i = 0; i < arity; ++i) { + rb_ary_store(array, i, read_any_raw(pData)); + } + + return array; +} + +VALUE read_list(unsigned char **pData) { + if(read_1(pData) != ERL_LIST) { + rb_raise(rb_eStandardError, "Invalid Type, not an erlang list"); + } + + int size = read_4(pData); + + VALUE list_class = rb_const_get(mBERT, rb_intern("List")); + VALUE array = rb_funcall(list_class, rb_intern("new"), 1, INT2NUM(size)); + + int i; + for(i = 0; i < size; ++i) { + rb_ary_store(array, i, read_any_raw(pData)); + } + + read_1(pData); + + return array; +} + +// primitives + +void read_string_raw(unsigned char *dest, unsigned char **pData, int length) { + memcpy((char *) dest, (char *) *pData, length); + *(dest + length) = (unsigned char) 0; + *pData += length; +} + +VALUE read_bin(unsigned char **pData) { + if(read_1(pData) != ERL_BIN) { + rb_raise(rb_eStandardError, "Invalid Type, not an erlang binary"); + } + + int length = read_4(pData); + + unsigned char buf[length + 1]; + read_string_raw(buf, pData, length); + + return rb_str_new((char *) buf, length); +} + +VALUE read_string(unsigned char **pData) { + if(read_1(pData) != ERL_STRING) { + rb_raise(rb_eStandardError, "Invalid Type, not an erlang string"); + } + + int length = read_2(pData); + + unsigned char buf[length + 1]; + read_string_raw(buf, pData, length); + + VALUE list_class = rb_const_get(mBERT, rb_intern("List")); + VALUE array = rb_funcall(list_class, rb_intern("new"), 1, INT2NUM(length)); + + int i = 0; + for(i; i < length; ++i) { + rb_ary_store(array, i, INT2NUM(*(buf + i))); + } + + return array; +} + +VALUE read_atom(unsigned char **pData) { + if(read_1(pData) != ERL_ATOM) { + rb_raise(rb_eStandardError, "Invalid Type, not an atom"); + } + + int length = read_2(pData); + + unsigned char buf[length + 1]; + read_string_raw(buf, pData, length); + + return ID2SYM(rb_intern((char *) buf)); +} + +VALUE read_small_int(unsigned char **pData) { + if(read_1(pData) != ERL_SMALL_INT) { + rb_raise(rb_eStandardError, "Invalid Type, not a small int"); + } + + int value = read_1(pData); + + return INT2FIX(value); +} + +VALUE read_int(unsigned char **pData) { + if(read_1(pData) != ERL_INT) { + rb_raise(rb_eStandardError, "Invalid Type, not an int"); + } + + long long value = read_4(pData); + + long long negative = ((value >> 31) & 0x1 == 1); + + if(negative) { + value = (value - ((long long) 1 << 32)); + } + + return INT2FIX(value); +} + +VALUE read_small_bignum(unsigned char **pData) { + if(read_1(pData) != ERL_SMALL_BIGNUM) { + rb_raise(rb_eStandardError, "Invalid Type, not a small bignum"); + } + + unsigned int size = read_1(pData); + unsigned int sign = read_1(pData); + + VALUE num = INT2NUM(0); + VALUE tmp; + + unsigned char buf[size + 1]; + read_string_raw(buf, pData, size); + + int i; + for(i = 0; i < size; ++i) { + tmp = INT2FIX(*(buf + i)); + tmp = rb_funcall(tmp, rb_intern("<<"), 1, INT2NUM(i * 8)); + num = rb_funcall(num, rb_intern("+"), 1, tmp); + } + + if(sign) { + num = rb_funcall(num, rb_intern("*"), 1, INT2NUM(-1)); + } + + return num; +} + +VALUE read_large_bignum(unsigned char **pData) { + if(read_1(pData) != ERL_LARGE_BIGNUM) { + rb_raise(rb_eStandardError, "Invalid Type, not a small bignum"); + } + + unsigned int size = read_4(pData); + unsigned int sign = read_1(pData); + + VALUE num = INT2NUM(0); + VALUE tmp; + + unsigned char buf[size + 1]; + read_string_raw(buf, pData, size); + + int i; + for(i = 0; i < size; ++i) { + tmp = INT2FIX(*(buf + i)); + tmp = rb_funcall(tmp, rb_intern("<<"), 1, INT2NUM(i * 8)); + + num = rb_funcall(num, rb_intern("+"), 1, tmp); + } + + if(sign) { + num = rb_funcall(num, rb_intern("*"), 1, INT2NUM(-1)); + } + + return num; +} + +VALUE read_float(unsigned char **pData) { + if(read_1(pData) != ERL_FLOAT) { + rb_raise(rb_eStandardError, "Invalid Type, not a float"); + } + + unsigned char buf[32]; + read_string_raw(buf, pData, 31); + + VALUE rString = rb_str_new2((char *) buf); + + return rb_funcall(rString, rb_intern("to_f"), 0); +} + +VALUE read_nil(unsigned char **pData) { + if(read_1(pData) != ERL_NIL) { + rb_raise(rb_eStandardError, "Invalid Type, not a nil list"); + } + + VALUE list_class = rb_const_get(mBERT, rb_intern("List")); + return rb_funcall(list_class, rb_intern("new"), 0); +} + +// read_any_raw + +VALUE read_any_raw(unsigned char **pData) { + switch(peek_1(pData)) { + case ERL_SMALL_INT: + return read_small_int(pData); + break; + case ERL_INT: + return read_int(pData); + break; + case ERL_FLOAT: + return read_float(pData); + break; + case ERL_ATOM: + return read_atom(pData); + break; + case ERL_SMALL_TUPLE: + return read_small_tuple(pData); + break; + case ERL_LARGE_TUPLE: + return read_large_tuple(pData); + break; + case ERL_NIL: + return read_nil(pData); + break; + case ERL_STRING: + return read_string(pData); + break; + case ERL_LIST: + return read_list(pData); + break; + case ERL_BIN: + return read_bin(pData); + break; + case ERL_SMALL_BIGNUM: + return read_small_bignum(pData); + break; + case ERL_LARGE_BIGNUM: + return read_large_bignum(pData); + break; + } + return Qnil; +} + +VALUE method_decode(VALUE klass, VALUE rString) { + unsigned char *data = (unsigned char *) StringValuePtr(rString); + + unsigned char **pData = &data; + + // check protocol version + if(read_1(pData) != ERL_VERSION) { + rb_raise(rb_eStandardError, "Bad Magic"); + } + + return read_any_raw(pData); +} + +VALUE method_impl(VALUE klass) { + return rb_str_new("C", 2); +} + +void Init_decode() { + mBERT = rb_const_get(rb_cObject, rb_intern("BERT")); + cDecode = rb_define_class_under(mBERT, "Decode", rb_cObject); + rb_define_singleton_method(cDecode, "decode", method_decode, 1); + rb_define_singleton_method(cDecode, "impl", method_impl, 0); +} diff --git a/ext/bert/c/extconf.rb b/ext/bert/c/extconf.rb new file mode 100644 index 0000000..fbaed15 --- /dev/null +++ b/ext/bert/c/extconf.rb @@ -0,0 +1,11 @@ +# Loads mkmf which is used to make makefiles for Ruby extensions +require 'mkmf' + +# Give it a name +extension_name = 'decode' + +# The destination +dir_config(extension_name) + +# Do the work +create_makefile(extension_name) \ No newline at end of file diff --git a/lib/bert.rb b/lib/bert.rb index 7a172f4..4be2cd2 100644 --- a/lib/bert.rb +++ b/lib/bert.rb @@ -1,33 +1,24 @@ require 'rubygems' -require 'erlectricity' + +$:.unshift File.join(File.dirname(__FILE__), *%w[.. ext]) + +require 'bert/bert' +require 'bert/types' + +begin + # try to load the C extension + require 'bert/c/decode' +rescue LoadError + # fall back on the pure ruby version + require 'bert/decode' +end + +require 'bert/encode' require 'bert/encoder' require 'bert/decoder' -module BERT - def self.encode(ruby) - Encoder.encode(ruby) - end - - def self.decode(bert) - Decoder.decode(bert) - end - - def self.ebin(str) - bytes = [] - str.each_byte { |b| bytes << b.to_s } - "<<" + bytes.join(',') + ">>" - end -end - -module BERT - class Tuple < Array - def inspect - "t#{super}" - end - end -end - +# Global method for specifying that an array should be encoded as a tuple. def t BERT::Tuple end \ No newline at end of file diff --git a/lib/bert/bert.rb b/lib/bert/bert.rb new file mode 100644 index 0000000..6c52b0e --- /dev/null +++ b/lib/bert/bert.rb @@ -0,0 +1,27 @@ +module BERT + def self.encode(ruby) + Encoder.encode(ruby) + end + + def self.decode(bert) + Decoder.decode(bert) + end + + def self.ebin(str) + bytes = [] + str.each_byte { |b| bytes << b.to_s } + "<<" + bytes.join(',') + ">>" + end + + class List < Array + def inspect + "l#{super}" + end + end + + class Tuple < Array + def inspect + "t#{super}" + end + end +end \ No newline at end of file diff --git a/lib/bert/decode.rb b/lib/bert/decode.rb new file mode 100644 index 0000000..f8cf62c --- /dev/null +++ b/lib/bert/decode.rb @@ -0,0 +1,192 @@ +module BERT + class Decode + attr_accessor :in + include Types + + def self.impl + 'Ruby' + end + + def self.decode(string) + new(StringIO.new(string)).read_any + end + + def initialize(ins) + @in = ins + @peeked = "" + end + + def read_any + fail("Bad Magic") unless read_1 == MAGIC + read_any_raw + end + + def read_any_raw + case peek_1 + when ATOM then read_atom + when SMALL_INT then read_small_int + when INT then read_int + when SMALL_BIGNUM then read_small_bignum + when LARGE_BIGNUM then read_large_bignum + when FLOAT then read_float + when SMALL_TUPLE then read_small_tuple + when LARGE_TUPLE then read_large_tuple + when NIL then read_nil + when STRING then read_erl_string + when LIST then read_list + when BIN then read_bin + else + fail("Unknown term tag: #{peek_1}") + end + end + + def read(length) + if length < @peeked.length + result = @peeked[0...length] + @peeked = @peeked[length..-1] + length = 0 + else + result = @peeked + @peeked = '' + length -= result.length + end + + if length > 0 + result << @in.read(length) + end + result + end + + def peek(length) + if length <= @peeked.length + @peeked[0...length] + else + read_bytes = @in.read(length - @peeked.length) + @peeked << read_bytes if read_bytes + @peeked + end + end + + def peek_1 + peek(1).unpack("C").first + end + + def peek_2 + peek(2).unpack("n").first + end + + def read_1 + read(1).unpack("C").first + end + + def read_2 + read(2).unpack("n").first + end + + def read_4 + read(4).unpack("N").first + end + + def read_string(length) + read(length) + end + + def read_atom + fail("Invalid Type, not an atom") unless read_1 == ATOM + length = read_2 + a = read_string(length) + case a + when "" + Marshal.load("\004\b:\005") # Workaround for inability to do ''.to_sym + else + a.to_sym + end + end + + def read_small_int + fail("Invalid Type, not a small int") unless read_1 == SMALL_INT + read_1 + end + + def read_int + fail("Invalid Type, not an int") unless read_1 == INT + value = read_4 + negative = (value >> 31)[0] == 1 + value = (value - (1 << 32)) if negative + value = Fixnum.induced_from(value) + end + + def read_small_bignum + fail("Invalid Type, not a small bignum") unless read_1 == SMALL_BIGNUM + size = read_1 + sign = read_1 + bytes = read_string(size).unpack("C" * size) + added = bytes.zip((0..bytes.length).to_a).inject(0) do |result, byte_index| + byte, index = *byte_index + value = (byte * (256 ** index)) + sign != 0 ? (result - value) : (result + value) + end + Bignum.induced_from(added) + end + + def read_large_bignum + fail("Invalid Type, not a large bignum") unless read_1 == LARGE_BIGNUM + size = read_4 + sign = read_1 + bytes = read_string(size).unpack("C" * size) + added = bytes.zip((0..bytes.length).to_a).inject(0) do |result, byte_index| + byte, index = *byte_index + value = (byte * (256 ** index)) + sign != 0 ? (result - value) : (result + value) + end + Bignum.induced_from(added) + end + + def read_float + fail("Invalid Type, not a float") unless read_1 == FLOAT + string_value = read_string(31) + result = string_value.to_f + end + + def read_small_tuple + fail("Invalid Type, not a small tuple") unless read_1 == SMALL_TUPLE + arity = read_1 + (0...arity).map { |i| read_any_raw } + end + + def read_large_tuple + fail("Invalid Type, not a small tuple") unless read_1 == LARGE_TUPLE + arity = read_4 + (0...arity).map { |i| read_any_raw } + end + + def read_nil + fail("Invalid Type, not a nil list") unless read_1 == NIL + List.new([]) + end + + def read_erl_string + fail("Invalid Type, not an erlang string") unless read_1 == STRING + length = read_2 + List.new(read_string(length).unpack('C' * length)) + end + + def read_list + fail("Invalid Type, not an erlang list") unless read_1 == LIST + length = read_4 + list = (0...length).map { |i| read_any_raw } + read_1 + List.new(list) + end + + def read_bin + fail("Invalid Type, not an erlang binary") unless read_1 == BIN + length = read_4 + read_string(length) + end + + def fail(str) + raise str + end + end +end diff --git a/lib/bert/decoder.rb b/lib/bert/decoder.rb index a7d3da7..0e4d7a6 100644 --- a/lib/bert/decoder.rb +++ b/lib/bert/decoder.rb @@ -5,20 +5,17 @@ module BERT # # Returns a Ruby object def self.decode(bert) - simple_ruby = Erlectricity::Decoder.decode(bert) + simple_ruby = Decode.decode(bert) convert(simple_ruby) end - # Convert Erlectricity representation of BERT complex types into - # corresponding Ruby types. + # Convert simple Ruby form into complex Ruby form. # +item+ is the Ruby object to convert # # Returns the converted Ruby object def self.convert(item) case item - when TrueClass, FalseClass - item.to_s.to_sym - when Erl::List + when List item.map { |x| convert(x) } when Array if item[0] == :bert @@ -43,9 +40,9 @@ module BERT item[2].inject({}) do |acc, x| acc[convert(x[0])] = convert(x[1]); acc end - when TrueClass + when :true true - when FalseClass + when :false false when :time Time.at(item[2] * 1_000_000 + item[3], item[4]) diff --git a/lib/bert/encode.rb b/lib/bert/encode.rb new file mode 100644 index 0000000..7ff7866 --- /dev/null +++ b/lib/bert/encode.rb @@ -0,0 +1,142 @@ +module BERT + class Encode + include Types + + attr_accessor :out + + def initialize(out) + self.out = out + end + + def self.encode(data) + io = StringIO.new + self.new(io).write_any(data) + io.string + end + + def write_any obj + write_1 MAGIC + write_any_raw obj + end + + def write_any_raw obj + case obj + when Symbol then write_symbol(obj) + when Fixnum, Bignum then write_fixnum(obj) + when Float then write_float(obj) + when BERT::List then write_list(obj) + when Array then write_tuple(obj) + when String then write_binary(obj) + else + fail(obj) + end + end + + def write_1(byte) + out.write([byte].pack("C")) + end + + def write_2(short) + out.write([short].pack("n")) + end + + def write_4(long) + out.write([long].pack("N")) + end + + def write_string(string) + out.write(string) + end + + def write_boolean(bool) + write_symbol(bool.to_s.to_sym) + end + + def write_symbol(sym) + fail(sym) unless sym.is_a?(Symbol) + data = sym.to_s + write_1 ATOM + write_2 data.length + write_string data + end + + def write_fixnum(num) + if num >= 0 && num < 256 + write_1 SMALL_INT + write_1 num + elsif num <= MAX_INT && num >= MIN_INT + write_1 INT + write_4 num + else + write_bignum num + end + end + + def write_float(float) + write_1 FLOAT + write_string format("%15.15e", float).ljust(31, "\000") + end + + def write_bignum(num) + if num.is_a?(Bignum) + n = num.size + else + n = (num.to_s(2).size / 8.0).ceil + end + if n <= 256 + write_1 SMALL_BIGNUM + write_1 n + write_bignum_guts(num) + else + write_1 LARGE_BIGNUM + write_4 n + write_bignum_guts(num) + end + end + + def write_bignum_guts(num) + write_1 (num >= 0 ? 0 : 1) + num = num.abs + i = 0 + while (rem = (num >> i * 8) % (256)) != 0 + write_1 rem + i += 1 + end + end + + def write_tuple(data) + fail(data) unless data.is_a? Array + + if data.length < 256 + write_1 SMALL_TUPLE + write_1 data.length + else + write_1 LARGE_TUPLE + write_4 data.length + end + + data.each { |e| write_any_raw e } + end + + def write_list(data) + fail(data) unless data.is_a? Array + write_1 NIL and return if data.empty? + write_1 LIST + write_4 data.length + data.each{|e| write_any_raw e } + write_1 NIL + end + + def write_binary(data) + write_1 BIN + write_4 data.length + write_string data + end + + private + + def fail(obj) + raise "Cannot encode to erlang external format: #{obj.inspect}" + end + end +end diff --git a/lib/bert/encoder.rb b/lib/bert/encoder.rb index 8bc8ecc..25c4700 100644 --- a/lib/bert/encoder.rb +++ b/lib/bert/encoder.rb @@ -6,24 +6,23 @@ module BERT # Returns a BERT def self.encode(ruby) complex_ruby = convert(ruby) - Erlectricity::Encoder.encode(complex_ruby) + Encode.encode(complex_ruby) end - # Convert Ruby types into corresponding Erlectricity representation - # of BERT complex types. + # Convert complex Ruby form in simple Ruby form. # +item+ is the Ruby object to convert # # Returns the converted Ruby object def self.convert(item) case item when Hash - pairs = Erl::List[] + pairs = List[] item.each_pair { |k, v| pairs << [convert(k), convert(v)] } [:bert, :dict, pairs] when Tuple item.map { |x| convert(x) } when Array - Erl::List.new(item.map { |x| convert(x) }) + List.new(item.map { |x| convert(x) }) when nil [:bert, :nil] when TrueClass @@ -33,7 +32,7 @@ module BERT when Time [:bert, :time, item.to_i / 1_000_000, item.to_i % 1_000_000, item.usec] when Regexp - options = Erl::List[] + options = List[] options << :caseless if item.options & Regexp::IGNORECASE > 0 options << :extended if item.options & Regexp::EXTENDED > 0 options << :multiline if item.options & Regexp::MULTILINE > 0 diff --git a/lib/bert/types.rb b/lib/bert/types.rb new file mode 100644 index 0000000..09bcd00 --- /dev/null +++ b/lib/bert/types.rb @@ -0,0 +1,21 @@ +module BERT + module Types + SMALL_INT = 97 + INT = 98 + SMALL_BIGNUM = 110 + LARGE_BIGNUM = 111 + FLOAT = 99 + ATOM = 100 + SMALL_TUPLE = 104 + LARGE_TUPLE = 105 + NIL = 106 + STRING = 107 + LIST = 108 + BIN = 109 + FUN = 117 + NEW_FUN = 112 + MAGIC = 131 + MAX_INT = (1 << 27) -1 + MIN_INT = -(1 << 27) + end +end \ No newline at end of file diff --git a/test/decoder_test.rb b/test/decoder_test.rb index ddcff0f..aa3372d 100644 --- a/test/decoder_test.rb +++ b/test/decoder_test.rb @@ -33,13 +33,13 @@ class DecoderTest < Test::Unit::TestCase end should "convert true" do - before = [:bert, true] + before = [:bert, :true] after = true assert_equal after, BERT::Decoder.convert(before) end should "convert false" do - before = [:bert, false] + before = [:bert, :false] after = false assert_equal after, BERT::Decoder.convert(before) end diff --git a/test/encoder_test.rb b/test/encoder_test.rb index 4228bb3..39c9c87 100644 --- a/test/encoder_test.rb +++ b/test/encoder_test.rb @@ -27,7 +27,7 @@ class EncoderTest < Test::Unit::TestCase should "convert hash to tuple with array of tuples" do arr = BERT::Encoder.convert({:foo => 'bar'}) assert arr.is_a?(Array) - assert arr[2].is_a?(Erl::List) + assert arr[2].is_a?(BERT::List) assert arr[2][0].is_a?(Array) end @@ -38,13 +38,13 @@ class EncoderTest < Test::Unit::TestCase should "convert array to erl list" do list = BERT::Encoder.convert([1, 2]) - assert list.is_a?(Erl::List) + assert list.is_a?(BERT::List) end should "convert an array in a tuple" do arrtup = BERT::Encoder.convert(t[:foo, [1, 2]]) assert arrtup.is_a?(Array) - assert arrtup[1].is_a?(Erl::List) + assert arrtup[1].is_a?(BERT::List) end should "convert true" do diff --git a/test/test_helper.rb b/test/test_helper.rb index 596f3f1..70651c7 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -5,15 +5,4 @@ require 'shoulda' $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) $LOAD_PATH.unshift(File.dirname(__FILE__)) require 'bert' - -class Test::Unit::TestCase -end - -# So I can easily see which arrays are Erl::List -module Erl - class List - def inspect - "l#{super}" - end - end -end \ No newline at end of file +puts "Using #{BERT::Decode.impl} implementation." \ No newline at end of file