You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@deltacloud.apache.org by mf...@redhat.com on 2012/08/03 15:15:24 UTC

[PATCH core 1/8] CIMI: Converted rspec tests to minitest

From: Michal Fojtik <mf...@redhat.com>

* Added new Rake task: rake test:cimi:models
* All tests can be now run standalone

Signed-off-by: Michal fojtik <mf...@redhat.com>
---
 server/Rakefile                                    |   16 +-
 server/spec/cimi/data/machine.json                 |   43 ----
 server/spec/cimi/data/machine.xml                  |   33 ---
 server/spec/cimi/data/machine_admin.json           |   14 --
 server/spec/cimi/data/machine_admin.xml            |   10 -
 server/spec/cimi/data/machine_configuration.json   |   17 --
 server/spec/cimi/data/machine_configuration.xml    |   14 --
 server/spec/cimi/data/machine_image.json           |   14 --
 server/spec/cimi/data/machine_image.xml            |   11 -
 server/spec/cimi/data/machine_template.json        |   30 ---
 server/spec/cimi/data/machine_template.xml         |   24 --
 server/spec/cimi/data/volume.json                  |   16 --
 server/spec/cimi/data/volume.xml                   |   12 -
 server/spec/cimi/data/volume_configuration.json    |   16 --
 server/spec/cimi/data/volume_configuration.xml     |   12 -
 server/spec/cimi/data/volume_image.json            |   14 --
 server/spec/cimi/data/volume_image.xml             |   10 -
 server/spec/cimi/data/volume_template.json         |   14 --
 server/spec/cimi/data/volume_template.xml          |   10 -
 server/spec/cimi/model/machine_admin_spec.rb       |   28 ---
 .../spec/cimi/model/machine_configuration_spec.rb  |   27 ---
 server/spec/cimi/model/machine_image_spec.rb       |   29 ---
 server/spec/cimi/model/machine_spec.rb             |   27 ---
 server/spec/cimi/model/machine_template_spec.rb    |   27 ---
 server/spec/cimi/model/schema_spec.rb              |  241 -------------------
 .../spec/cimi/model/volume_configuration_spec.rb   |   30 ---
 server/spec/cimi/model/volume_image_spec.rb        |   29 ---
 server/spec/cimi/model/volume_spec.rb              |   28 ---
 server/spec/cimi/model/volume_template_spec.rb     |   28 ---
 server/spec/spec_helper.rb                         |  133 -----------
 server/tests/cimi/spec/cimi/data/machine.json      |   43 ++++
 server/tests/cimi/spec/cimi/data/machine.xml       |   33 +++
 .../tests/cimi/spec/cimi/data/machine_admin.json   |   14 ++
 server/tests/cimi/spec/cimi/data/machine_admin.xml |   10 +
 .../cimi/spec/cimi/data/machine_configuration.json |   17 ++
 .../cimi/spec/cimi/data/machine_configuration.xml  |   14 ++
 .../tests/cimi/spec/cimi/data/machine_image.json   |   14 ++
 server/tests/cimi/spec/cimi/data/machine_image.xml |   11 +
 .../cimi/spec/cimi/data/machine_template.json      |   30 +++
 .../tests/cimi/spec/cimi/data/machine_template.xml |   24 ++
 server/tests/cimi/spec/cimi/data/volume.json       |   16 ++
 server/tests/cimi/spec/cimi/data/volume.xml        |   12 +
 .../cimi/spec/cimi/data/volume_configuration.json  |   16 ++
 .../cimi/spec/cimi/data/volume_configuration.xml   |   12 +
 server/tests/cimi/spec/cimi/data/volume_image.json |   14 ++
 server/tests/cimi/spec/cimi/data/volume_image.xml  |   10 +
 .../tests/cimi/spec/cimi/data/volume_template.json |   14 ++
 .../tests/cimi/spec/cimi/data/volume_template.xml  |   10 +
 .../cimi/spec/cimi/model/machine_admin_spec.rb     |   32 +++
 .../spec/cimi/model/machine_configuration_spec.rb  |   30 +++
 .../cimi/spec/cimi/model/machine_image_spec.rb     |   31 +++
 server/tests/cimi/spec/cimi/model/machine_spec.rb  |   30 +++
 .../cimi/spec/cimi/model/machine_template_spec.rb  |   30 +++
 server/tests/cimi/spec/cimi/model/schema_spec.rb   |  243 ++++++++++++++++++++
 .../spec/cimi/model/volume_configuration_spec.rb   |   32 +++
 .../cimi/spec/cimi/model/volume_image_spec.rb      |   31 +++
 server/tests/cimi/spec/cimi/model/volume_spec.rb   |   30 +++
 .../cimi/spec/cimi/model/volume_template_spec.rb   |   30 +++
 server/tests/cimi/spec/spec_helper.rb              |  127 ++++++++++
 59 files changed, 974 insertions(+), 943 deletions(-)
 delete mode 100644 server/spec/cimi/data/machine.json
 delete mode 100644 server/spec/cimi/data/machine.xml
 delete mode 100644 server/spec/cimi/data/machine_admin.json
 delete mode 100644 server/spec/cimi/data/machine_admin.xml
 delete mode 100644 server/spec/cimi/data/machine_configuration.json
 delete mode 100644 server/spec/cimi/data/machine_configuration.xml
 delete mode 100644 server/spec/cimi/data/machine_image.json
 delete mode 100644 server/spec/cimi/data/machine_image.xml
 delete mode 100644 server/spec/cimi/data/machine_template.json
 delete mode 100644 server/spec/cimi/data/machine_template.xml
 delete mode 100644 server/spec/cimi/data/volume.json
 delete mode 100644 server/spec/cimi/data/volume.xml
 delete mode 100644 server/spec/cimi/data/volume_configuration.json
 delete mode 100644 server/spec/cimi/data/volume_configuration.xml
 delete mode 100644 server/spec/cimi/data/volume_image.json
 delete mode 100644 server/spec/cimi/data/volume_image.xml
 delete mode 100644 server/spec/cimi/data/volume_template.json
 delete mode 100644 server/spec/cimi/data/volume_template.xml
 delete mode 100644 server/spec/cimi/model/machine_admin_spec.rb
 delete mode 100644 server/spec/cimi/model/machine_configuration_spec.rb
 delete mode 100644 server/spec/cimi/model/machine_image_spec.rb
 delete mode 100644 server/spec/cimi/model/machine_spec.rb
 delete mode 100644 server/spec/cimi/model/machine_template_spec.rb
 delete mode 100644 server/spec/cimi/model/schema_spec.rb
 delete mode 100644 server/spec/cimi/model/volume_configuration_spec.rb
 delete mode 100644 server/spec/cimi/model/volume_image_spec.rb
 delete mode 100644 server/spec/cimi/model/volume_spec.rb
 delete mode 100644 server/spec/cimi/model/volume_template_spec.rb
 delete mode 100644 server/spec/spec_helper.rb
 create mode 100644 server/tests/cimi/spec/cimi/data/machine.json
 create mode 100644 server/tests/cimi/spec/cimi/data/machine.xml
 create mode 100644 server/tests/cimi/spec/cimi/data/machine_admin.json
 create mode 100644 server/tests/cimi/spec/cimi/data/machine_admin.xml
 create mode 100644 server/tests/cimi/spec/cimi/data/machine_configuration.json
 create mode 100644 server/tests/cimi/spec/cimi/data/machine_configuration.xml
 create mode 100644 server/tests/cimi/spec/cimi/data/machine_image.json
 create mode 100644 server/tests/cimi/spec/cimi/data/machine_image.xml
 create mode 100644 server/tests/cimi/spec/cimi/data/machine_template.json
 create mode 100644 server/tests/cimi/spec/cimi/data/machine_template.xml
 create mode 100644 server/tests/cimi/spec/cimi/data/volume.json
 create mode 100644 server/tests/cimi/spec/cimi/data/volume.xml
 create mode 100644 server/tests/cimi/spec/cimi/data/volume_configuration.json
 create mode 100644 server/tests/cimi/spec/cimi/data/volume_configuration.xml
 create mode 100644 server/tests/cimi/spec/cimi/data/volume_image.json
 create mode 100644 server/tests/cimi/spec/cimi/data/volume_image.xml
 create mode 100644 server/tests/cimi/spec/cimi/data/volume_template.json
 create mode 100644 server/tests/cimi/spec/cimi/data/volume_template.xml
 create mode 100644 server/tests/cimi/spec/cimi/model/machine_admin_spec.rb
 create mode 100644 server/tests/cimi/spec/cimi/model/machine_configuration_spec.rb
 create mode 100644 server/tests/cimi/spec/cimi/model/machine_image_spec.rb
 create mode 100644 server/tests/cimi/spec/cimi/model/machine_spec.rb
 create mode 100644 server/tests/cimi/spec/cimi/model/machine_template_spec.rb
 create mode 100644 server/tests/cimi/spec/cimi/model/schema_spec.rb
 create mode 100644 server/tests/cimi/spec/cimi/model/volume_configuration_spec.rb
 create mode 100644 server/tests/cimi/spec/cimi/model/volume_image_spec.rb
 create mode 100644 server/tests/cimi/spec/cimi/model/volume_spec.rb
 create mode 100644 server/tests/cimi/spec/cimi/model/volume_template_spec.rb
 create mode 100644 server/tests/cimi/spec/spec_helper.rb

diff --git a/server/Rakefile b/server/Rakefile
index 80589c4..ec3984b 100644
--- a/server/Rakefile
+++ b/server/Rakefile
@@ -127,6 +127,8 @@ task :test do
   Rake::Task["mock:fixtures:reset"].invoke
   puts "\n[ \033[1;37;mrake test:ec2\33[0m ]\n"
   Rake::Task["test:ec2"].invoke
+  puts "\n[ \033[1;37;mrake test:cimi:models\33[0m ]\n"
+  Rake::Task["test:cimi:models"].invoke
   DRIVERS.each do |driver|
     puts "\n[ \033[1;37;mrake drivers:#{driver}\33[0m ]\n"
     Rake::Task["test:drivers:#{driver}"].invoke
