亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄 搜尋
Ruby用戶指南 3、開始 4、簡單的例子 5、字符串 6、正則表達(dá)式 7、數(shù)組 8、回到那些簡單的例子 9、流程控制 10、迭代器 11、面向?qū)ο笏季S 12、方法 13、類 14、繼承 15、重載方法 16、訪問控制 17、單態(tài)方法 18、模塊 19、過程對(duì)象 20、變量 21、全局變量 22、實(shí)變量 23、局部變量 24、類常量 25、異常處理:rescue 26、異常處理:ensure 27、存取器 28、對(duì)象的初始化 29、雜項(xiàng) RGSS入門教程 1、什么是RGSS 2、開始:最簡單的腳本 3、數(shù)據(jù)類型:數(shù)字 4、數(shù)據(jù)類型:常量與變量 5、數(shù)據(jù)類型:字符串 6、控制語句:條件分歧語句 7、控制語句:循環(huán) 8、函數(shù) 9、對(duì)象與類 10、顯示圖片 11、數(shù)組 12、哈希表(關(guān)聯(lián)數(shù)組) 13、類 14、數(shù)據(jù)庫 15、游戲?qū)ο?/a> 16、精靈的管理 17、窗口的管理 18、活動(dòng)指令 19、場景類 Programming Ruby的翻譯 Programming Ruby: The Pragmatic Programmer's Guide 前言 Roadmap Ruby.new 類,對(duì)象和變量 容器Containers,塊Blocks和迭代Iterators 標(biāo)準(zhǔn)類型 深入方法 表達(dá)式Expressions 異常,捕捉和拋出(已經(jīng)開始,by jellen) 模塊 基本輸入輸出 線程和進(jìn)程 當(dāng)遭遇挫折 Ruby和它的世界 Ruby和Web開發(fā) Ruby Tk Ruby 和微軟的 Windows 擴(kuò)展Ruby Ruby語言 (by jellen) 類和對(duì)象 (by jellen) Ruby安全 反射Reflection 內(nèi)建類和方法 標(biāo)準(zhǔn)庫 OO設(shè)計(jì) 網(wǎng)絡(luò)和Web庫 Windows支持 內(nèi)嵌文檔 交互式Ruby Shell 支持 Ruby參考手冊(cè) Ruby首頁 卷首語 Ruby的啟動(dòng) 環(huán)境變量 對(duì)象 執(zhí)行 結(jié)束時(shí)的相關(guān)處理 線程 安全模型 正則表達(dá)式 字句構(gòu)造 程序 變量和常數(shù) 字面值 操作符表達(dá)式 控制結(jié)構(gòu) 方法調(diào)用 類/方法的定義 內(nèi)部函數(shù) 內(nèi)部變量 內(nèi)部常數(shù) 內(nèi)部類/模塊/異常類 附加庫 Ruby變更記錄 ruby 1.6 特性 ruby 1.7 特性 Ruby術(shù)語集 Ruby的運(yùn)行平臺(tái) pack模板字符串 sprintf格式 Marshal格式 Ruby FAQ Ruby的陷阱
文字

Marshal格式

2002-04-04 草稿....

  • 以4.8(對(duì)應(yīng)于1.8)版的格式為藍(lán)本

    # 截至2003-05-02為止的格式版本如下所示
    p Marshal.Dump(Object.new).unpack("cc").join(".")
        => ruby 1.6.0 (2000-09-19) [i586-linux]
           "4.4"
        => ruby 1.6.1 (2000-09-27) [i586-linux]
           "4.4"
        => ruby 1.6.2 (2000-12-25) [i586-linux]
           "4.5"
        => ruby 1.6.3 (2001-03-19) [i586-linux]
           "4.5"
        => ruby 1.6.4 (2001-06-04) [i586-linux]
           "4.5"
        => ruby 1.6.5 (2001-09-19) [i586-linux]
           "4.6"
        => ruby 1.6.6 (2001-12-26) [i586-linux]
           "4.6"
        => ruby 1.6.7 (2002-03-01) [i586-linux]
           "4.6"
        => ruby 1.6.7 (2002-09-06) [i586-linux]
           "4.6"
        => ruby 1.7.3 (2002-09-06) [i586-linux]
           "4.7"
        => ruby 1.7.3 (2002-09-20) [i586-linux]
           "4.8"
        => ruby 1.8.0 (2003-08-03) [i586-linux]
           "4.8"
    
  • 本文兼顧了以前的版本,同時(shí)也指出了兼容性問題
  • 還提到了Ruby的Marshal中的BUG(?)
