vagrant-kvm 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/.travis.yml +14 -0
- data/CHANGELOG.md +29 -0
- data/DEVELOPMENT.md +87 -0
- data/Gemfile +1 -0
- data/INSTALL.md +229 -0
- data/LICENSE +2 -1
- data/README.md +154 -63
- data/Rakefile +24 -1
- data/example_box/README.md +8 -8
- data/lib/vagrant-kvm/action.rb +47 -5
- data/lib/vagrant-kvm/action/boot.rb +0 -4
- data/lib/vagrant-kvm/action/clear_forwarded_ports.rb +53 -0
- data/lib/vagrant-kvm/action/forward_ports.rb +104 -0
- data/lib/vagrant-kvm/action/import.rb +97 -18
- data/lib/vagrant-kvm/action/init_storage_pool.rb +3 -1
- data/lib/vagrant-kvm/action/message_not_running.rb +16 -0
- data/lib/vagrant-kvm/action/network.rb +12 -13
- data/lib/vagrant-kvm/action/package_vagrantfile.rb +3 -1
- data/lib/vagrant-kvm/action/prepare_gui.rb +20 -0
- data/lib/vagrant-kvm/action/prepare_nfs_settings.rb +8 -16
- data/lib/vagrant-kvm/action/prepare_nfs_valid_ids.rb +17 -0
- data/lib/vagrant-kvm/action/reset_image_permission.rb +23 -0
- data/lib/vagrant-kvm/action/resume_network.rb +28 -0
- data/lib/vagrant-kvm/action/share_folders.rb +6 -5
- data/lib/vagrant-kvm/action/suspend.rb +8 -1
- data/lib/vagrant-kvm/config.rb +103 -2
- data/lib/vagrant-kvm/driver/driver.rb +321 -99
- data/lib/vagrant-kvm/errors.rb +18 -0
- data/lib/vagrant-kvm/provider.rb +4 -1
- data/lib/vagrant-kvm/util.rb +3 -0
- data/lib/vagrant-kvm/util/commands.rb +23 -0
- data/lib/vagrant-kvm/util/definition_attributes.rb +33 -0
- data/lib/vagrant-kvm/util/disk_info.rb +48 -0
- data/lib/vagrant-kvm/util/network_definition.rb +44 -84
- data/lib/vagrant-kvm/util/vm_definition.rb +91 -103
- data/lib/vagrant-kvm/version.rb +1 -1
- data/locales/en.yml +8 -0
- data/locales/ja.yml +14 -0
- data/spec/acceptance/vagrant-kvm_spec.rb +80 -0
- data/spec/fedora/10.virt.rules +10 -0
- data/spec/fedora/50-vagrant-libvirt-access.pkla +6 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/libvirt_helper.rb +37 -0
- data/spec/support/vagrant_kvm_helper.rb +39 -0
- data/spec/test_files/box.xml +74 -0
- data/spec/vagrant-kvm/config_spec.rb +56 -0
- data/spec/vagrant-kvm/driver/driver_spec.rb +36 -0
- data/spec/vagrant-kvm/errors_spec.rb +25 -0
- data/spec/vagrant-kvm/util/network_definition_spec.rb +60 -0
- data/spec/vagrant-kvm/util/vm_definition_spec.rb +76 -0
- data/templates/libvirt_domain.erb +34 -12
- data/templates/libvirt_network.erb +13 -0
- data/templates/package_Vagrantfile.erb +11 -0
- data/vagrant-kvm.gemspec +1 -2
- metadata +41 -42
data/lib/vagrant-kvm/version.rb
CHANGED
data/locales/en.yml
CHANGED
@@ -10,3 +10,11 @@ en:
|
|
10
10
|
kvm_invalid_version: |-
|
11
11
|
Invalid Kvm version detected: %{actual}, but a version %{required} is
|
12
12
|
required.
|
13
|
+
kvm_no_qemu_binary: |-
|
14
|
+
Executable binary of qemu could not be found. Please re-examine %{cause}.
|
15
|
+
kvm_fail_image_conversion: |-
|
16
|
+
Failed to convert image to specified format.
|
17
|
+
kvm_failed_command: |-
|
18
|
+
System command %{cmd} returned with error code %{res}.
|
19
|
+
kvm_bad_box_format: |-
|
20
|
+
Unsupported box format.
|
data/locales/ja.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
en:
|
2
|
+
vagrant_kvm:
|
3
|
+
test_message: |-
|
4
|
+
これはテストメッセージです。
|
5
|
+
errors:
|
6
|
+
kvm_no_connection: |-
|
7
|
+
KVMにLibvirt経由で接続できません。カーネルモジュールの
|
8
|
+
'kvm' 及び、'kvm-intel'か'kvm-amd'が正しくインストールされ、(debian/ubuntuの場合)あなたのユーザIDが
|
9
|
+
libvirtグループに属しているか、確認してください。
|
10
|
+
kvm_invalid_version: |-
|
11
|
+
不適切なKVMのバージョンが検出されました:バージョン %{actual} が検出されましたが、%{required}
|
12
|
+
が必要です。
|
13
|
+
kvm_no_qemu_binary: |-
|
14
|
+
Qemuの実行バイナリが見つかりません。%{cause}を確認してください。
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'vagrant-kvm' do
|
4
|
+
before(:all) do
|
5
|
+
create_vagrantfile
|
6
|
+
end
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
@old_domains = libvirt.domains.count
|
10
|
+
@old_pool_files = pool_files.count
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'up' do
|
14
|
+
before(:all) do
|
15
|
+
vagrant_up
|
16
|
+
end
|
17
|
+
|
18
|
+
after(:all) do
|
19
|
+
vagrant_destroy
|
20
|
+
end
|
21
|
+
|
22
|
+
it'creates new libvirt domain' do
|
23
|
+
(libvirt.domains.count - @old_domains).should == 1
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'starts created libvirt domain' do
|
27
|
+
expect(libvirt.domain).to be_active
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'creates disk image file' do
|
31
|
+
(pool_files.count - @old_pool_files).should == 1
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'creates new pool' do
|
35
|
+
expect(libvirt.storage_pools).to include('vagrant')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'creates new network' do
|
39
|
+
expect(libvirt.networks).to include('vagrant')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'down' do
|
44
|
+
before(:all) do
|
45
|
+
vagrant_up
|
46
|
+
vagrant_halt
|
47
|
+
end
|
48
|
+
|
49
|
+
after(:all) do
|
50
|
+
vagrant_destroy
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'shutdowns domain' do
|
54
|
+
expect(libvirt.domain).not_to be_active
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'destroy' do
|
59
|
+
before(:all) do
|
60
|
+
vagrant_up
|
61
|
+
vagrant_destroy
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'undefines domain' do
|
65
|
+
libvirt.domains.count.should == @old_domains
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'removes disk image file' do
|
69
|
+
expect(pool_files).to be_empty
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'does not undefine storage pool' do
|
73
|
+
expect(libvirt.storage_pools).to include('vagrant')
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'does not undefine new network' do
|
77
|
+
expect(libvirt.networks).to include('vagrant')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
polkit.addRule(function(action, subject) {
|
2
|
+
polkit.log("action=" + action);
|
3
|
+
polkit.log("subject=" + subject);
|
4
|
+
var now = new Date();
|
5
|
+
polkit.log("now=" + now)
|
6
|
+
if ((action.id == "org.libvirt.unix.manage" || action.id == "org.libvirt.unix.monitor") && subject.isInGroup("virt")) {
|
7
|
+
return polkit.Result.YES;
|
8
|
+
}
|
9
|
+
return null;
|
10
|
+
});
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'vagrant-kvm'
|
2
|
+
require 'support/libvirt_helper'
|
3
|
+
require 'support/vagrant_kvm_helper'
|
4
|
+
require 'pry'
|
5
|
+
|
6
|
+
def libvirt
|
7
|
+
@libvirt ||= LibvirtHelper.new
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec.configure do |spec|
|
11
|
+
spec.include VagrantKvmHelper
|
12
|
+
|
13
|
+
spec.before(:all) do
|
14
|
+
|
15
|
+
# make sure everything is run in tmp
|
16
|
+
Dir.chdir '/tmp'
|
17
|
+
end
|
18
|
+
|
19
|
+
spec.after(:all) do
|
20
|
+
libvirt.connection.close
|
21
|
+
end
|
22
|
+
|
23
|
+
at_exit do
|
24
|
+
File.delete('Vagrantfile') if File.exists?('Vagrantfile')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_file(path)
|
29
|
+
File.join(File.dirname(__FILE__), "test_files", path)
|
30
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'libvirt'
|
2
|
+
|
3
|
+
class LibvirtHelper
|
4
|
+
|
5
|
+
attr_reader :connection
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@connection = Libvirt.open('qemu:///system')
|
9
|
+
end
|
10
|
+
|
11
|
+
def domains
|
12
|
+
# list_domains returns IDs of active domains
|
13
|
+
# list_defined_domains returns names of inactive domains
|
14
|
+
@connection.list_domains + @connection.list_defined_domains
|
15
|
+
end
|
16
|
+
|
17
|
+
def domain
|
18
|
+
domain = domains.first
|
19
|
+
case domain
|
20
|
+
when Integer
|
21
|
+
@connection.lookup_domain_by_id(domain)
|
22
|
+
when String
|
23
|
+
@connection.lookup_domain_by_name(domain)
|
24
|
+
else
|
25
|
+
raise "Cannot find domain!"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def storage_pools
|
30
|
+
@connection.list_storage_pools
|
31
|
+
end
|
32
|
+
|
33
|
+
def networks
|
34
|
+
@connection.list_networks
|
35
|
+
end
|
36
|
+
|
37
|
+
end # LibvirtHelper
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module VagrantKvmHelper
|
2
|
+
|
3
|
+
def create_vagrantfile
|
4
|
+
File.open('Vagrantfile', 'w') do |file|
|
5
|
+
file.write <<-RUBY
|
6
|
+
Vagrant.require_plugin 'vagrant-kvm'
|
7
|
+
|
8
|
+
Vagrant.configure('2') do |config|
|
9
|
+
config.vm.box = 'vagrant-kvm-specs'
|
10
|
+
config.vm.network :private_network, ip: '192.168.50.2'
|
11
|
+
end
|
12
|
+
RUBY
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def vagrant_up
|
17
|
+
silent_exec('bundle exec vagrant up --provider=kvm')
|
18
|
+
end
|
19
|
+
|
20
|
+
def vagrant_halt
|
21
|
+
silent_exec('bundle exec vagrant halt')
|
22
|
+
end
|
23
|
+
|
24
|
+
def vagrant_destroy
|
25
|
+
silent_exec('bundle exec vagrant destroy -f')
|
26
|
+
end
|
27
|
+
|
28
|
+
def pool_files
|
29
|
+
Dir["/home/#{ENV['USER']}/.vagrant.d/tmp/storage-pool/*"]
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def silent_exec(cmd)
|
35
|
+
cmd << ' 2>&1' unless !!ENV['DEBUG']
|
36
|
+
`#{cmd}`
|
37
|
+
end
|
38
|
+
|
39
|
+
end # VagrantKvmHelper
|
@@ -0,0 +1,74 @@
|
|
1
|
+
<domain type='kvm' id='37'>
|
2
|
+
<name>winxp_base</name>
|
3
|
+
<memory unit='KiB'>524288</memory>
|
4
|
+
<currentMemory unit='KiB'>524288</currentMemory>
|
5
|
+
<vcpu placement='static'>1</vcpu>
|
6
|
+
<os>
|
7
|
+
<type arch='x86_64' machine='pc-1.2'>hvm</type>
|
8
|
+
<boot dev='hd'/>
|
9
|
+
</os>
|
10
|
+
<features>
|
11
|
+
<acpi/>
|
12
|
+
<apic/>
|
13
|
+
<pae/>
|
14
|
+
</features>
|
15
|
+
<clock offset='utc'/>
|
16
|
+
<on_poweroff>destroy</on_poweroff>
|
17
|
+
<on_reboot>restart</on_reboot>
|
18
|
+
<on_crash>restart</on_crash>
|
19
|
+
<devices>
|
20
|
+
<emulator>/usr/bin/kvm</emulator>
|
21
|
+
<disk type='file' device='disk'>
|
22
|
+
<driver name='qemu' type='qcow2'/>
|
23
|
+
<source file='winxp.qcow2'/>
|
24
|
+
<target dev='vda' bus='virtio'/>
|
25
|
+
<alias name='virtio-disk0'/>
|
26
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
|
27
|
+
</disk>
|
28
|
+
<controller type='usb' index='0'>
|
29
|
+
<alias name='usb0'/>
|
30
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
|
31
|
+
</controller>
|
32
|
+
<controller type='virtio-serial' index='0'>
|
33
|
+
<alias name='virtio-serial0'/>
|
34
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
|
35
|
+
</controller>
|
36
|
+
<interface type='network'>
|
37
|
+
<mac address='08:00:27:30:3b:ea'/>
|
38
|
+
<source network='vagrant'/>
|
39
|
+
<target dev='vnet0'/>
|
40
|
+
<model type='virtio'/>
|
41
|
+
<alias name='net0'/>
|
42
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
43
|
+
</interface>
|
44
|
+
<serial type='pty'>
|
45
|
+
<source path='/dev/pts/1'/>
|
46
|
+
<target port='0'/>
|
47
|
+
<alias name='serial0'/>
|
48
|
+
</serial>
|
49
|
+
<console type='pty' tty='/dev/pts/1'>
|
50
|
+
<source path='/dev/pts/1'/>
|
51
|
+
<target type='serial' port='0'/>
|
52
|
+
<alias name='serial0'/>
|
53
|
+
</console>
|
54
|
+
<input type='mouse' bus='ps2'/>
|
55
|
+
<graphics type='vnc' port='5900' autoport='no' listen='0.0.0.0'>
|
56
|
+
<listen type='address' address='0.0.0.0'/>
|
57
|
+
</graphics>
|
58
|
+
<sound model='ich6'>
|
59
|
+
<alias name='sound0'/>
|
60
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
61
|
+
</sound>
|
62
|
+
<video>
|
63
|
+
<model type='cirrus' vram='9216' heads='1'/>
|
64
|
+
<alias name='video0'/>
|
65
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
66
|
+
</video>
|
67
|
+
<memballoon model='virtio'>
|
68
|
+
<alias name='balloon0'/>
|
69
|
+
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
|
70
|
+
</memballoon>
|
71
|
+
</devices>
|
72
|
+
<seclabel type='none'/>
|
73
|
+
</domain>
|
74
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require "vagrant-kvm/config"
|
3
|
+
|
4
|
+
describe VagrantPlugins::ProviderKvm::Config do
|
5
|
+
describe "#machine_type" do
|
6
|
+
it "defaults to pc-1.2" do
|
7
|
+
should_default(:machine_type, "pc-1.2")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#vnc_port" do
|
12
|
+
it "defaults to -1" do
|
13
|
+
should_default(:vnc_port, -1)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#vnc_password" do
|
18
|
+
it "defaults to nil" do
|
19
|
+
should_default(:vnc_password, nil)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#network_model" do
|
24
|
+
it "defaults to 'virtio'" do
|
25
|
+
should_default(:network_model, 'virtio')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#video_model" do
|
30
|
+
it "defaults to 'virtio'" do
|
31
|
+
should_default(:video_model, 'cirrus')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#image_mode" do
|
36
|
+
it "sets image_backing to false if clone" do
|
37
|
+
subject.image_mode = 'clone'
|
38
|
+
subject.finalize!
|
39
|
+
subject.image_backing.should be_false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "sets image_backing to true if cow" do
|
43
|
+
subject.image_mode = 'cow'
|
44
|
+
subject.finalize!
|
45
|
+
subject.image_backing.should be_true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def should_default(field, default_value)
|
51
|
+
instance = described_class.new
|
52
|
+
instance.send(field).should == described_class::UNSET_VALUE
|
53
|
+
instance.finalize!
|
54
|
+
instance.send(field).should == default_value
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module ProviderKvm
|
5
|
+
module Driver
|
6
|
+
describe Driver do
|
7
|
+
let(:xml) { test_file "box.xml" }
|
8
|
+
let(:volume_name) { "" }
|
9
|
+
|
10
|
+
before do
|
11
|
+
described_class.any_instance.stub(:load_kvm_module!) { true }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#import" do
|
15
|
+
# FIXME All of these required stubs are a symptom of bad design in the
|
16
|
+
# driver class.
|
17
|
+
let(:volume) { double(path: "foo") }
|
18
|
+
let(:pool) { double(refresh: nil, lookup_volume_by_name: volume) }
|
19
|
+
let(:domain) { double(uuid: "abc") }
|
20
|
+
let(:conn) { double(version: 1000000000,
|
21
|
+
lookup_storage_pool_by_name: pool,
|
22
|
+
define_domain_xml: domain) }
|
23
|
+
subject do
|
24
|
+
described_class.new(nil, conn)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "does not raise exception" do
|
28
|
+
expect do
|
29
|
+
subject.import(xml, volume_name)
|
30
|
+
end.to_not raise_exception
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module VagrantPlugins::ProviderKvm::Errors
|
4
|
+
describe VagrantPlugins::ProviderKvm::Errors do
|
5
|
+
it "has translations for all errors" do
|
6
|
+
# Load the translations
|
7
|
+
VagrantPlugins::ProviderKvm::Plugin.setup_i18n
|
8
|
+
|
9
|
+
descendants = ObjectSpace.each_object(Class).select { |klass| klass < VagrantKVMError }
|
10
|
+
|
11
|
+
all_interpolations = {
|
12
|
+
required: "",
|
13
|
+
cause: "",
|
14
|
+
actual: "",
|
15
|
+
cmd: "",
|
16
|
+
res: "",
|
17
|
+
}
|
18
|
+
|
19
|
+
descendants.each do |klass|
|
20
|
+
msg = klass.new(all_interpolations).message
|
21
|
+
msg.should_not include("translation missing")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe VagrantPlugins::ProviderKvm::Util::NetworkDefinition do
|
4
|
+
let(:name) { 'vagrant' }
|
5
|
+
let(:xml) do
|
6
|
+
<<-XML
|
7
|
+
<network connections='1'>
|
8
|
+
<name>vagrant</name>
|
9
|
+
<uuid>0b9deaff-7665-d129-02e9-0f0a74054f87</uuid>
|
10
|
+
<forward mode='nat'/>
|
11
|
+
<bridge name='virbr1' stp='on' delay='0' />
|
12
|
+
<mac address='52:54:00:DE:20:0C'/>
|
13
|
+
<domain name='vagrant.local'/>
|
14
|
+
<ip address='192.168.123.1' netmask='255.255.255.0'>
|
15
|
+
<dhcp>
|
16
|
+
<range start='192.168.123.100' end='192.168.123.200' />
|
17
|
+
<host mac='00:69:0d:c2:52:f7' name='default' ip='192.168.123.10' />
|
18
|
+
</dhcp>
|
19
|
+
</ip>
|
20
|
+
</network>
|
21
|
+
XML
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:definition) { described_class.new(name, xml) }
|
25
|
+
subject { definition }
|
26
|
+
|
27
|
+
it "should set the attributes properly" do
|
28
|
+
subject.get(:forward).should == 'nat'
|
29
|
+
subject.get(:domain_name).should == 'vagrant.local'
|
30
|
+
subject.get(:base_ip).should == '192.168.123.1'
|
31
|
+
subject.get(:netmask).should == '255.255.255.0'
|
32
|
+
subject.get(:range).should == { :start => "192.168.123.100", :end => "192.168.123.200"}
|
33
|
+
subject.get(:hosts).should == [ {
|
34
|
+
:mac => '00:69:0d:c2:52:f7',
|
35
|
+
:name => 'default',
|
36
|
+
:ip => '192.168.123.10',
|
37
|
+
}]
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
describe "#==" do
|
42
|
+
it "returns true if and only if all attributes are equal" do
|
43
|
+
def1 = described_class.new(name, xml)
|
44
|
+
def2 = described_class.new(name, xml)
|
45
|
+
|
46
|
+
def1.should == def2
|
47
|
+
|
48
|
+
def2.set(:netmask, '255.255.0.0')
|
49
|
+
def1.should_not == def2
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#as_xml" do
|
54
|
+
it "should be symetrical" do
|
55
|
+
def1 = described_class.new(name, subject.as_xml)
|
56
|
+
subject.should == def1
|
57
|
+
subject.as_xml.should == def1.as_xml
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|