@@ -180,6 +182,16 @@ namespace :test do
     ]
   end
 
-end
-
+  namespace :cimi do
+    Rake::TestTask.new(:models) do |t|
+      t.ruby_opts << '-r./tests/cimi/spec/spec_helper.rb'    # Load SimpleCov when COVERAGE=1 is set
+      unless RUBY_VERSION < '1.9.0'
+        t.loader = :testrb
+      end
+      t.test_files = FileList[
+        'tests/cimi/spec/cimi/model/*spec.rb',        # CIMI frontend serialization API tests
+      ]
+    end
+  end
 
+end
diff --git a/server/spec/cimi/data/machine.json b/server/spec/cimi/data/machine.json
deleted file mode 100644
index 728ff5c..0000000
--- a/server/spec/cimi/data/machine.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{ "id": "http://cimi.example.org/machines/1",
-  "name": "machine1",
-  "description": "Machine one description",
-  "created": "2011-11-21",
-  "properties": { "owner_id": "mockuser" },
-  "state": "STARTED",
-  "cpu": "4",
-  "memory": { "quantity": "1", "units": "gibibyte" },
-  "disks" : [
-    { "capacity": { "quantity": "1", "units": "terabyte" } }
-  ],
-  "volumes": [{
-    "href": "http://cimi.example.org/volumes/1",
-    "attachmentPoint": "/dev/sda",
-    "protocol": "nfs"
-  }],
-  "networkInterfaces": [{
-    "vsp": { "href": "http://cimi.example.org/vsps/2" },
-    "hostname": "machine1.cimi.example.org",
-    "macAddress": "00:11:22:33:44:56",
-    "state": "UP",
-    "protocol": "TCP",
-    "allocation": "static",
-    "address": "192.168.0.18",
-    "defaultGateway": "192.168.0.1",
-    "dns": "192.168.0.1",
-    "maxTransmissionUnit": "1500"
-  }],
-  "meters": [
-    { "href": "http://cimi.example.org/meters/1" }
-  ],
-  "eventLog": { "href": "http://cimi.example.org/event_logs/1" },
-  "operations": [
-    { "rel": "edit",
-      "href": "http://cimi.example.org/machines/1/edit" },
-    { "rel": "delete",
-      "href": "http://cimi.example.org/machines/1/delete" },
-    { "rel": "http://www.dmtf.org/cimi/action/stop",
-      "href": "http://cimi.example.org/machines/1/stop" },
-    { "rel": "http://www.dmtf.org/cimi/action/restart",
-      "href": "http://cimi.example.org/machines/1/restart" }
-  ]
-}
diff --git a/server/spec/cimi/data/machine.xml b/server/spec/cimi/data/machine.xml
deleted file mode 100644
index 37b6582..0000000
--- a/server/spec/cimi/data/machine.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<Machine xmlns="http://www.dmtf.org/cimi">
-  <id>http://cimi.example.org/machines/1</id>
-  <name>machine1</name>
-  <description>Machine one description</description>
-  <created>2011-11-21</created>
-  <property name="owner_id">mockuser</property>
-  <cpu>4</cpu>
-  <memory quantity="1" units="gibibyte"/>
-  <state>STARTED</state>
-  <disk>
-    <capacity quantity="1" units="terabyte"/>
-  </disk>
-  <volume href="http://cimi.example.org/volumes/1"
-          attachmentPoint="/dev/sda" protocol="nfs" />
-  <networkInterface>
-    <vsp href="http://cimi.example.org/vsps/2"/>
-    <hostname>machine1.cimi.example.org</hostname>
-    <macAddress>00:11:22:33:44:56</macAddress>
-    <state>UP</state>
-    <protocol>TCP</protocol>
-    <allocation>static</allocation>
-    <address>192.168.0.18</address>
-    <defaultGateway>192.168.0.1</defaultGateway>
-    <dns>192.168.0.1</dns>
-    <maxTransmissionUnit>1500</maxTransmissionUnit>
-  </networkInterface>
-  <meter href="http://cimi.example.org/meters/1"/>
-  <eventLog href="http://cimi.example.org/event_logs/1"/>
-  <operation rel="edit" href="http://cimi.example.org/machines/1/edit"/>
-  <operation rel="delete" href="http://cimi.example.org/machines/1/delete"/>
-  <operation rel="http://www.dmtf.org/cimi/action/stop" href="http://cimi.example.org/machines/1/stop"/>
-  <operation rel="http://www.dmtf.org/cimi/action/restart" href="http://cimi.example.org/machines/1/restart"/>
-</Machine>
diff --git a/server/spec/cimi/data/machine_admin.json b/server/spec/cimi/data/machine_admin.json
deleted file mode 100644
index 35ab04b..0000000
--- a/server/spec/cimi/data/machine_admin.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "id": "http://cimi.example.org/machine_admins/1",
-  "name": "credentials1",
-  "description": "Machine Admin One",
-  "created": "2011-11-16",
-  "username": "mockuser",
-  "password": "mockpassword",
-  "operations": [
-  { "rel": "edit",
-    "href": "http://cimi.example.org/machine_admins/1/edit" },
-  { "rel": "delete",
-    "href": "http://cimi.example.org/machine_admins/1/delete" }
-  ]
-}
diff --git a/server/spec/cimi/data/machine_admin.xml b/server/spec/cimi/data/machine_admin.xml
deleted file mode 100644
index 1f395c3..0000000
--- a/server/spec/cimi/data/machine_admin.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<MachineAdmin xmlns="http://www.dmtf.org/cimi">
-  <id>http://cimi.example.org/machine_admins/1</id>
-  <name>credentials1</name>
-  <description>Machine Admin One</description>
-  <created>2011-11-16</created>
-  <username>mockuser</username>
-  <password>mockpassword</password>
-  <operation rel="edit" href="http://cimi.example.org/machine_admins/1/edit"/>
-  <operation rel="delete" href="http://cimi.example.org/machine_admins/1/delete"/>
-</MachineAdmin>
diff --git a/server/spec/cimi/data/machine_configuration.json b/server/spec/cimi/data/machine_configuration.json
deleted file mode 100644
index 40c77ad..0000000
--- a/server/spec/cimi/data/machine_configuration.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "id": "http://cimi.example.org/machine_configurations/1",
-  "name": "MachineConfiguration1",
-  "description": "Example MachineConfiguration One",
-  "created": "2011-11-14",
-  "cpu": "2",
-  "memory" : { "quantity": "1", "units": "gigabyte" },
-  "disks" : [
-    { "capacity": { "quantity": "1", "units": "terabyte" } }
-  ],
-  "properties": { "architecture": "i386" },
-  "operations": [
-    { "rel": "edit",
-      "href": "http://cimi.example.org/machine_configurations/1/edit" },
-    { "rel": "delete",
-      "href": "http://cimi.example.org/machine_configurations/1/delete" }]
-}
diff --git a/server/spec/cimi/data/machine_configuration.xml b/server/spec/cimi/data/machine_configuration.xml
deleted file mode 100644
index b3810a3..0000000
--- a/server/spec/cimi/data/machine_configuration.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<MachineConfiguration xmlns="http://www.dmtf.org/cimi">
-  <id>http://cimi.example.org/machine_configurations/1</id>
-  <name>MachineConfiguration1</name>
-  <description>Example MachineConfiguration One</description>
-  <created>2011-11-14</created>
-  <property name="architecture">i386</property>
-  <cpu>2</cpu>
-  <memory quantity="1" units="gigabyte"/>
-  <disk>
-    <capacity quantity="1" units="terabyte"/>
-  </disk>
-  <operation rel="edit" href="http://cimi.example.org/machine_configurations/1/edit"/>
-  <operation rel="delete" href="http://cimi.example.org/machine_configurations/1/delete"/>
-</MachineConfiguration>
diff --git a/server/spec/cimi/data/machine_image.json b/server/spec/cimi/data/machine_image.json
deleted file mode 100644
index cee0a52..0000000
--- a/server/spec/cimi/data/machine_image.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "id": "http://cimi.example.org/machine_images/1",
-  "name": "img1",
-  "description": "Machine Image One",
-  "created": "2011-11-14",
-  "imageLocation": { "href": "nfs://cimi.example.com/images/1.img" },
-  "properties": { "status": "BUILD", "locked": "true" },
-  "operations": [
-  { "rel": "edit",
-    "href": "http://cimi.example.org/machine_images/1/edit" },
-  { "rel": "delete",
-    "href": "http://cimi.example.org/machine_images/1/delete" }
-  ]
-}
diff --git a/server/spec/cimi/data/machine_image.xml b/server/spec/cimi/data/machine_image.xml
deleted file mode 100644
index e1d4452..0000000
--- a/server/spec/cimi/data/machine_image.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<MachineImage xmlns="http://www.dmtf.org/cimi">
-  <id>http://cimi.example.org/machine_images/1</id>
-  <name>img1</name>
-  <description>Machine Image One</description>
-  <created>2011-11-14</created>
-  <property name="status">BUILD</property>
-  <property name="locked">true</property>
-  <imageLocation href="nfs://cimi.example.com/images/1.img"/>
-  <operation rel="edit" href="http://cimi.example.org/machine_images/1/edit"/>
-  <operation rel="delete" href="http://cimi.example.org/machine_images/1/delete"/>
-</MachineImage>
diff --git a/server/spec/cimi/data/machine_template.json b/server/spec/cimi/data/machine_template.json
deleted file mode 100644
index 1be6592..0000000
--- a/server/spec/cimi/data/machine_template.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "id": "http://cimi.example.org/machine_templates/1",
-  "name": "My First Template",
-  "description": "A template for testing",
-  "created": "2011-11-01",
-  "machineConfig": { "href": "http://cimi.example.org/machine_configs/1" },
-  "machineImage": { "href": "http://cimi.example.org/machine_images/1" },
-  "volumes": [{
-    "href": "http://cimi.example.org/volumes/1",
-    "attachmentPoint": "/dev/sda",
-    "protocol": "nfs"
-  }],
-  "networkInterfaces": [{
-    "vsp": { "href": "http://cimi.example.org/vsps/1" },
-    "hostname": "host.cimi.example.org",
-    "macAddress": "00:11:22:33:44:55",
-    "state": "UP",
-    "protocol": "TCP",
-    "allocation": "static",
-    "address": "192.168.0.17",
-    "defaultGateway": "192.168.0.1",
-    "dns": "192.168.0.1",
-    "maxTransmissionUnit": "1500"
-  }],
-  "operations": [
-    { "rel": "edit",
-      "href": "http://cimi.example.org/machine_templates/1/edit" },
-    { "rel": "delete",
-      "href": "http://cimi.example.org/machine_templates/1/delete" }]
-}
diff --git a/server/spec/cimi/data/machine_template.xml b/server/spec/cimi/data/machine_template.xml
deleted file mode 100644
index 1386460..0000000
--- a/server/spec/cimi/data/machine_template.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<MachineTemplate xmlns="http://www.dmtf.org/cimi">
-  <id>http://cimi.example.org/machine_templates/1</id>
-  <name>My First Template</name>
-  <description>A template for testing</description>
-  <created>2011-11-01</created>
-  <machineConfig href="http://cimi.example.org/machine_configs/1"/>
-  <machineImage href="http://cimi.example.org/machine_images/1"/>
-  <volume href="http://cimi.example.org/volumes/1"
-          attachmentPoint="/dev/sda" protocol="nfs" />
-  <networkInterface>
-    <vsp href="http://cimi.example.org/vsps/1"/>
-    <hostname>host.cimi.example.org</hostname>
-    <macAddress>00:11:22:33:44:55</macAddress>
-    <state>UP</state>
-    <protocol>TCP</protocol>
-    <allocation>static</allocation>
-    <address>192.168.0.17</address>
-    <defaultGateway>192.168.0.1</defaultGateway>
-    <dns>192.168.0.1</dns>
-    <maxTransmissionUnit>1500</maxTransmissionUnit>
-  </networkInterface>
-  <operation rel="edit" href="http://cimi.example.org/machine_templates/1/edit"/>
-  <operation rel="delete" href="http://cimi.example.org/machine_templates/1/delete"/>
-</MachineTemplate>
diff --git a/server/spec/cimi/data/volume.json b/server/spec/cimi/data/volume.json
deleted file mode 100644
index e8364dd..0000000
--- a/server/spec/cimi/data/volume.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "id": "http://cimi.example.org/volumes/1",
-  "name": "volume1",
-  "description": "Volume One",
-  "created": "2011-11-17",
-  "capacity": { "quantity": "10", "units": "gigabyte" },
-  "bootable": "false",
-  "supportsSnapshots": "false",
-  "guestInterface": "NFS",
-  "operations": [
-    { "rel": "edit",
-      "href": "http://cimi.example.org/volumes/1/edit" },
-    { "rel": "delete",
-      "href": "http://cimi.example.org/volumes/1/delete" }
-  ]
-}
diff --git a/server/spec/cimi/data/volume.xml b/server/spec/cimi/data/volume.xml
deleted file mode 100644
index 65e6e06..0000000
--- a/server/spec/cimi/data/volume.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<Volume xmlns="http://www.dmtf.org/cimi">
-  <id>http://cimi.example.org/volumes/1</id>
-  <name>volume1</name>
-  <description>Volume One</description>
-  <created>2011-11-17</created>
-  <capacity quantity="10" units="gigabyte"/>
-  <bootable>false</bootable>
-  <supportsSnapshots>false</supportsSnapshots>
-  <guestInterface>NFS</guestInterface>
-  <operation rel="edit" href="http://cimi.example.org/volumes/1/edit"/>
-  <operation rel="delete" href="http://cimi.example.org/volumes/1/delete"/>
-</Volume>
diff --git a/server/spec/cimi/data/volume_configuration.json b/server/spec/cimi/data/volume_configuration.json
deleted file mode 100644
index 817e20c..0000000
--- a/server/spec/cimi/data/volume_configuration.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "id": "http://cimi.example.org/volume_configurations/1",
-  "name": "volume_config_1",
-  "description": "Volume Configuration One",
-  "created": "2011-11-21",
-  "format": "ext3",
-  "capacity": { "quantity": "10", "units": "gigabyte" },
-  "supportsSnapshots": "false",
-  "guestInterface": "NFS",
-  "operations": [
-    { "rel": "edit",
-      "href": "http://cimi.example.org/volume_configurations/1/edit" },
-    { "rel": "delete",
-      "href": "http://cimi.example.org/volume_configurations/1/delete" }
-  ]
-}
diff --git a/server/spec/cimi/data/volume_configuration.xml b/server/spec/cimi/data/volume_configuration.xml
deleted file mode 100644
index 120e8a6..0000000
--- a/server/spec/cimi/data/volume_configuration.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<VolumeConfiguration xmlns="http://www.dmtf.org/cimi">
-  <id>http://cimi.example.org/volume_configurations/1</id>
-  <name>volume_config_1</name>
-  <description>Volume Configuration One</description>
-  <created>2011-11-21</created>
-  <capacity quantity="10" units="gigabyte"/>
-  <supportsSnapshots>false</supportsSnapshots>
-  <guestInterface>NFS</guestInterface>
-  <format>ext3</format>
-  <operation rel="edit" href="http://cimi.example.org/volume_configurations/1/edit"/>
-  <operation rel="delete" href="http://cimi.example.org/volume_configurations/1/delete"/>
-</VolumeConfiguration>
diff --git a/server/spec/cimi/data/volume_image.json b/server/spec/cimi/data/volume_image.json
deleted file mode 100644
index 8c6ac04..0000000
--- a/server/spec/cimi/data/volume_image.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "id": "http://cimi.example.org/volume_images/1",
-  "name": "volume_image_1",
-  "description": "Volume Image One",
-  "created": "2011-11-21",
-  "bootable": "false",
-  "imageLocation":{ "href": "nfs://cimi.example.com/volume_images/vol_image_1.img" },
-  "operations": [
-    { "rel": "edit",
-      "href": "http://cimi.example.org/volume_images/1/edit" },
-    { "rel": "delete",
-      "href": "http://cimi.example.org/volume_images/1/delete" }
-  ]
-}
diff --git a/server/spec/cimi/data/volume_image.xml b/server/spec/cimi/data/volume_image.xml
deleted file mode 100644
index c6ba575..0000000
--- a/server/spec/cimi/data/volume_image.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<VolumeImage xmlns="http://www.dmtf.org/cimi">
-  <id>http://cimi.example.org/volume_images/1</id>
-  <name>volume_image_1</name>
-  <description>Volume Image One</description>
-  <created>2011-11-21</created>
-  <bootable>false</bootable>
-  <imageLocation href="nfs://cimi.example.com/volume_images/vol_image_1.img"/>
-  <operation rel="edit" href="http://cimi.example.org/volume_images/1/edit"/>
-  <operation rel="delete" href="http://cimi.example.org/volume_images/1/delete"/>
-</VolumeImage>
diff --git a/server/spec/cimi/data/volume_template.json b/server/spec/cimi/data/volume_template.json
deleted file mode 100644
index bddb5dc..0000000
--- a/server/spec/cimi/data/volume_template.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "id": "http://cimi.example.org/volume_templates/1",
-  "name": "volume_template_1",
-  "description": "Volume Template One",
-  "created": "2011-11-21",
-  "volumeConfig":{ "href": "http://cimi.example.com/volume_configurations/1" },
-  "volumeImage":{ "href": "http://cimi.example.com/volume_images/1" },
-  "operations": [
-    { "rel": "edit",
-      "href": "http://cimi.example.org/volume_templates/1/edit" },
-    { "rel": "delete",
-      "href": "http://cimi.example.org/volume_templates/1/delete" }
-  ]
-}
diff --git a/server/spec/cimi/data/volume_template.xml b/server/spec/cimi/data/volume_template.xml
deleted file mode 100644
index 47113b5..0000000
--- a/server/spec/cimi/data/volume_template.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<VolumeTemplate xmlns="http://www.dmtf.org/cimi">
-  <id>http://cimi.example.org/volume_templates/1</id>
-  <name>volume_template_1</name>
-  <description>Volume Template One</description>
-  <created>2011-11-21</created>
-  <volumeImage href="http://cimi.example.com/volume_images/1"/>
-  <volumeConfig href="http://cimi.example.com/volume_configurations/1"/>
-  <operation rel="edit" href="http://cimi.example.org/volume_templates/1/edit"/>
-  <operation rel="delete" href="http://cimi.example.org/volume_templates/1/delete"/>
-</VolumeTemplate>
diff --git a/server/spec/cimi/model/machine_admin_spec.rb b/server/spec/cimi/model/machine_admin_spec.rb
deleted file mode 100644
index 036a66d..0000000
--- a/server/spec/cimi/model/machine_admin_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-describe "MachineAdmin model" do
-
-  before(:all) do
-    @xml = IO::read(File::join(DATA_DIR, "machine_admin.xml"))
-    @json = IO::read(File::join(DATA_DIR, "machine_admin.json"))
-  end
-
-  it "can be constructed from XML and JSON" do
-    should_properly_serialize_model CIMI::Model::MachineAdmin, @xml, @json
-  end
-
-end
diff --git a/server/spec/cimi/model/machine_configuration_spec.rb b/server/spec/cimi/model/machine_configuration_spec.rb
deleted file mode 100644
index 2a57269..0000000
--- a/server/spec/cimi/model/machine_configuration_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-describe "MachineConfiguration model" do
-
-  before(:all) do
-    @xml = IO::read(File::join(DATA_DIR, "machine_configuration.xml"))
-    @json = IO::read(File::join(DATA_DIR, "machine_configuration.json"))
-  end
-
-  it "can be constructed from XML and JSON" do
-    should_properly_serialize_model CIMI::Model::MachineConfiguration, @xml, @json
-  end
-
-end
diff --git a/server/spec/cimi/model/machine_image_spec.rb b/server/spec/cimi/model/machine_image_spec.rb
deleted file mode 100644
index f284952..0000000
--- a/server/spec/cimi/model/machine_image_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-describe "MachineImage model" do
-
-  before(:all) do
-    @xml = IO::read(File::join(DATA_DIR, "machine_image.xml"))
-    @json = IO::read(File::join(DATA_DIR, "machine_image.json"))
-  end
-
-  it "can be constructed from XML and JSON" do
-    should_properly_serialize_model CIMI::Model::MachineImage, @xml, @json
-  end
-
-
-end
diff --git a/server/spec/cimi/model/machine_spec.rb b/server/spec/cimi/model/machine_spec.rb
deleted file mode 100644
index 59b5d6f..0000000
--- a/server/spec/cimi/model/machine_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-describe "Machine model" do
-
-  before(:all) do
-    @xml = IO::read(File::join(DATA_DIR, "machine.xml"))
-    @json = IO::read(File::join(DATA_DIR, "machine.json"))
-  end
-
-  it "can be constructed from XML and JSON" do
-    should_properly_serialize_model CIMI::Model::Machine, @xml, @json
-  end
-
-end
diff --git a/server/spec/cimi/model/machine_template_spec.rb b/server/spec/cimi/model/machine_template_spec.rb
deleted file mode 100644
index 3ca2c9a..0000000
--- a/server/spec/cimi/model/machine_template_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-describe "MachineTemplate model" do
-
-  before(:all) do
-    @xml = IO::read(File::join(DATA_DIR, "machine_template.xml"))
-    @json = IO::read(File::join(DATA_DIR, "machine_template.json"))
-  end
-
-  it "can be constructed from XML and JSON" do
-    should_properly_serialize_model CIMI::Model::MachineTemplate, @xml, @json
-  end
-
-end
diff --git a/server/spec/cimi/model/schema_spec.rb b/server/spec/cimi/model/schema_spec.rb
deleted file mode 100644
index 9fd4338..0000000
--- a/server/spec/cimi/model/schema_spec.rb
+++ /dev/null
@@ -1,241 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-describe "Schema" do
-  before(:each) do
-    @schema = CIMI::Model::Schema.new
-  end
-
-  it "does not allow adding attributes after being used for conversion" do
-    @schema.scalar(:before)
-    @schema.from_json({})
-    lambda { @schema.scalar(:after) }.should raise_error
-  end
-
-  describe "scalars" do
-    before(:each) do
-      @schema.scalar(:attr)
-      @schema.text(:camel_hump)
-
-      @schema.attribute_names.should == [:attr, :camel_hump]
-    end
-
-    let :sample_xml do
-      parse_xml("<camelHump>bumpy</camelHump>", :keep_root => true)
-    end
-
-    it "should camel case attribute names for JSON" do
-      obj = @schema.from_json("camelHump" => "bumpy")
-      obj.should_not be_nil
-      obj[:camel_hump].should == "bumpy"
-
-      json = @schema.to_json(obj)
-      json.should == { "camelHump" => "bumpy" }
-    end
-
-    it "should camel case attribute names for XML" do
-      obj = @schema.from_xml(sample_xml)
-
-      obj.should_not be_nil
-      obj[:camel_hump].should == "bumpy"
-
-      xml = @schema.to_xml(obj)
-
-      xml.should == { "camelHump" => [{ "content" => "bumpy" }] }
-    end
-
-    it "should allow aliasing the XML and JSON name" do
-      @schema.scalar :aliased, :xml_name => :xml, :json_name => :json
-      obj = @schema.from_xml({"aliased" => "no", "xml" => "yes"}, {})
-      obj[:aliased].should == "yes"
-
-      obj = @schema.from_json({"aliased" => "no", "json" => "yes"}, {})
-      obj[:aliased].should == "yes"
-    end
-  end
-
-  describe "hrefs" do
-    before(:each) do
-      @schema.href(:meter)
-    end
-
-    it "should extract the href attribute from XML" do
-      xml = parse_xml("<meter href='http://example.org/'/>")
-
-      obj = @schema.from_xml(xml)
-      check obj
-      @schema.to_xml(obj).should == xml
-    end
-
-    it "should extract the href attribute from JSON" do
-      json = { "meter" =>  { "href" => "http://example.org/" } }
-
-      obj = @schema.from_json(json)
-      check obj
-      @schema.to_json(obj).should == json
-    end
-
-    def check(obj)
-      obj.should_not be_nil
-      obj[:meter].href.should == 'http://example.org/'
-    end
-  end
-
-  describe "structs" do
-    before(:each) do
-      @schema.struct(:struct, :content => :scalar) do
-        scalar   :href
-      end
-      @schema.attribute_names.should == [:struct]
-    end
-
-    let(:sample_json) do
-      { "struct" => { "scalar" => "v1", "href" => "http://example.org/" } }
-    end
-
-    let (:sample_xml) do
-      parse_xml("<struct href='http://example.org/'>v1</struct>")
-    end
-
-    let (:sample_xml_no_href) do
-      parse_xml("<struct>v1</struct>")
-    end
-
-    describe "JSON conversion" do
-      it "should convert empty hash" do
-        model = @schema.from_json({ })
-        check_empty_struct model
-        @schema.to_json(model).should == {}
-      end
-
-      it "should convert empty body" do
-        model = @schema.from_json({ "struct" => { } })
-        check_empty_struct model
-        @schema.to_json(model).should == {}
-      end
-
-      it "should convert values" do
-        model = @schema.from_json(sample_json)
-        check_struct model
-        @schema.to_json(model).should == sample_json
-      end
-    end
-
-    describe "XML conversion" do
-      it "should convert empty hash" do
-        model = @schema.from_xml({ })
-        check_empty_struct model
-        @schema.to_xml(model).should == {}
-      end
-
-      it "should convert empty body" do
-        model = @schema.from_json({ "struct" => { } })
-        check_empty_struct model
-        @schema.to_xml(model).should == {}
-      end
-
-      it "should convert values" do
-        model = @schema.from_xml(sample_xml)
-        check_struct model
-        @schema.to_xml(model).should == sample_xml
-      end
-
-      it "should handle missing attributes" do
-        model = @schema.from_xml(sample_xml_no_href)
-        check_struct model, :nil_href => true
-        @schema.to_xml(model).should == sample_xml_no_href
-      end
-    end
-
-    def check_struct(obj, opts = {})
-      obj.should_not be_nil
-      obj[:struct].should_not be_nil
-      obj[:struct].scalar.should == "v1"
-      if opts[:nil_href]
-        obj[:struct].href.should be_nil
-      else
-        obj[:struct].href.should == "http://example.org/"
-      end
-    end
-
-    def check_empty_struct(obj)
-      obj.should_not be_nil
-      obj[:struct].should_not be_nil
-      obj[:struct].scalar.should be_nil
-      obj[:struct].href.should be_nil
-    end
-  end
-
-  describe "arrays" do
-    before(:each) do
-      @schema.array(:structs, :content => :scalar) do
-        scalar :href
-      end
-    end
-
-    let(:sample_json) do
-      { "structs" => [{ "scalar" => "v1", "href" => "http://example.org/1" },
-                      { "scalar" => "v2", "href" => "http://example.org/2" }] }
-    end
-
-    let (:sample_xml) do
-      parse_xml("<wrapper>
-  <struct href='http://example.org/1'>v1</struct>
-  <struct href='http://example.org/2'>v2</struct>
-</wrapper>", :keep_root => false)
-    end
-
-    it "should convert missing array from JSON" do
-      obj = @schema.from_json({})
-
-      obj.should_not be_nil
-      obj[:structs].should == []
-      @schema.to_json(obj).should == {}
-    end
-
-    it "should convert empty array from JSON" do
-      obj = @schema.from_json("structs" => [])
-
-      obj.should_not be_nil
-      obj[:structs].should == []
-      @schema.to_json(obj).should == {}
-    end
-
-    it "should convert arrays from JSON" do
-      obj = @schema.from_json(sample_json)
-
-      check_structs(obj)
-      @schema.to_json(obj).should == sample_json
-    end
-
-    it "should convert arrays from XML" do
-      obj = @schema.from_xml(sample_xml)
-
-      check_structs(obj)
-      @schema.to_xml(obj).should == sample_xml
-    end
-
-    def check_structs(obj)
-      obj.should_not be_nil
-      obj[:structs].size.should == 2
-      obj[:structs][0].scalar.should == "v1"
-      obj[:structs][0].href.should == "http://example.org/1"
-      obj[:structs][1].scalar.should == "v2"
-      obj[:structs][1].href.should == "http://example.org/2"
-    end
-  end
-
-end
diff --git a/server/spec/cimi/model/volume_configuration_spec.rb b/server/spec/cimi/model/volume_configuration_spec.rb
deleted file mode 100644
index 15be8ff..0000000
--- a/server/spec/cimi/model/volume_configuration_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-describe "Volume Configuration model" do
-
-  before(:all) do
-    @xml = IO::read(File::join(DATA_DIR, "volume_configuration.xml"))
-    @json = IO::read(File::join(DATA_DIR, "volume_configuration.json"))
-  end
-
-  it "can be constructed from XML and JSON" do
-    should_properly_serialize_model CIMI::Model::VolumeConfiguration, @xml, @json
-  end
-
-
-end
diff --git a/server/spec/cimi/model/volume_image_spec.rb b/server/spec/cimi/model/volume_image_spec.rb
deleted file mode 100644
index 99abdad..0000000
--- a/server/spec/cimi/model/volume_image_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-describe "Volume Image model" do
-
-  before(:all) do
-    @xml = IO::read(File::join(DATA_DIR, "volume_image.xml"))
-    @json = IO::read(File::join(DATA_DIR, "volume_image.json"))
-  end
-
-  it "can be constructed from XML and JSON" do
-    should_properly_serialize_model CIMI::Model::VolumeImage, @xml, @json
-  end
-
-
-end
diff --git a/server/spec/cimi/model/volume_spec.rb b/server/spec/cimi/model/volume_spec.rb
deleted file mode 100644
index d208e15..0000000
--- a/server/spec/cimi/model/volume_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-describe "Volume model" do
-
-  before(:all) do
-    @xml = IO::read(File::join(DATA_DIR, "volume.xml"))
-    @json = IO::read(File::join(DATA_DIR, "volume.json"))
-  end
-
-  it "can be constructed from XML and JSON" do
-    should_properly_serialize_model CIMI::Model::Volume, @xml, @json
-  end
-
-end
diff --git a/server/spec/cimi/model/volume_template_spec.rb b/server/spec/cimi/model/volume_template_spec.rb
deleted file mode 100644
index 12849e2..0000000
--- a/server/spec/cimi/model/volume_template_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-describe "Volume Template model" do
-
-  before(:all) do
-    @xml = IO::read(File::join(DATA_DIR, "volume_template.xml"))
-    @json = IO::read(File::join(DATA_DIR, "volume_template.json"))
-  end
-
-  it "can be constructed from XML and JSON" do
-    should_properly_serialize_model CIMI::Model::VolumeTemplate, @xml, @json
-  end
-
-end
diff --git a/server/spec/spec_helper.rb b/server/spec/spec_helper.rb
deleted file mode 100644
index 643873e..0000000
--- a/server/spec/spec_helper.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.  The
-# ASF licenses this file to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the
-# License.  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-require 'rubygems'
-require 'pp'
-require 'rspec/core'
-require 'xmlsimple'
-require 'require_relative'
-
-require_relative '../lib/deltacloud/core_ext.rb'
-require_relative '../lib/cimi/models.rb'
-
-DATA_DIR = File::join(File::expand_path(File::dirname(__FILE__)), 'cimi', 'data')
-
-def parse_xml(xml, opts = {})
-  opts[:force_content] = true
-  opts[:keep_root] = true unless opts.has_key?(:keep_root)
-  XmlSimple.xml_in(xml, opts)
-end
-
-class HashCmp
-  def initialize(exp, act)
-    @exp = exp
-    @act = act
-    @io = StringIO.new
-  end
-
-  def match?
-    @equal = true
-    compare_values(@exp, @act, [])
-    @equal
-  end
-
-  def errors
-    @io.string
-  end
-
-  private
-  def compare_values(exp, act, path)
-    if exp.is_a?(String)
-      mismatch("entries differ", exp, act, path) unless exp == act
-    elsif exp.is_a?(Array)
-      mismatch("expected array", exp, act, path) unless act.is_a?(Array)
-      unless act.size == exp.size
-        mismatch("different array lengths", exp, act, path)
-      end
-      name = path.pop
-      0.upto(exp.size-1) do |i|
-        compare_values(exp[i], act[i], path + [ "#{name}[#{i}]" ])
-      end
-    elsif exp.is_a?(Hash)
-      unless act.is_a?(Hash)
-        mismatch("expected Hash", exp, act, path)
-        return
-      end
-      unless (missing = exp.keys - act.keys).empty?
-        error "Missing key(s) at /#{path.join("/")}: #{missing.inspect}"
-      end
-      unless (excess = act.keys - exp.keys).empty?
-        error "Excess key(s) at /#{path.join("/")}: #{excess.inspect}"
-      end
-      (exp.keys - missing - excess).each do |k|
-        compare_values(exp[k], act[k], path + [ k ])
-      end
-    end
-  end
-
-  def mismatch(msg, exp, act, path)
-    error "#{msg}[#{fmt(path)}]: #{exp.inspect} != #{act.inspect}"
-  end
-
-  def error(msg)
-    @equal = false
-    @io.puts msg
-  end
-
-  def fmt(path)
-    "/#{path.join("/")}"
-  end
-end
-
-def should_properly_serialize_model(model_class, xml, json)
-  # Roundtrip in same format
-  model_class.from_xml(xml).should serialize_to xml, :fmt => :xml
-  model_class.from_json(json).should serialize_to json, :fmt => :json
-  # Roundtrip crossing format
-  model_class.from_xml(xml).should serialize_to json, :fmt => :json
-  model_class.from_json(json).should serialize_to xml, :fmt => :xml
-end
-
-RSpec::Matchers.define :serialize_to do |exp, opts|
-  match do |act|
-    matcher(exp, act, opts[:fmt]).match?
-  end
-
-  failure_message_for_should do |act|
-    m = matcher(exp, act, opts[:fmt])
-    m.match?
-    "#{opts[:fmt].to_s.upcase} documents do not match\n" + m.errors
-  end
-
-  def matcher(exp, act, fmt)
-    raise "missing format; use :fmt => [:xml || :json]" if fmt.nil?
-    exp, act = [exp, act].map { |x| convert(x, fmt) }
-    HashCmp.new(exp, act)
-  end
-
-  def convert(x, fmt)
-    if fmt == :json
-      x = x.to_json if x.is_a?(CIMI::Model::Base)
-      x = JSON.parse(x) if x.is_a?(String)
-    elsif fmt == :xml
-      x = x.to_xml if x.is_a?(CIMI::Model::Base)
-      x = parse_xml(x)  if x.is_a?(String)
-    else
-      raise "Invalid format #{fmt}"
-    end
-    x
-  end
-end
diff --git a/server/tests/cimi/spec/cimi/data/machine.json b/server/tests/cimi/spec/cimi/data/machine.json
new file mode 100644
index 0000000..728ff5c
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine.json
@@ -0,0 +1,43 @@
+{ "id": "http://cimi.example.org/machines/1",
+  "name": "machine1",
+  "description": "Machine one description",
+  "created": "2011-11-21",
+  "properties": { "owner_id": "mockuser" },
+  "state": "STARTED",
+  "cpu": "4",
+  "memory": { "quantity": "1", "units": "gibibyte" },
+  "disks" : [
+    { "capacity": { "quantity": "1", "units": "terabyte" } }
+  ],
+  "volumes": [{
+    "href": "http://cimi.example.org/volumes/1",
+    "attachmentPoint": "/dev/sda",
+    "protocol": "nfs"
+  }],
+  "networkInterfaces": [{
+    "vsp": { "href": "http://cimi.example.org/vsps/2" },
+    "hostname": "machine1.cimi.example.org",
+    "macAddress": "00:11:22:33:44:56",
+    "state": "UP",
+    "protocol": "TCP",
+    "allocation": "static",
+    "address": "192.168.0.18",
+    "defaultGateway": "192.168.0.1",
+    "dns": "192.168.0.1",
+    "maxTransmissionUnit": "1500"
+  }],
+  "meters": [
+    { "href": "http://cimi.example.org/meters/1" }
+  ],
+  "eventLog": { "href": "http://cimi.example.org/event_logs/1" },
+  "operations": [
+    { "rel": "edit",
+      "href": "http://cimi.example.org/machines/1/edit" },
+    { "rel": "delete",
+      "href": "http://cimi.example.org/machines/1/delete" },
+    { "rel": "http://www.dmtf.org/cimi/action/stop",
+      "href": "http://cimi.example.org/machines/1/stop" },
+    { "rel": "http://www.dmtf.org/cimi/action/restart",
+      "href": "http://cimi.example.org/machines/1/restart" }
+  ]
+}
diff --git a/server/tests/cimi/spec/cimi/data/machine.xml b/server/tests/cimi/spec/cimi/data/machine.xml
new file mode 100644
index 0000000..37b6582
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine.xml
@@ -0,0 +1,33 @@
+<Machine xmlns="http://www.dmtf.org/cimi">
+  <id>http://cimi.example.org/machines/1</id>
+  <name>machine1</name>
+  <description>Machine one description</description>
+  <created>2011-11-21</created>
+  <property name="owner_id">mockuser</property>
+  <cpu>4</cpu>
+  <memory quantity="1" units="gibibyte"/>
+  <state>STARTED</state>
+  <disk>
+    <capacity quantity="1" units="terabyte"/>
+  </disk>
+  <volume href="http://cimi.example.org/volumes/1"
+          attachmentPoint="/dev/sda" protocol="nfs" />
+  <networkInterface>
+    <vsp href="http://cimi.example.org/vsps/2"/>
+    <hostname>machine1.cimi.example.org</hostname>
+    <macAddress>00:11:22:33:44:56</macAddress>
+    <state>UP</state>
+    <protocol>TCP</protocol>
+    <allocation>static</allocation>
+    <address>192.168.0.18</address>
+    <defaultGateway>192.168.0.1</defaultGateway>
+    <dns>192.168.0.1</dns>
+    <maxTransmissionUnit>1500</maxTransmissionUnit>
+  </networkInterface>
+  <meter href="http://cimi.example.org/meters/1"/>
+  <eventLog href="http://cimi.example.org/event_logs/1"/>
+  <operation rel="edit" href="http://cimi.example.org/machines/1/edit"/>
+  <operation rel="delete" href="http://cimi.example.org/machines/1/delete"/>
+  <operation rel="http://www.dmtf.org/cimi/action/stop" href="http://cimi.example.org/machines/1/stop"/>
+  <operation rel="http://www.dmtf.org/cimi/action/restart" href="http://cimi.example.org/machines/1/restart"/>
+</Machine>
diff --git a/server/tests/cimi/spec/cimi/data/machine_admin.json b/server/tests/cimi/spec/cimi/data/machine_admin.json
new file mode 100644
index 0000000..35ab04b
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine_admin.json
@@ -0,0 +1,14 @@
+{
+  "id": "http://cimi.example.org/machine_admins/1",
+  "name": "credentials1",
+  "description": "Machine Admin One",
+  "created": "2011-11-16",
+  "username": "mockuser",
+  "password": "mockpassword",
+  "operations": [
+  { "rel": "edit",
+    "href": "http://cimi.example.org/machine_admins/1/edit" },
+  { "rel": "delete",
+    "href": "http://cimi.example.org/machine_admins/1/delete" }
+  ]
+}
diff --git a/server/tests/cimi/spec/cimi/data/machine_admin.xml b/server/tests/cimi/spec/cimi/data/machine_admin.xml
new file mode 100644
index 0000000..1f395c3
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine_admin.xml
@@ -0,0 +1,10 @@
+<MachineAdmin xmlns="http://www.dmtf.org/cimi">
+  <id>http://cimi.example.org/machine_admins/1</id>
+  <name>credentials1</name>
+  <description>Machine Admin One</description>
+  <created>2011-11-16</created>
+  <username>mockuser</username>
+  <password>mockpassword</password>
+  <operation rel="edit" href="http://cimi.example.org/machine_admins/1/edit"/>
+  <operation rel="delete" href="http://cimi.example.org/machine_admins/1/delete"/>
+</MachineAdmin>
diff --git a/server/tests/cimi/spec/cimi/data/machine_configuration.json b/server/tests/cimi/spec/cimi/data/machine_configuration.json
new file mode 100644
index 0000000..40c77ad
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine_configuration.json
@@ -0,0 +1,17 @@
+{
+  "id": "http://cimi.example.org/machine_configurations/1",
+  "name": "MachineConfiguration1",
+  "description": "Example MachineConfiguration One",
+  "created": "2011-11-14",
+  "cpu": "2",
+  "memory" : { "quantity": "1", "units": "gigabyte" },
+  "disks" : [
+    { "capacity": { "quantity": "1", "units": "terabyte" } }
+  ],
+  "properties": { "architecture": "i386" },
+  "operations": [
+    { "rel": "edit",
+      "href": "http://cimi.example.org/machine_configurations/1/edit" },
+    { "rel": "delete",
+      "href": "http://cimi.example.org/machine_configurations/1/delete" }]
+}
diff --git a/server/tests/cimi/spec/cimi/data/machine_configuration.xml b/server/tests/cimi/spec/cimi/data/machine_configuration.xml
new file mode 100644
index 0000000..b3810a3
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine_configuration.xml
@@ -0,0 +1,14 @@
+<MachineConfiguration xmlns="http://www.dmtf.org/cimi">
+  <id>http://cimi.example.org/machine_configurations/1</id>
+  <name>MachineConfiguration1</name>
+  <description>Example MachineConfiguration One</description>
+  <created>2011-11-14</created>
+  <property name="architecture">i386</property>
+  <cpu>2</cpu>
+  <memory quantity="1" units="gigabyte"/>
+  <disk>
+    <capacity quantity="1" units="terabyte"/>
+  </disk>
+  <operation rel="edit" href="http://cimi.example.org/machine_configurations/1/edit"/>
+  <operation rel="delete" href="http://cimi.example.org/machine_configurations/1/delete"/>
+</MachineConfiguration>
diff --git a/server/tests/cimi/spec/cimi/data/machine_image.json b/server/tests/cimi/spec/cimi/data/machine_image.json
new file mode 100644
index 0000000..cee0a52
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine_image.json
@@ -0,0 +1,14 @@
+{
+  "id": "http://cimi.example.org/machine_images/1",
+  "name": "img1",
+  "description": "Machine Image One",
+  "created": "2011-11-14",
+  "imageLocation": { "href": "nfs://cimi.example.com/images/1.img" },
+  "properties": { "status": "BUILD", "locked": "true" },
+  "operations": [
+  { "rel": "edit",
+    "href": "http://cimi.example.org/machine_images/1/edit" },
+  { "rel": "delete",
+    "href": "http://cimi.example.org/machine_images/1/delete" }
+  ]
+}
diff --git a/server/tests/cimi/spec/cimi/data/machine_image.xml b/server/tests/cimi/spec/cimi/data/machine_image.xml
new file mode 100644
index 0000000..e1d4452
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine_image.xml
@@ -0,0 +1,11 @@
+<MachineImage xmlns="http://www.dmtf.org/cimi">
+  <id>http://cimi.example.org/machine_images/1</id>
+  <name>img1</name>
+  <description>Machine Image One</description>
+  <created>2011-11-14</created>
+  <property name="status">BUILD</property>
+  <property name="locked">true</property>
+  <imageLocation href="nfs://cimi.example.com/images/1.img"/>
+  <operation rel="edit" href="http://cimi.example.org/machine_images/1/edit"/>
+  <operation rel="delete" href="http://cimi.example.org/machine_images/1/delete"/>
+</MachineImage>
diff --git a/server/tests/cimi/spec/cimi/data/machine_template.json b/server/tests/cimi/spec/cimi/data/machine_template.json
new file mode 100644
index 0000000..1be6592
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine_template.json
@@ -0,0 +1,30 @@
+{
+  "id": "http://cimi.example.org/machine_templates/1",
+  "name": "My First Template",
+  "description": "A template for testing",
+  "created": "2011-11-01",
+  "machineConfig": { "href": "http://cimi.example.org/machine_configs/1" },
+  "machineImage": { "href": "http://cimi.example.org/machine_images/1" },
+  "volumes": [{
+    "href": "http://cimi.example.org/volumes/1",
+    "attachmentPoint": "/dev/sda",
+    "protocol": "nfs"
+  }],
+  "networkInterfaces": [{
+    "vsp": { "href": "http://cimi.example.org/vsps/1" },
+    "hostname": "host.cimi.example.org",
+    "macAddress": "00:11:22:33:44:55",
+    "state": "UP",
+    "protocol": "TCP",
+    "allocation": "static",
+    "address": "192.168.0.17",
+    "defaultGateway": "192.168.0.1",
+    "dns": "192.168.0.1",
+    "maxTransmissionUnit": "1500"
+  }],
+  "operations": [
+    { "rel": "edit",
+      "href": "http://cimi.example.org/machine_templates/1/edit" },
+    { "rel": "delete",
+      "href": "http://cimi.example.org/machine_templates/1/delete" }]
+}
diff --git a/server/tests/cimi/spec/cimi/data/machine_template.xml b/server/tests/cimi/spec/cimi/data/machine_template.xml
new file mode 100644
index 0000000..1386460
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/machine_template.xml
@@ -0,0 +1,24 @@
+<MachineTemplate xmlns="http://www.dmtf.org/cimi">
+  <id>http://cimi.example.org/machine_templates/1</id>
+  <name>My First Template</name>
+  <description>A template for testing</description>
+  <created>2011-11-01</created>
+  <machineConfig href="http://cimi.example.org/machine_configs/1"/>
+  <machineImage href="http://cimi.example.org/machine_images/1"/>
+  <volume href="http://cimi.example.org/volumes/1"
+          attachmentPoint="/dev/sda" protocol="nfs" />
+  <networkInterface>
+    <vsp href="http://cimi.example.org/vsps/1"/>
+    <hostname>host.cimi.example.org</hostname>
+    <macAddress>00:11:22:33:44:55</macAddress>
+    <state>UP</state>
+    <protocol>TCP</protocol>
+    <allocation>static</allocation>
+    <address>192.168.0.17</address>
+    <defaultGateway>192.168.0.1</defaultGateway>
+    <dns>192.168.0.1</dns>
+    <maxTransmissionUnit>1500</maxTransmissionUnit>
+  </networkInterface>
+  <operation rel="edit" href="http://cimi.example.org/machine_templates/1/edit"/>
+  <operation rel="delete" href="http://cimi.example.org/machine_templates/1/delete"/>
+</MachineTemplate>
diff --git a/server/tests/cimi/spec/cimi/data/volume.json b/server/tests/cimi/spec/cimi/data/volume.json
new file mode 100644
index 0000000..e8364dd
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/volume.json
@@ -0,0 +1,16 @@
+{
+  "id": "http://cimi.example.org/volumes/1",
+  "name": "volume1",
+  "description": "Volume One",
+  "created": "2011-11-17",
+  "capacity": { "quantity": "10", "units": "gigabyte" },
+  "bootable": "false",
+  "supportsSnapshots": "false",
+  "guestInterface": "NFS",
+  "operations": [
+    { "rel": "edit",
+      "href": "http://cimi.example.org/volumes/1/edit" },
+    { "rel": "delete",
+      "href": "http://cimi.example.org/volumes/1/delete" }
+  ]
+}
diff --git a/server/tests/cimi/spec/cimi/data/volume.xml b/server/tests/cimi/spec/cimi/data/volume.xml
new file mode 100644
index 0000000..65e6e06
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/volume.xml
@@ -0,0 +1,12 @@
+<Volume xmlns="http://www.dmtf.org/cimi">
+  <id>http://cimi.example.org/volumes/1</id>
+  <name>volume1</name>
+  <description>Volume One</description>
+  <created>2011-11-17</created>
+  <capacity quantity="10" units="gigabyte"/>
+  <bootable>false</bootable>
+  <supportsSnapshots>false</supportsSnapshots>
+  <guestInterface>NFS</guestInterface>
+  <operation rel="edit" href="http://cimi.example.org/volumes/1/edit"/>
+  <operation rel="delete" href="http://cimi.example.org/volumes/1/delete"/>
+</Volume>
diff --git a/server/tests/cimi/spec/cimi/data/volume_configuration.json b/server/tests/cimi/spec/cimi/data/volume_configuration.json
new file mode 100644
index 0000000..817e20c
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/volume_configuration.json
@@ -0,0 +1,16 @@
+{
+  "id": "http://cimi.example.org/volume_configurations/1",
+  "name": "volume_config_1",
+  "description": "Volume Configuration One",
+  "created": "2011-11-21",
+  "format": "ext3",
+  "capacity": { "quantity": "10", "units": "gigabyte" },
+  "supportsSnapshots": "false",
+  "guestInterface": "NFS",
+  "operations": [
+    { "rel": "edit",
+      "href": "http://cimi.example.org/volume_configurations/1/edit" },
+    { "rel": "delete",
+      "href": "http://cimi.example.org/volume_configurations/1/delete" }
+  ]
+}
diff --git a/server/tests/cimi/spec/cimi/data/volume_configuration.xml b/server/tests/cimi/spec/cimi/data/volume_configuration.xml
new file mode 100644
index 0000000..120e8a6
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/volume_configuration.xml
@@ -0,0 +1,12 @@
+<VolumeConfiguration xmlns="http://www.dmtf.org/cimi">
+  <id>http://cimi.example.org/volume_configurations/1</id>
+  <name>volume_config_1</name>
+  <description>Volume Configuration One</description>
+  <created>2011-11-21</created>
+  <capacity quantity="10" units="gigabyte"/>
+  <supportsSnapshots>false</supportsSnapshots>
+  <guestInterface>NFS</guestInterface>
+  <format>ext3</format>
+  <operation rel="edit" href="http://cimi.example.org/volume_configurations/1/edit"/>
+  <operation rel="delete" href="http://cimi.example.org/volume_configurations/1/delete"/>
+</VolumeConfiguration>
diff --git a/server/tests/cimi/spec/cimi/data/volume_image.json b/server/tests/cimi/spec/cimi/data/volume_image.json
new file mode 100644
index 0000000..8c6ac04
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/volume_image.json
@@ -0,0 +1,14 @@
+{
+  "id": "http://cimi.example.org/volume_images/1",
+  "name": "volume_image_1",
+  "description": "Volume Image One",
+  "created": "2011-11-21",
+  "bootable": "false",
+  "imageLocation":{ "href": "nfs://cimi.example.com/volume_images/vol_image_1.img" },
+  "operations": [
+    { "rel": "edit",
+      "href": "http://cimi.example.org/volume_images/1/edit" },
+    { "rel": "delete",
+      "href": "http://cimi.example.org/volume_images/1/delete" }
+  ]
+}
diff --git a/server/tests/cimi/spec/cimi/data/volume_image.xml b/server/tests/cimi/spec/cimi/data/volume_image.xml
new file mode 100644
index 0000000..c6ba575
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/volume_image.xml
@@ -0,0 +1,10 @@
+<VolumeImage xmlns="http://www.dmtf.org/cimi">
+  <id>http://cimi.example.org/volume_images/1</id>
+  <name>volume_image_1</name>
+  <description>Volume Image One</description>
+  <created>2011-11-21</created>
+  <bootable>false</bootable>
+  <imageLocation href="nfs://cimi.example.com/volume_images/vol_image_1.img"/>
+  <operation rel="edit" href="http://cimi.example.org/volume_images/1/edit"/>
+  <operation rel="delete" href="http://cimi.example.org/volume_images/1/delete"/>
+</VolumeImage>
diff --git a/server/tests/cimi/spec/cimi/data/volume_template.json b/server/tests/cimi/spec/cimi/data/volume_template.json
new file mode 100644
index 0000000..bddb5dc
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/volume_template.json
@@ -0,0 +1,14 @@
+{
+  "id": "http://cimi.example.org/volume_templates/1",
+  "name": "volume_template_1",
+  "description": "Volume Template One",
+  "created": "2011-11-21",
+  "volumeConfig":{ "href": "http://cimi.example.com/volume_configurations/1" },
+  "volumeImage":{ "href": "http://cimi.example.com/volume_images/1" },
+  "operations": [
+    { "rel": "edit",
+      "href": "http://cimi.example.org/volume_templates/1/edit" },
+    { "rel": "delete",
+      "href": "http://cimi.example.org/volume_templates/1/delete" }
+  ]
+}
diff --git a/server/tests/cimi/spec/cimi/data/volume_template.xml b/server/tests/cimi/spec/cimi/data/volume_template.xml
new file mode 100644
index 0000000..47113b5
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/volume_template.xml
@@ -0,0 +1,10 @@
+<VolumeTemplate xmlns="http://www.dmtf.org/cimi">
+  <id>http://cimi.example.org/volume_templates/1</id>
+  <name>volume_template_1</name>
+  <description>Volume Template One</description>
+  <created>2011-11-21</created>
+  <volumeImage href="http://cimi.example.com/volume_images/1"/>
+  <volumeConfig href="http://cimi.example.com/volume_configurations/1"/>
+  <operation rel="edit" href="http://cimi.example.org/volume_templates/1/edit"/>
+  <operation rel="delete" href="http://cimi.example.org/volume_templates/1/delete"/>
+</VolumeTemplate>
diff --git a/server/tests/cimi/spec/cimi/model/machine_admin_spec.rb b/server/tests/cimi/spec/cimi/model/machine_admin_spec.rb
new file mode 100644
index 0000000..132272d
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/machine_admin_spec.rb
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+if require 'minitest/autorun'
+  require_relative '../../spec_helper.rb'
+end
+
+describe "MachineAdmin model" do
+
+  before do
+    @xml = IO::read(File::join(DATA_DIR, "machine_admin.xml"))
+    @json = IO::read(File::join(DATA_DIR, "machine_admin.json"))
+  end
+
+  it "can be constructed from XML and JSON" do
+    should_properly_serialize_model CIMI::Model::MachineAdmin, @xml, @json
+  end
+
+end
diff --git a/server/tests/cimi/spec/cimi/model/machine_configuration_spec.rb b/server/tests/cimi/spec/cimi/model/machine_configuration_spec.rb
new file mode 100644
index 0000000..e59fcc0
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/machine_configuration_spec.rb
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+describe "MachineConfiguration model" do
+
+  before do
+    @xml = IO::read(File::join(DATA_DIR, "machine_configuration.xml"))
+    @json = IO::read(File::join(DATA_DIR, "machine_configuration.json"))
+  end
+
+  it "can be constructed from XML and JSON" do
+    should_properly_serialize_model CIMI::Model::MachineConfiguration, @xml, @json
+  end
+
+end
diff --git a/server/tests/cimi/spec/cimi/model/machine_image_spec.rb b/server/tests/cimi/spec/cimi/model/machine_image_spec.rb
new file mode 100644
index 0000000..7eef29a
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/machine_image_spec.rb
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+describe "MachineImage model" do
+
+  before do
+    @xml = IO::read(File::join(DATA_DIR, "machine_image.xml"))
+    @json = IO::read(File::join(DATA_DIR, "machine_image.json"))
+  end
+
+  it "can be constructed from XML and JSON" do
+    should_properly_serialize_model CIMI::Model::MachineImage, @xml, @json
+  end
+
+
+end
diff --git a/server/tests/cimi/spec/cimi/model/machine_spec.rb b/server/tests/cimi/spec/cimi/model/machine_spec.rb
new file mode 100644
index 0000000..b10ecfe
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/machine_spec.rb
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+describe "Machine model" do
+
+  before do
+    @xml = IO::read(File::join(DATA_DIR, "machine.xml"))
+    @json = IO::read(File::join(DATA_DIR, "machine.json"))
+  end
+
+  it "can be constructed from XML and JSON" do
+    should_properly_serialize_model CIMI::Model::Machine, @xml, @json
+  end
+
+end
diff --git a/server/tests/cimi/spec/cimi/model/machine_template_spec.rb b/server/tests/cimi/spec/cimi/model/machine_template_spec.rb
new file mode 100644
index 0000000..7210c92
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/machine_template_spec.rb
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+describe "MachineTemplate model" do
+
+  before do
+    @xml = IO::read(File::join(DATA_DIR, "machine_template.xml"))
+    @json = IO::read(File::join(DATA_DIR, "machine_template.json"))
+  end
+
+  it "can be constructed from XML and JSON" do
+    should_properly_serialize_model CIMI::Model::MachineTemplate, @xml, @json
+  end
+
+end
diff --git a/server/tests/cimi/spec/cimi/model/schema_spec.rb b/server/tests/cimi/spec/cimi/model/schema_spec.rb
new file mode 100644
index 0000000..c5619b1
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/schema_spec.rb
@@ -0,0 +1,243 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+describe "Schema" do
+  before do
+    @schema = CIMI::Model::Schema.new
+  end
+
+  it "does not allow adding attributes after being used for conversion" do
+    @schema.scalar(:before)
+    @schema.from_json({})
+    lambda { @schema.scalar(:after) }.must_raise RuntimeError, 'The schema has already been used to convert objects'
+  end
+
+  describe "scalars" do
+    before(:each) do
+      @schema.scalar(:attr)
+      @schema.text(:camel_hump)
+
+      @schema.attribute_names.must_equal [:attr, :camel_hump]
+    end
+
+    let :sample_xml do
+      parse_xml("<camelHump>bumpy</camelHump>", :keep_root => true)
+    end
+
+    it "should camel case attribute names for JSON" do
+      obj = @schema.from_json("camelHump" => "bumpy")
+      obj.wont_be_nil
+      obj[:camel_hump].must_equal "bumpy"
+
+      json = @schema.to_json(obj)
+      json['camelHump'].must_equal "bumpy"
+    end
+
+    it "should camel case attribute names for XML" do
+      obj = @schema.from_xml(sample_xml)
+
+      obj.wont_be_nil
+      obj[:camel_hump].must_equal "bumpy"
+
+      xml = @schema.to_xml(obj)
+
+      xml['camelHump'].must_equal [{ "content" => "bumpy" }]
+    end
+
+    it "should allow aliasing the XML and JSON name" do
+      @schema.scalar :aliased, :xml_name => :xml, :json_name => :json
+      obj = @schema.from_xml({"aliased" => "no", "xml" => "yes"}, {})
+      obj[:aliased].must_equal "yes"
+
+      obj = @schema.from_json({"aliased" => "no", "json" => "yes"}, {})
+      obj[:aliased].must_equal "yes"
+    end
+  end
+
+  describe "hrefs" do
+    before do
+      @schema.href(:meter)
+    end
+
+    it "should extract the href attribute from XML" do
+      xml = parse_xml("<meter href='http://example.org/'/>")
+
+      obj = @schema.from_xml(xml)
+      check obj
+      @schema.to_xml(obj).must_equal xml
+    end
+
+    it "should extract the href attribute from JSON" do
+      json = { "meter" =>  { "href" => "http://example.org/" } }
+
+      obj = @schema.from_json(json)
+      check obj
+      @schema.to_json(obj).must_equal json
+    end
+
+    def check(obj)
+      obj.wont_be_nil
+      obj[:meter].href.must_equal 'http://example.org/'
+    end
+  end
+
+  describe "structs" do
+    before do
+      @schema.struct(:struct, :content => :scalar) do
+        scalar   :href
+      end
+      @schema.attribute_names.must_equal [:struct]
+    end
+
+    let(:sample_json) do
+      { "struct" => { "scalar" => "v1", "href" => "http://example.org/" } }
+    end
+
+    let (:sample_xml) do
+      parse_xml("<struct href='http://example.org/'>v1</struct>")
+    end
+
+    let (:sample_xml_no_href) do
+      parse_xml("<struct>v1</struct>")
+    end
+
+    describe "JSON conversion" do
+      it "should convert empty hash" do
+        model = @schema.from_json({ })
+        check_empty_struct model
+        @schema.to_json(model).keys.must_be_empty
+      end
+
+      it "should convert empty body" do
+        model = @schema.from_json({ "struct" => { } })
+        check_empty_struct model
+        @schema.to_json(model).keys.must_be_empty
+      end
+
+      it "should convert values" do
+        model = @schema.from_json(sample_json)
+        check_struct model
+        @schema.to_json(model).must_equal sample_json
+      end
+    end
+
+    describe "XML conversion" do
+      it "should convert empty hash" do
+        model = @schema.from_xml({ })
+        check_empty_struct model
+        @schema.to_xml(model).keys.must_be_empty
+      end
+
+      it "should convert empty body" do
+        model = @schema.from_json({ "struct" => { } })
+        check_empty_struct model
+        @schema.to_xml(model).keys.must_be_empty
+      end
+
+      it "should convert values" do
+        model = @schema.from_xml(sample_xml)
+        check_struct model
+        @schema.to_xml(model).must_equal sample_xml
+      end
+
+      it "should handle missing attributes" do
+        model = @schema.from_xml(sample_xml_no_href)
+        check_struct model, :nil_href => true
+        @schema.to_xml(model).must_equal sample_xml_no_href
+      end
+    end
+
+    def check_struct(obj, opts = {})
+      obj.wont_be_nil
+      obj[:struct].wont_be_nil
+      obj[:struct].scalar.must_equal "v1"
+      if opts[:nil_href]
+        obj[:struct].href.must_be_nil
+      else
+        obj[:struct].href.must_equal "http://example.org/"
+      end
+    end
+
+    def check_empty_struct(obj)
+      obj.wont_be_nil
+      obj[:struct].wont_be_nil
+      obj[:struct].scalar.must_be_nil
+      obj[:struct].href.must_be_nil
+    end
+  end
+
+  describe "arrays" do
+    before do
+      @schema.array(:structs, :content => :scalar) do
+        scalar :href
+      end
+    end
+
+    let(:sample_json) do
+      { "structs" => [{ "scalar" => "v1", "href" => "http://example.org/1" },
+                      { "scalar" => "v2", "href" => "http://example.org/2" }] }
+    end
+
+    let (:sample_xml) do
+      parse_xml("<wrapper>
+  <struct href='http://example.org/1'>v1</struct>
+  <struct href='http://example.org/2'>v2</struct>
+</wrapper>", :keep_root => false)
+    end
+
+    it "should convert missing array from JSON" do
+      obj = @schema.from_json({})
+
+      obj.wont_be_nil
+      obj[:structs].must_be_empty
+      @schema.to_json(obj).keys.must_be_empty
+    end
+
+    it "should convert empty array from JSON" do
+      obj = @schema.from_json("structs" => [])
+
+      obj.wont_be_nil
+      obj[:structs].must_be_empty
+      @schema.to_json(obj).keys.must_be_empty
+    end
+
+    it "should convert arrays from JSON" do
+      obj = @schema.from_json(sample_json)
+
+      check_structs(obj)
+      @schema.to_json(obj).must_equal sample_json
+    end
+
+    it "should convert arrays from XML" do
+      obj = @schema.from_xml(sample_xml)
+
+      check_structs(obj)
+      @schema.to_xml(obj).must_equal sample_xml
+    end
+
+    def check_structs(obj)
+      obj.wont_be_nil
+      obj[:structs].size.must_equal 2
+      obj[:structs][0].scalar.must_equal "v1"
+      obj[:structs][0].href.must_equal "http://example.org/1"
+      obj[:structs][1].scalar.must_equal "v2"
+      obj[:structs][1].href.must_equal "http://example.org/2"
+    end
+  end
+
+end
diff --git a/server/tests/cimi/spec/cimi/model/volume_configuration_spec.rb b/server/tests/cimi/spec/cimi/model/volume_configuration_spec.rb
new file mode 100644
index 0000000..c12ac05
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/volume_configuration_spec.rb
@@ -0,0 +1,32 @@
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+describe "Volume Configuration model" do
+
+  before do
+    @xml = IO::read(File::join(DATA_DIR, "volume_configuration.xml"))
+    @json = IO::read(File::join(DATA_DIR, "volume_configuration.json"))
+  end
+
+  it "can be constructed from XML and JSON" do
+    should_properly_serialize_model CIMI::Model::VolumeConfiguration, @xml, @json
+  end
+
+
+end
diff --git a/server/tests/cimi/spec/cimi/model/volume_image_spec.rb b/server/tests/cimi/spec/cimi/model/volume_image_spec.rb
new file mode 100644
index 0000000..a6c4a20
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/volume_image_spec.rb
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+describe "Volume Image model" do
+
+  before do
+    @xml = IO::read(File::join(DATA_DIR, "volume_image.xml"))
+    @json = IO::read(File::join(DATA_DIR, "volume_image.json"))
+  end
+
+  it "can be constructed from XML and JSON" do
+    should_properly_serialize_model CIMI::Model::VolumeImage, @xml, @json
+  end
+
+
+end
diff --git a/server/tests/cimi/spec/cimi/model/volume_spec.rb b/server/tests/cimi/spec/cimi/model/volume_spec.rb
new file mode 100644
index 0000000..1176add
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/volume_spec.rb
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+describe "Volume model" do
+
+  before do
+    @xml = IO::read(File::join(DATA_DIR, "volume.xml"))
+    @json = IO::read(File::join(DATA_DIR, "volume.json"))
+  end
+
+  it "can be constructed from XML and JSON" do
+    should_properly_serialize_model CIMI::Model::Volume, @xml, @json
+  end
+
+end
diff --git a/server/tests/cimi/spec/cimi/model/volume_template_spec.rb b/server/tests/cimi/spec/cimi/model/volume_template_spec.rb
new file mode 100644
index 0000000..444baa7
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/volume_template_spec.rb
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+describe "Volume Template model" do
+
+  before do
+    @xml = IO::read(File::join(DATA_DIR, "volume_template.xml"))
+    @json = IO::read(File::join(DATA_DIR, "volume_template.json"))
+  end
+
+  it "can be constructed from XML and JSON" do
+    should_properly_serialize_model CIMI::Model::VolumeTemplate, @xml, @json
+  end
+
+end
diff --git a/server/tests/cimi/spec/spec_helper.rb b/server/tests/cimi/spec/spec_helper.rb
new file mode 100644
index 0000000..3cde6cf
--- /dev/null
+++ b/server/tests/cimi/spec/spec_helper.rb
@@ -0,0 +1,127 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+require 'minitest/autorun'
+require 'minitest/spec'
+require 'xmlsimple'
+require 'require_relative'
+
+require_relative '../../../lib/deltacloud/core_ext.rb'
+require_relative '../../../lib/cimi/models.rb'
+
+DATA_DIR = File::join(File::expand_path(File::dirname(__FILE__)), 'cimi', 'data')
+
+def parse_xml(xml, opts = {})
+  opts[:force_content] = true
+  opts[:keep_root] = true unless opts.has_key?(:keep_root)
+  XmlSimple.xml_in(xml, opts)
+end
+
+class HashCmp
+  def initialize(exp, act)
+    @exp = exp
+    @act = act
+    @io = StringIO.new
+  end
+
+  def match?
+    @equal = true
+    compare_values(@exp, @act, [])
+    @equal
+  end
+
+  def errors
+    @io.string
+  end
+
+  private
+  def compare_values(exp, act, path)
+    if exp.is_a?(String)
+      mismatch("entries differ", exp, act, path) unless exp == act
+    elsif exp.is_a?(Array)
+      mismatch("expected array", exp, act, path) unless act.is_a?(Array)
+      unless act.size == exp.size
+        mismatch("different array lengths", exp, act, path)
+      end
+      name = path.pop
+      0.upto(exp.size-1) do |i|
+        compare_values(exp[i], act[i], path + [ "#{name}[#{i}]" ])
+      end
+    elsif exp.is_a?(Hash)
+      unless act.is_a?(Hash)
+        mismatch("expected Hash", exp, act, path)
+        return
+      end
+      unless (missing = exp.keys - act.keys).empty?
+        error "Missing key(s) at /#{path.join("/")}: #{missing.inspect}"
+      end
+      unless (excess = act.keys - exp.keys).empty?
+        error "Excess key(s) at /#{path.join("/")}: #{excess.inspect}"
+      end
+      (exp.keys - missing - excess).each do |k|
+        compare_values(exp[k], act[k], path + [ k ])
+      end
+    end
+  end
+
+  def mismatch(msg, exp, act, path)
+    error "#{msg}[#{fmt(path)}]: #{exp.inspect} != #{act.inspect}"
+  end
+
+  def error(msg)
+    @equal = false
+    @io.puts msg
+  end
+
+  def fmt(path)
+    "/#{path.join("/")}"
+  end
+end
+
+def should_properly_serialize_model(model_class, xml, json)
+  # Roundtrip in same format
+  model_class.from_xml(xml).must_serialize_to xml, :fmt => :xml
+  model_class.from_json(json).must_serialize_to json, :fmt => :json
+  # Roundtrip crossing format
+  model_class.from_xml(xml).must_serialize_to json, :fmt => :json
+  model_class.from_json(json).must_serialize_to xml, :fmt => :xml
+end
+
+module MiniTest::Assertions
+
+  def assert_serialize_to(exp, act, opts)
+    raise "missing format; use :fmt => [:xml || :json]" if opts[:fmt].nil?
+    exp, act = [exp, act].map { |x| convert(x, opts[:fmt]) }
+    m = HashCmp.new(exp, act)
+    assert m.match?,  "#{opts[:fmt].to_s.upcase} documents do not match\n" + m.errors
+  end
+
+  def convert(x, fmt)
+    if fmt == :json
+      x = x.to_json if x.is_a?(CIMI::Model::Base)
+      x = JSON.parse(x) if x.is_a?(String)
+    elsif fmt == :xml
+      x = x.to_xml if x.is_a?(CIMI::Model::Base)
+      x = parse_xml(x)  if x.is_a?(String)
+    else
+      raise "Invalid format #{fmt}"
+    end
+    x
+  end
+
+end
+
+CIMI::Model::Base.infect_an_assertion :assert_serialize_to, :must_serialize_to
-- 
1.7.10.2