nil
true
false

分別是'0', 'T', 'F'

p Marshal.Dump(nil).unpack("x2 a*")
# => ["0"]

此時(shí),即使設(shè)置了實(shí)例變量也無法Dump。

class NilClass
  attr_accessor :foo
end
nil.foo = 1
p nil.foo                           # => 1
p Marshal.Dump(nil).unpack("x2 a*") # => ["0"]
Fixnum

在'i'之后是表示Fixnum的數(shù)據(jù)結(jié)構(gòu)。

以數(shù)值n為例,在表示數(shù)值部分的形式中(不僅限于Fixnum,在其它地方也是如此),保存著

形式 1:

n == 0:       0
0 < n < 123:  n + 5
-124 < n < 0: n - 5

這樣的數(shù)值(1 byte)。之所以加減5,是為了有別于下面的形式。

例:

p Marshal.Dump(-1).unpack("x2 a*") # => "i\372"
p Marshal.Dump(0).unpack("x2 a*")  # => "i\000"
p Marshal.Dump(1).unpack("x2 a*")  # => "i\006"
p Marshal.Dump(2).unpack("x2 a*")  # => "i\a"   ("i\007")

若數(shù)值N超出形式1的范圍時(shí),則有下面的形式。

形式 2:

| len | n1 | n2 | n3 | n4 |
 <-1-> <-     len       ->
 byte        bytes

len的值是-4 ~ -1, 1 ~ 4。這表示符號(hào)和后續(xù)的數(shù)據(jù)存在于n1 ~ n|len|。

# 舉個(gè)更好的例子...
def foo(len, n1, n2 = 0, n3 = 0, n4 = 0)

    case len
    when -3;           n4 = 255
    when -2;      n3 = n4 = 255
    when -1; n2 = n3 = n4 = 255
    end

    n = (0xffffff00 | n1) &
        (0xffff00ff | n2 * 0x100) &
        (0xff00ffff | n3 * 0x10000) &
        (0x00ffffff | n4 * 0x1000000)
    # p "%x" % n
    n = -((n ^ 0xffff_ffff) + 1) if len < 0
    n
end

p Marshal.Dump(-125).unpack("x2 acC*") # => ["i", -1, 131]
p foo(-1, 131)
p Marshal.Dump(-255).unpack("x2 acC*") # => ["i", -1, 1]
p foo(-1, 1)
p Marshal.Dump(-256).unpack("x2 acC*") # => ["i", -1, 0]
p foo(-1, 0)
p Marshal.Dump(-257).unpack("x2 acC*") # => ["i", -2, 255, 254]
p foo(-2, 255, 254)
p Marshal.Dump(124).unpack("x2 acC*") # => ["i", 1, 124]
p foo(1, 124)
p Marshal.Dump(256).unpack("x2 acC*") # => ["i", 2, 0, 1]
p foo(2, 0, 1)

即使設(shè)定了實(shí)例變量,也無法Dump。

class Fixnum
  attr_accessor :foo
end
99.foo = 1
p 99.foo                           # => 1
p 999.foo                          # => nil
p Marshal.Dump(99).unpack("x2 ac") # => ["i", 104]
instance of the user class

'C': String, Regexp, Array, Hash 的子類的實(shí)例變量

| 'C' | 類名(Symbol)的 Dump | 父類的實(shí)例的 Dump |

例 1:

class Foo < String # (or Regexp, Array, Hash)
end
p Marshal.Dump(Foo.new("foo")).unpack("x2 a a c a3 aca*")
# => ["C", ":", 8, "Foo", "\"", 8, "foo"]
                          ^^^ (or '/', '[', '{')

例 2: 有實(shí)例變量(請(qǐng)參考instance variable)

class Foo < String # (or Regexp, Array, Hash)
  def initialize(obj)
    @foo = obj
    super(obj)
  end
