Permalink
Browse files

added vm test scaffold

  • Loading branch information...
1 parent 338cc54 commit 9e116650f395e79ab3ecd14df8c7a015395bc8f5 Simon Chiang committed Aug 16, 2011
Showing with 442 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +70 −0 Rakefile
  3. +124 −0 VBOX_TEST_README.md
  4. +14 −0 config/ssh.example
  5. +72 −0 vboxtest.sh
  6. +73 −0 vboxtest/test/example_test.sh
  7. +48 −0 vboxtest/test_helper.sh
  8. +40 −0 vboxtest/test_suite.sh
View
@@ -23,3 +23,4 @@ Makefile
depcomp
missing
.deps/
+config/ssh
View
@@ -57,3 +57,73 @@ end
task :test do
exec "bash -l -c \"./test/suite\""
end
+
+#
+# VirtualBox Helpers
+#
+
+# Matches a host declaration in a ssh config file.
+HOST_REGEXP = /^\s*Host\s+([^\s#*]+)/
+SNAPSHOT = (ENV['SNAPSHOT'] || 'CURRENT').upcase
+SSH_CONFIG_FILE = ENV['SSH_CONFIG_FILE'] || File.expand_path('../config/ssh', __FILE__)
+
+def shell(cmd)
+ puts "$ #{cmd}"
+ system(cmd)
+end
+
+def hosts
+ @hosts ||= begin
+ hosts = []
+
+ File.open(SSH_CONFIG_FILE) do |io|
+ io.each_line do |line|
+ next unless line =~ HOST_REGEXP
+ hosts << $1
+ end
+ end
+
+ hosts
+ end
+end
+
+namespace :vbox do
+ desc "start each vm"
+ task :start => :stop do
+ hosts.each do |host|
+ shell "VBoxManage -q snapshot #{host} restore #{SNAPSHOT}"
+ shell "VBoxManage -q startvm #{host} --type headless"
+ shell "ssh -MNf -F '#{SSH_CONFIG_FILE}' '#{host}' >/dev/null 2>&1 </dev/null"
+ end
+ end
+
+ desc "stop each vm"
+ task :stop do
+ hosts.each do |host|
+ if `VBoxManage -q list runningvms`.include?(host)
+ shell "VBoxManage -q controlvm #{host} poweroff"
+ end
+ end
+ end
+
+ desc 'Run the tests remotely on each VM'
+ task :test do
+ begin
+ Rake::Task["vbox:start"].invoke
+ Rake::Task["vbox:remote_test"].invoke
+ ensure
+ Rake::Task["vbox:stop"].execute(nil)
+ end
+ end
+
+ desc 'Run the tests remotely (assuming each VM is running)'
+ task :remote_test do
+ local_dir = File.expand_path("../vboxtest", __FILE__)
+ sh "'#{File.expand_path("../vboxtest.sh", __FILE__)}' -L '#{local_dir}' #{hosts.join(' ')}"
+ end
+
+ desc 'Run the tests locally'
+ task :local_test do
+ sh File.expand_path("../vboxtest/test_suite.sh", __FILE__)
+ end
+end
View
@@ -0,0 +1,124 @@
+Testing
+=============================================================================
+
+RVM lives in the shell and so is tested in a shell. The test directory
+contains shell-based unit tests.
+
+To run locally:
+
+ ./test/test_suite.sh
+
+Or:
+
+ rake vbox:local_test
+
+To add another test suite, make a script in the test directory that ends with
+`_test.sh` and ensure it is executable. Then follow the pattern in
+`example_test.sh`:
+
+ #!/bin/sh
+
+ ########################################################################
+ TEST_CASE=$(basename $0)
+ ########################################################################
+ . ${0%/$TEST_CASE}/../test_helper.sh
+
+ test_echo_echos_a_string_to_stdout () {
+ # The assert_equal method will check that the echo command exits
+ # with status 0, and that the stdout is 'hello world'.
+ #
+ # There are similar assertions to just check the exit status
+ # or just check stdout.
+
+ assert_equal 0 "$(
+ echo 'hello world'
+ )" $LINENO <<stdout
+ hello world
+ stdout
+
+ # Write as many assertions as you please in a given method.
+ }
+
+ run_test_case "$0"
+
+You can write as many test methods as you like... just follow the same
+conventions as in Test::Unit (ie start the method with `test_`).
+
+Running on VMs
+------------------------
+
+First set up some virtual machines by following the instructions in
+doc/vm_setup. Then copy config/ssh.example to config/ssh and replace the
+USERNAME comment with your user for the virtual machines. You can add/remove
+hosts as you please; each host should correspond to the name of a VM in
+[VirtualBox](http://www.virtualbox.org/). The only requirement is that the VM
+can be reached via ssh.
+
+Now to run the tests:
+
+ # starts each of the VMs
+ rake vbox:start
+
+ # copies the test scripts to each vm and runs the test suite on each
+ rake vbox:remote_test
+
+ # stops each of the VMs
+ rake vbox:stop
+
+Or you can run the whole shebang with:
+
+ rake vbox:test
+
+Setting up a Ubuntu VM
+------------------------
+
+As an example, build a Ubuntu VM using the following:
+
+- name: ubuntu
+- Linux/Ubuntu
+- 512 MB memory
+- 8 GB dynamically resizing drive
+
+Add the iso to the cd/dvd device under Settings > Storage. Now start the
+server and install ubuntu (use default settings unless specified):
+
+- user/password: vboxtest
+- select 'OpenSSH server' in packages to install
+
+When the server has rebooted and is ready at the login screen, remove the
+install iso, take a snapshot and setup port forwarding.
+
+ (Devices > CD/DVD Devices > Remove disk from virtual drive)
+ VBoxManage snapshot ubuntu take RAW
+ VBoxManage controlvm ubuntu poweroff
+ # wait to fully power off
+ VBoxManage modifyvm ubuntu --natpf1 'ubuntu-ssh,tcp,,2220,,22'
+ VBoxManage -q snapshot ubuntu restore RAW
+ VBoxManage startvm ubuntu
+
+Transfer your ssh key to the vm. Help to generate ssh keys can be found on
+[GitHub](http://help.github.com/key-setup-redirect):
+
+ scp -P 2220 -o UserKnownHostsFile=/dev/null ~/.ssh/id_rsa.pub USERNAME@localhost:id_rsa.pub
+
+Setup SSH for your user:
+
+ vm: mkdir .ssh
+ vm: mv id_rsa.pub .ssh/authorized_keys
+ vm: chmod 0700 .ssh
+ vm: chmod 0600 .ssh/authorized_keys
+
+Remove the login banner and exit:
+
+ vm: sudo rm /etc/motd
+ vm: exit
+
+Now take some standard snapshots:
+
+ VBoxManage snapshot ubuntu take BASE
+ VBoxManage snapshot ubuntu take CURRENT
+ VBoxManage controlvm ubuntu poweroff
+
+To cleanup the port forwarding (run later, if ever):
+
+ VBoxManage modifyvm ubuntu --natpf1 delete 'ubuntu-ssh'
View
@@ -0,0 +1,14 @@
+# Add hosts as needed...
+Host ubuntu
+Port 2220
+
+# The default SSH options go at the bottom.
+Host *
+HostName localhost
+User vboxtest
+Port 2220
+UserKnownHostsFile /dev/null
+StrictHostKeyChecking no
+IdentitiesOnly yes
+ControlMaster auto
+ControlPath /tmp/socket-%r@%h:%p
View
@@ -0,0 +1,72 @@
+#! /bin/sh
+############################################################################
+
+ssh_config_file=${SSH_CONFIG_FILE:-config/ssh}
+local_dir=${LOCAL_DIR:-$(pwd)/test}
+remote_dir=${REMOTE_DIR:-\$(pwd)/$(basename "$local_dir")}
+remote_script=${REMOTE_SCRIPT:-test_suite.sh}
+
+usage="usage: %s [-F SSH_CONFIG_FILE] [-L LOCAL_DIR] [-R REMOTE_DIR] [-S SCRIPT] [-h] HOSTS...\n"
+option=" %s %s\n"
+while getopts "F:G:L:R:S:h" opt
+do
+ case $opt in
+ F ) ssh_config_file=$OPTARG ;;
+ L ) local_dir=$OPTARG ;;
+ R ) remote_dir=$OPTARG ;;
+ S ) remote_script=$OPTARG ;;
+ h ) printf "$usage" $0
+ printf "$option" "-F" "the ssh config file"
+ printf "$option" "-L" "the local dir"
+ printf "$option" "-R" "the remote dir"
+ printf "$option" "-S" "the remote script"
+ printf "$option" "-h" "prints this help"
+ exit 0 ;;
+ \? ) printf "$usage" $0
+ exit 2 ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+############################################################################
+#
+# transfer tests
+#
+
+for host in "$@"
+do
+ssh -q -T -F "$ssh_config_file" "$host" -- <<SCRIPT
+rm -rf "$remote_dir"
+if [ "\$(dirname "$remote_dir")" != "" ]
+then
+ mkdir -p "\$(dirname "$remote_dir")"
+fi
+SCRIPT
+
+scp -q -r -p -F "$ssh_config_file" "$local_dir" "$host:$remote_dir"
+
+status=$?
+if [ $status -ne 0 ]
+then
+ echo "[$status] could not scp tests to host: $host" >&2
+ exit 1
+fi
+done
+
+#
+# run tests
+#
+
+for host in "$@"
+do
+echo "############## $host ##############"
+ssh -q -F "$ssh_config_file" "$host" -- "$remote_dir/$remote_script" </dev/null
+
+status=$?
+if [ $status -ne 0 ]
+then
+ echo "[$status] $remote_dir/$remote_script" >&2
+ exit 1
+fi
+done
+############################################################################
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+########################################################################
+TEST_CASE=$(basename $0)
+########################################################################
+. ${0%/$TEST_CASE}/../test_helper.sh
+
+#
+# assert_equal test
+#
+
+test_assert_equal_pass () {
+ assert_equal 0 "$(
+echo 'hello world'
+echo 'hello world'
+echo 'hello world'
+)" $LINENO <<stdout
+hello world
+hello world
+hello world
+stdout
+}
+
+test_assert_equal_fail_by_status () {
+ assert_equal 1 "$(
+echo 'hello world'
+echo 'hello world'
+echo 'hello world'
+)" $LINENO <<stdout
+hello world
+hello world
+hello world
+stdout
+}
+
+test_assert_equal_fail_by_output () {
+ assert_equal 0 "$(
+echo 'hello world'
+echo 'ellow world'
+echo 'hello world'
+)" $LINENO <<stdout
+hello world
+hello world
+hello world
+stdout
+}
+
+#
+# assert_status_equal test
+#
+
+test_assert_status_equal_pass () {
+ true
+ assert_status_equal 0 $? $LINENO
+}
+
+#
+# assert_output test
+#
+
+test_assert_output_equal_pass () {
+ assert_output_equal "$(
+echo 'hello world'
+echo 'hello world'
+echo 'hello world'
+)" $LINENO <<stdout
+hello world
+hello world
+hello world
+stdout
+}
+
+run_test_case "$0"
Oops, something went wrong.

0 comments on commit 9e11665

Please sign in to comment.