end
p Marshal.Dump(Foo.new("foo")).unpack("x2 a a a c a3 aca3 caca4 aca*")
# => ["I", "C", ":", 8, "Foo", "\"", 8, "foo", 6, ":", 9, "@foo", "\"", 8, "foo"]

除此以外,將變?yōu)?o'。這是因?yàn)閮?nèi)部結(jié)構(gòu)有所差異所致(請(qǐng)參考Object)

例:

class Foo
end
p Marshal.Dump(Foo.new).unpack("x2 a a c a*")
# => ["o", ":", 8, "Foo\000"]

'u'

若定義了_Dump、_load的話,就是'u'。因?yàn)闊o法Dump實(shí)例變量,所以必須使用_Dump/_load進(jìn)行處理。

| 'u' | 類名(Symbol)的 Dump | _Dump 的結(jié)果的長度(Fixnum形式) |
| _Dump 的返回值 |

例:

class Foo
  def self._load
  end
  def _Dump(obj)
    "hogehoge"
  end
end
p Marshal.Dump(Foo.new).unpack("x2 a aca3 c a*")
# => ["u", ":", 8, "Foo", 13, "hogehoge"]

'U' ruby 1.8 特性

若定義了marshal_Dump、marshal_load的話,就是'U'。因?yàn)闊o法Dump實(shí)例變量,所以必須使用marshal_Dump/marshal_load來處理。

| 'U' | 類名(Symbol)的 Dump | marshal_Dump 方法的返回值的 Dump |

例:

class Foo
  def marshal_Dump
    "hogehoge"
  end
  def marshal_load(obj)
  end
end
p Marshal.Dump(Foo.new).unpack("x2 a aca3 a c a*")

# => ["U", ":", 8, "Foo", "\"", 13, "hogehoge"]
Object

'o'

| 'o' | 類名(Symbol)的 Dump | 實(shí)例變量的數(shù)量(Fixnum形式) |
| 實(shí)例變量名(Symbol) 的Dump(1) | 值(1) |
          :
          :
| 實(shí)例變量名(Symbol) 的Dump(n) | 值(n) |

例 1:

p Marshal.Dump(Object.new).unpack("x2 a a c a*")
# => ["o", ":", 11, "Object\000"]

例 2: 有實(shí)例變量

class Foo
  def initialize
    @foo = "foo"
    @bar = "bar"
  end
end
p Marshal.Dump(Foo.new).unpack("x2 a a c a3 c aca4 aca3 aca4 aca3")
# => ["o", ":", 8, "Foo", 7,
      ":", 9, "@bar", "\"", 8, "bar",
      ":", 9, "@foo", "\"", 8, "foo"]
Float

'f'

| 'f' | 數(shù)串的長度(Fixnum形式) | "%.16g" 的字符串 |

例:

p Marshal.Dump(Math::PI).unpack("x2 a c a*")
# => ["f", 22, "3.141592653589793"]

p Marshal.Dump(0.0/0).unpack("x2 a c a*")  # => ["f", 8, "nan"]
p Marshal.Dump(1.0/0).unpack("x2 a c a*")  # => ["f", 8, "inf"]
p Marshal.Dump(-1.0/0).unpack("x2 a c a*") # => ["f", 9, "-inf"]
p Marshal.Dump(-0.0).unpack("x2 a c a*")   # => ["f", 9, "-0"]
Bignum

'l'

| 'l' | '+'/'-' | short的個(gè)數(shù)(Fixnum形式) | ... |

例:

p Marshal.Dump(2**32).unpack("x2 a a c a*")
# => ["l", "+", 8, "\000\000\000\000\001\000"]

# => ["l", "+", 8, "\000\000\001\000"]  <- BUG: ruby version 1.6.3
String

'"'

| '"' | 長度(Fixnum形式) | 字符串 |

例:

p Marshal.Dump("hogehoge").unpack("x2 a c a*")
# => ["\"", 13, "hogehoge"]
Regexp

'/'

| '/' | 長度(Fixnum形式) | source字符串 | 選項(xiàng) |

選項(xiàng)是 options的結(jié)果+漢字代碼的flag值。

例:

p Marshal.Dump(/(hoge)*/).unpack("x2 a c a7 c")
# => ["/", 12, "(hoge)*", 0]

p Marshal.Dump(/hogehoge/m).unpack("x2 a c a8 c")
# => ["/", 13, "hogehoge", 4]

p Marshal.Dump(/hogehoge/e).unpack("x2 a c a8 c")

# => ["/", 13, "hogehoge", 32]
Array

'['

| '[' | 元素?cái)?shù)(Fixnum形式) | 元素的 Dump | ... |

例:

p Marshal.Dump(["hogehoge", /hogehoge/]).unpack("x2 a c aca8 aca*")
# => ["[", 7, "\"", 13, "hogehoge", "/", 13, "hogehoge\000"]
Hash

'{'

| '{' | 元素?cái)?shù)(Fixnum形式) | 鍵的 Dump | 值的 Dump | ... |

例:

p Marshal.Dump({"hogehoge", /hogehoge/}).unpack("x2 a c aca8 aca*")
# => ["{", 6, "\"", 13, "hogehoge", "/", 13, "hogehoge\000"]
Hash with default value ( not Proc )

'}'

| '}' | 元素?cái)?shù)(Fixnum形式) | 鍵的 Dump | 值的 Dump | ... | 默認(rèn)值 |

例:

h = Hash.new(true)
h["foo"] = "bar"
p Marshal.Dump(h).unpack("x2 a c aca3 aca*")
# => ["}", 6, "\"", 8, "foo", "\"", 8, "barT"]

若某Hash的默認(rèn)對(duì)象是Proc的話,則無法Dump該Hash

h = Hash.new { }
Marshal.Dump(h)
=> -:2:in `Dump': cannot Dump hash with default proc (TypeError)
Struct

'S': 結(jié)構(gòu)體類的實(shí)例的Dump

| 'S' | 類名(Symbol) 的 Dump | 成員數(shù)量(Fixnum形式) |
| 成員名(Symbol) 的 Dump | 值 | ... |

例:

Struct.new("XXX", :foo, :bar)
p Marshal.Dump(Struct::XXX.new).unpack("x2 a ac a11 c aca3a aca3a")
# => ["S", ":", 16, "Struct::XXX", 7,
      ":", 8, "foo", "0",
      ":", 8, "bar", "0"]
Class/Module (old format)

'M'

| 'M' | 長度(Fixnum形式) | 模塊/類名 |

例: 因?yàn)橐呀?jīng)無法dump這種形式,所以使用load進(jìn)行說明。

class Mod
end
p Marshal.load([4,7, 'M', 3+5, 'Mod'].pack("ccaca*"))
# => Mod
Class/Module

'c', 'm'

| 'c'/'m' | 類名的長度(Fixnum 形式) | 類名 |

例:

class Foo
end
p Marshal.Dump(Foo).unpack("x2 a c a*") # => ["c", 8, "Foo"]

例 2: 無法dump類/模塊的實(shí)例變量

module Bar
  @bar = 1
end
p Bar.instance_eval { @bar }
Marshal.Dump(Bar, open("/tmp/foo", "w"))
# => 1

module Bar
end
p bar = Marshal.load(open("/tmp/foo"))
p bar.instance_eval { @bar }
# => nil

例 3: 無法dump類變量

module Baz
  @@baz = 1
  def self.baz
    @@baz
  end
end
p Baz.baz
Marshal.Dump(Baz, open("/tmp/foo", "w"))
# => 1

module Baz
  def self.baz
    @@baz
  end
end
p baz = Marshal.load(open("/tmp/foo"))
baz.baz
# => Baz
     -:3:in `baz': uninitialized class variable @@baz in Baz (NameError)
             from -:7
Symbol

':'

| ':' | 符號(hào)名的長度(Fixnum形式) | 符號(hào)名 |

例:

p Marshal.Dump(:foo).unpack("x2 a c a*")
# => [":", 8, "foo"]
Symbol (link)

';'

| ';' | 表明Symbol實(shí)際狀態(tài)的號(hào)碼(Fixnum形式) |

在相應(yīng)符號(hào)名已被dump/load時(shí)使用。該號(hào)碼是內(nèi)部管理的號(hào)碼。(在dump/load時(shí),會(huì)生成哈希表以便對(duì)Symbol進(jìn)行管理。它表示記錄位置)

例:

p Marshal.Dump([:foo, :foo]).unpack("x2 ac aca3 aC*")
# => ["[", 7, ":", 8, "foo", ";", 0]

p Marshal.Dump([:foo, :foo, :bar, :bar]).
    unpack("x2 ac aca3 aC aca3 aC*")
# => ["[", 9, ":", 8, "foo", ";", 0, ":", 8, "bar", ";", 6]
instance variable

'I': Object, Class, Module 的實(shí)例以外的對(duì)象

| 'I' | 對(duì)象的 Dump | 實(shí)例變量的數(shù)量(Fixnum形式) |
| 實(shí)例變量名(Symbol) 的Dump(1) | 值(1) |
          :
          :
| 實(shí)例變量名(Symbol) 的Dump(n) | 值(n) |

因?yàn)镺bject的實(shí)例中包含實(shí)例變量,所以會(huì)采用其他的形式進(jìn)行Dump(請(qǐng)參考Object)。該形式只針對(duì)Array 或 String 的實(shí)例。

例:

obj = String.new
obj.instance_eval { @foo = "bar" }
p Marshal.Dump(obj).unpack("x2 a ac c a c a4 aca*")
# => ["I", "\"", 0, 6, ":", 9, "@foo", "\"", 8, "bar"]

類或模塊(Class/Module的實(shí)例)不會(huì)dump實(shí)例變量的信息。(請(qǐng)參考Class/Module)

link

'@'

| '@' | 表明對(duì)象實(shí)際狀態(tài)的號(hào)碼(Fixnum形式 |

在相應(yīng)對(duì)象已被dump/load時(shí)使用。該號(hào)碼是內(nèi)部管理的號(hào)碼。(在dump/load時(shí),會(huì)生成哈希表以便對(duì)對(duì)象進(jìn)行管理。它表示記錄位置)

例:

obj = Object.new
p Marshal.Dump([obj, obj]).unpack("x2 ac aaca6c aca*")
# => ["[", 7, "o", ":", 11, "Object", 0, "@", 6, ""]

ary = []
ary.push ary
p Marshal.Dump(ary).unpack("x2 acac")

# => ["[", 6, "@", 0]

Marshal 的BUG

在ruby version 1.6中發(fā)現(xiàn)了下列BUG。括號(hào)()中列出的是正確的運(yùn)作方式(1.7的運(yùn)作方式)。

<= 1.6.7
  • 類的clone中的實(shí)例是可以Dump的,但卻不能加載(因?yàn)槭菬o名類的對(duì)象,所以無法Dump)
  • 當(dāng)某對(duì)象通過include/extend無名Module而定義了特殊方法后,仍可以Dump/加載該對(duì)象(若某對(duì)象include了無名模塊的話,則不能Dump該對(duì)象)
1.6.6, 1.6.7
  • 擁有實(shí)例變量的Array和String是可以Dump的,但卻不能加載(既能Dump,又能加載)
<= 1.6.5
  • 類的clone中的實(shí)例是可以Dump的,但卻不能正常加載。否則就會(huì)生成奇怪的對(duì)象(?)
  • 特殊類被dump成為普通類了(特殊類是無法Dump的)
  • 無名類是可以Dump的,但卻不能加載(無名類是無法Dump的)
<= 1.6.4
  • 模塊可以Dump卻不能加載(可以加載)
  • 無名模塊可以Dump卻不能加載(無名模塊是不能Dump的)
<= 1.6.3
  • dump Float時(shí),其保存精度偏低
<= 1.6.2
  • dump時(shí),無法保存正則表達(dá)式中/m, /x 選項(xiàng)的狀態(tài)
1.6.2, 1.6.3
  • 在1.6.2, 1.6.3中,Bignum可以Dump卻不能加載。按理說其他版本也會(huì)有這個(gè)BUG,但因?yàn)闆]有測試腳本,所以無法證實(shí)。
<= 1.6.1
  • dump時(shí)無法保存Range中的特定標(biāo)識(shí),該標(biāo)識(shí)表明該范圍中是否包含終點(diǎn)

下面就是測試腳本(請(qǐng)參考[RAA:RubyUnit])

# test for Marshal for ruby version 1.6
require 'rubyunit'

$version_dependent_behavior = true
# for test_userClass, test_userModule
module UserModule
  def foo
  end
end
class UserClass
  def foo
  end
end

class TestMarshal < RUNIT::TestCase

  def assert_no_Dumpable(obj)
    ex = assert_exception(TypeError) {
      begin
        # Marshal.Dump will cause TypeError or ArgumentError
        Marshal.Dump obj
      rescue ArgumentError
        case $!.message
        when /can't Dump anonymous/,
             /cannot Dump hash with default proc/
          raise TypeError
        else
          raise "unknown error"
        end
      end
    }
  end
  def assert_Dumpable_but_not_equal(obj)
    obj2 = Marshal.load(Marshal.Dump(obj))
    assert(obj != obj2)
    assert_equals(obj.type, obj2.type)
  end
  def assert_Dumpable_and_equal(obj)
    obj2 = Marshal.load(Marshal.Dump(obj))
    assert_equals(obj, obj2)
    assert_equals(obj.type, obj2.type)

    # check values of instance variable
    ivars = obj.instance_variables
    ivars2 = obj2.instance_variables
    assert_equals(ivars, ivars2)
    while ivars.size != 0
      assert_equals(obj.instance_eval(ivars.shift),
                    obj2.instance_eval(ivars2.shift))
    end
  end

  def test_Object
    assert_Dumpable_but_not_equal Object.new
  end

  # object with singleton method
  def test_Object_with_singleton_method
    obj = Object.new
    # On ruby version 1.6.0 - 1.6.2, cause parse error (nested method)
    class <<obj
      def foo
      end
    end

    # object has singleton method can't be Dumped
    assert_no_Dumpable obj
  end

  # object with singleton method (with named module)
  def test_Object_with_singleton_method2
    obj = Object.new
    # On ruby version 1.6.0 - 1.6.2, cause parse error (nested method)
    class <<obj
      include UserModule
    end

    # On ruby version 1.6.0 - 1.6.7, no consider the singleton
    # method with Mix-in.
    # On ruby version 1.7, Dumpable object which is extended by
    # named module.
    assert_Dumpable_but_not_equal obj
  end

  # object with singleton method (with anonymous module)
  def test_Object_with_singleton_method3
    obj = Object.new
    # On ruby version 1.6.0 - 1.6.2, cause parse error (nested method)
    class <<obj
      include Module.new
    end

    if $version_dependent_behavior and RUBY_VERSION <= "1.6.7"
      # On ruby version 1.6.0 - 1.6.7, no consider the singleton method with Mix-in.
      assert_Dumpable_but_not_equal obj
    else
      # object has singleton method (with anonymous module) can't be Dumped
      assert_no_Dumpable obj
    end
  end

  # singleton class
  def test_singletonClass
    obj = Object.new
    # On ruby version 1.6.0 - 1.6.2, cause parse error (nested method)
    singleton_class = class <<obj
                        def foo
                        end
                        self
                      end

    # singleton class can't be Dumped
    # On ruby version 1.6.0 - 1.6.5, singleton class be able to Dumped
    # as normal class.
    if $version_dependent_behavior and RUBY_VERSION <= "1.6.5"
      assert_equals(Object, Marshal.load(Marshal.Dump(singleton_class)))
    else
      assert_no_Dumpable singleton_class
    end
  end

  def test_Array
    assert_Dumpable_and_equal [1,"foo", :foo]
  end

  def test_Array_with_instance_variable
    ary = [1,"foo", :foo]
    ary.instance_eval{ @var = 1 }

    if $version_dependent_behavior and %w(1.6.6 1.6.7).member?(RUBY_VERSION)
      # On ruby version 1.6.6 - 1.6.7, Array(or String ...) has instance
      # variable is able to be Dumped, but can't load it.
      Dump = Marshal.Dump(ary)
      ex = assert_exception(ArgumentError) {
        Marshal.load(Dump)
      }
    else
      assert_Dumpable_and_equal ary
    end
  end

  def test_Binding
    assert_no_Dumpable binding
  end

  def test_Continuation
    assert_no_Dumpable callcc {|c| c}
  end

  def test_Data
    # assert_fail("")
  end

  def test_Exception
    assert_Dumpable_but_not_equal Exception.new("hoge")
  end

  def test_Dir
    assert_no_Dumpable Dir.open("/")
  end

  def test_FalseClass
    assert_Dumpable_and_equal false
  end

  def test_File__Stat
    assert_no_Dumpable File.stat("/")
  end

  def test_Hash
    assert_Dumpable_and_equal(1=>"1",2=>"2")

    # 1.7 feature.
    if $version_dependent_behavior and RUBY_VERSION >= '1.7.0'
      # On ruby version 1.7, hash with default Proc cannot be Dumped.
      # see [ruby-dev:15417]
      assert_no_Dumpable(Hash.new { })
    end
  end

  def test_IO
    assert_no_Dumpable IO.new(0)
  end

  def test_File
    assert_no_Dumpable File.open("/")
  end

  def test_MatchData
    assert_no_Dumpable(/foo/ =~ "foo" && $~)
  end

  def test_Method
    assert_no_Dumpable Object.method(:method)
  end

  def test_UnboundMethod
    assert_no_Dumpable Object.instance_method(:id)
  end

  def test_Module
    # On ruby version 1.6.0 - 1.6.4, loaded module is not a module.
    if $version_dependent_behavior and RUBY_VERSION <= '1.6.4'
      Dump = Marshal.Dump Enumerable
      ex = assert_exception(TypeError) {
        Marshal.load Dump
      }
      assert_matches(ex.message, /is not a module/)
    else
      assert_Dumpable_and_equal Enumerable
    end
  end

  def test_userModule
    # On ruby version 1.6.0 - 1.6.4, loaded module is not a module.
    if $version_dependent_behavior and RUBY_VERSION <= '1.6.4'
      # same as test_Module
    else
      # Note: this module must be defineed for Marshal.load.
      assert_Dumpable_and_equal(UserModule)
    end
  end

  def test_anonymousModule
    # On ruby version 1.6.0 - 1.6.4, anonymous class is able to be Dumped,
    # but loaded object is not identical.
    if $version_dependent_behavior and RUBY_VERSION <= '1.6.4'
      Dump = Marshal.Dump(Module.new)
      ex = assert_exception(ArgumentError) {
        Marshal.load Dump
      }
      assert_matches(ex.message, /can\'t retrieve anonymous class/)
    else
      assert_no_Dumpable Module.new
    end
  end

  def test_Class
    assert_Dumpable_and_equal Class
  end

  def test_userClass
    # Note: this class must be defineed for Marshal.load.
    assert_Dumpable_and_equal(UserClass)
  end
  def test_anonymousClass
    # On ruby version 1.6.0 - 1.6.5, anonymous class able to be Dumped,
    # but can't load it.
    if $version_dependent_behavior and RUBY_VERSION <= '1.6.5'
      Dump = Marshal.Dump(Class.new)
      ex = assert_exception(ArgumentError) {
        Marshal.load(Dump)
      }
      assert_matches(ex.message, /can\'t retrieve anonymous class/)
    else
      assert_no_Dumpable Class.new
    end
  end

  def test_clonedClass
    # On ruby version 1.6.0 - 1.6.7, instance of cloned class is able to
    # Dumped, but loaded object is not identical.
    # see [ruby-dev:14961]
    if $version_dependent_behavior
      if RUBY_VERSION <= '1.6.5'
        obj = String.clone.new("foo")
        Dump = Marshal.Dump(obj)
        obj2 = Marshal.load Dump
        assert(obj == obj2)
        assert(obj.type != obj2.type)
        assert(obj.type.inspect == obj2.type.inspect)
      elsif RUBY_VERSION <= '1.6.7'
        Dump = Marshal.Dump(String.clone.new("foo"))
        assert_exception(ArgumentError) {
          Marshal.load Dump
        }
      else
        assert_no_Dumpable String.clone.new("foo")
      end
    else
      # anonymous class can't be Dumped
      assert_no_Dumpable String.clone.new("foo")
    end
  end

  def test_Numeric
    # assert_fail("")
  end

  def test_Integer
    # assert_fail("")
  end

  def test_Fixnum
    assert_Dumpable_and_equal 100
  end

  def test_Bignum
    # derived from Rubicon
    assert_Dumpable_and_equal 123456789012345678901234567890
    assert_Dumpable_and_equal -123**99
    if $version_dependent_behavior and %w(1.6.2 1.6.3).member?(RUBY_VERSION)
      Dump = Marshal.Dump 2**32
      ex = assert_exception(ArgumentError) {
        Marshal.load(Dump)
      }
      assert_matches(ex.message, /marshal data too short/)
    else
      assert_Dumpable_and_equal 2**32
    end
  end

  def test_Float
    assert_Dumpable_and_equal 1.41421356

    # On ruby version 1.6.4, Dumped format changed from "%.12g" to "%.16g"
    if $version_dependent_behavior and RUBY_VERSION <= '1.6.3'
      assert_Dumpable_but_not_equal Math::PI
    else
      assert_Dumpable_and_equal Math::PI
    end
  end

  def test_Proc
    assert_no_Dumpable proc { }
  end

  def test_Process__Status
    assert_Dumpable_and_equal system("true") && $?
  end

  def test_Range
    # Range#== is changed from 1.6.2
    # On ruby version 1.6.0 - 1.6.1, Range.new(1,2) != Range.new(1,2)
    # assert_Dumpable_and_equal 1..2
    # assert_Dumpable_and_equal 1...2

    obj = Marshal.load(Marshal.Dump 1..2)
    assert_equals(1, obj.begin)
    assert_equals(2, obj.end)
    assert_equals(false, obj.exclude_end?)

    obj = Marshal.load(Marshal.Dump 1...2)
    assert_equals(1, obj.begin)
    assert_equals(2, obj.end)

    # On ruby version 1.6.0 - 1.6.1, the attribute exclude_end? is not saved.
    if $version_dependent_behavior and RUBY_VERSION <= '1.6.1'
      assert_equals(false, obj.exclude_end?)
    else
      assert_equals(true, obj.exclude_end?)
    end
  end

  def test_Regexp
    # this test is no consider the /foo/p
    assert_Dumpable_and_equal /foo/
    assert_Dumpable_and_equal /foo/i
    assert_Dumpable_and_equal /foo/m
    assert_Dumpable_and_equal /foo/x
    assert_Dumpable_and_equal /foo/e
    assert_Dumpable_and_equal /foo/s
    assert_Dumpable_and_equal /foo/u

    # On ruby version 1.6.0 - 1.6.2, Regexp#== is ignore the option.
    for obj in [/foo/, /foo/i, /foo/m, /foo/x, /foo/e, /foo/s, /foo/u]
      obj2 = Marshal.load(Marshal.Dump obj)

      if $version_dependent_behavior and RUBY_VERSION <= '1.6.2' and
          %w(/foo/m /foo/x).member?(obj.inspect)
        # On ruby version 1.6.0 - 1.6.2,
        # //m options is not saved.
        assert_equals('/foo/', obj2.inspect)
      else
        assert_equals(obj.inspect, obj2.inspect)
      end
    end
  end

  def test_String
    assert_Dumpable_and_equal "foo"
  end

  def test_Struct
    assert_Dumpable_and_equal Struct.new("Foo", :foo, :bar)

    Object.const_set('Foo', Struct.new(:foo, :bar))
    assert_Dumpable_and_equal Foo
  end

  def test_aStruct
    assert_Dumpable_and_equal Struct.new("Bar", :foo, :bar).new("foo", "bar")

    # see [ruby-dev:14961]
  end

  def test_Symbol
    assert_Dumpable_and_equal :foo
  end

  def test_Thread
    assert_no_Dumpable Thread.new { sleep }
  end

  def test_ThreadGroup
    assert_no_Dumpable ThreadGroup::Default
  end

  def test_Time
    assert_Dumpable_and_equal Time.now
    assert_Dumpable_and_equal Time.now.gmtime

    # time zone is not saved.
    assert_equals(false, Marshal.load(Marshal.Dump(Time.now)).utc?)
    assert_equals(false, Marshal.load(Marshal.Dump(Time.now.gmtime)).utc?)
  end

  def test_TrueClass
    assert_Dumpable_and_equal true
  end

  def test_NilClass
    assert_Dumpable_and_equal nil
  end
end


上一篇: 下一篇: