summaryrefslogtreecommitdiffstats
path: root/mmc_updater/src/tests/test-update.rb
diff options
context:
space:
mode:
Diffstat (limited to 'mmc_updater/src/tests/test-update.rb')
-rwxr-xr-xmmc_updater/src/tests/test-update.rb218
1 files changed, 218 insertions, 0 deletions
diff --git a/mmc_updater/src/tests/test-update.rb b/mmc_updater/src/tests/test-update.rb
new file mode 100755
index 00000000..82965cf4
--- /dev/null
+++ b/mmc_updater/src/tests/test-update.rb
@@ -0,0 +1,218 @@
+#!/usr/bin/ruby
+
+require 'fileutils.rb'
+require 'find'
+require 'rbconfig'
+require 'optparse'
+
+# Install directory - this contains a space to check
+# for correct escaping of paths when passing comamnd
+# line arguments under Windows
+INSTALL_DIR = File.expand_path("install dir/")
+PACKAGE_DIR = File.expand_path("package-dir/")
+PACKAGE_SRC_DIR = File.expand_path("package-src-dir/")
+IS_WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
+
+if IS_WINDOWS
+ OLDAPP_NAME = "oldapp.exe"
+ NEWAPP_NAME = "newapp.exe"
+ APP_NAME = "app.exe"
+ UPDATER_NAME = "updater.exe"
+ ZIP_TOOL = File.expand_path("../zip-tool.exe")
+else
+ OLDAPP_NAME = "oldapp"
+ NEWAPP_NAME = "newapp"
+ APP_NAME = "app"
+ UPDATER_NAME = "updater"
+ ZIP_TOOL = File.expand_path("../zip-tool")
+end
+
+file_list_vars = {
+ "APP_FILENAME" => APP_NAME,
+ "UPDATER_FILENAME" => UPDATER_NAME
+}
+
+def replace_vars(src_file,dest_file,vars)
+ content = File.read(src_file)
+ vars.each do |key,value|
+ content.gsub! "$#{key}",value
+ end
+ File.open(dest_file,'w') do |file|
+ file.print content
+ end
+end
+
+# Returns true if |src_file| and |dest_file| have the same contents, type
+# and permissions or false otherwise
+def compare_files(src_file, dest_file)
+ if File.ftype(src_file) != File.ftype(dest_file)
+ $stderr.puts "Type of file #{src_file} and #{dest_file} differ"
+ return false
+ end
+
+ if File.file?(src_file) && !FileUtils.identical?(src_file, dest_file)
+ $stderr.puts "Contents of file #{src_file} and #{dest_file} differ"
+ return false
+ end
+
+ src_stat = File.stat(src_file)
+ dest_stat = File.stat(dest_file)
+
+ if src_stat.mode != dest_stat.mode
+ $stderr.puts "Permissions of #{src_file} and #{dest_file} differ"
+ return false
+ end
+
+ return true
+end
+
+# Compares the contents of two directories and returns a map of (file path => change type)
+# for files and directories which differ between the two
+def compare_dirs(src_dir, dest_dir)
+ src_dir += '/' if !src_dir.end_with?('/')
+ dest_dir += '/' if !dest_dir.end_with?('/')
+
+ src_file_map = {}
+ Find.find(src_dir) do |src_file|
+ src_file = src_file[src_dir.length..-1]
+ src_file_map[src_file] = nil
+ end
+
+ change_map = {}
+ Find.find(dest_dir) do |dest_file|
+ dest_file = dest_file[dest_dir.length..-1]
+
+ if !src_file_map.include?(dest_file)
+ change_map[dest_file] = :deleted
+ elsif !compare_files("#{src_dir}/#{dest_file}", "#{dest_dir}/#{dest_file}")
+ change_map[dest_file] = :updated
+ end
+
+ src_file_map.delete(dest_file)
+ end
+
+ src_file_map.each do |file|
+ change_map[file] = :added
+ end
+
+ return change_map
+end
+
+def create_test_file(name, content)
+ File.open(name, 'w') do |file|
+ file.puts content
+ end
+ return name
+end
+
+force_elevation = false
+run_in_debugger = false
+
+OptionParser.new do |parser|
+ parser.on("-f","--force-elevated","Force the updater to elevate itself") do
+ force_elevation = true
+ end
+ parser.on("-d","--debug","Run the updater under GDB") do
+ run_in_debugger = true
+ end
+end.parse!
+
+# copy 'src' to 'dest', preserving the attributes
+# of 'src'
+def copy_file(src, dest)
+ FileUtils.cp src, dest, :preserve => true
+end
+
+# Remove the install and package dirs if they
+# already exist
+FileUtils.rm_rf(INSTALL_DIR)
+FileUtils.rm_rf(PACKAGE_DIR)
+FileUtils.rm_rf(PACKAGE_SRC_DIR)
+
+# Create the install directory with the old app
+Dir.mkdir(INSTALL_DIR)
+copy_file OLDAPP_NAME, "#{INSTALL_DIR}/#{APP_NAME}"
+
+# Create a dummy file to uninstall
+uninstall_test_file = create_test_file("#{INSTALL_DIR}/file-to-uninstall.txt", "this file should be removed after the update")
+uninstall_test_symlink = if not IS_WINDOWS
+ FileUtils.ln_s("#{INSTALL_DIR}/file-to-uninstall.txt", "#{INSTALL_DIR}/symlink-to-file-to-uninstall.txt")
+else
+ create_test_file("#{INSTALL_DIR}/symlink-to-file-to-uninstall.txt", "dummy file. this is a symlink on Unix")
+end
+
+# Populate package source dir with files to install
+Dir.mkdir(PACKAGE_SRC_DIR)
+nested_dir_path = "#{PACKAGE_SRC_DIR}/new-dir/new-dir2"
+FileUtils.mkdir_p(nested_dir_path)
+FileUtils::chmod 0755, "#{PACKAGE_SRC_DIR}/new-dir"
+FileUtils::chmod 0755, "#{PACKAGE_SRC_DIR}/new-dir/new-dir2"
+nested_dir_test_file = "#{nested_dir_path}/new-file.txt"
+File.open(nested_dir_test_file,'w') do |file|
+ file.puts "this is a new file in a new nested dir"
+end
+FileUtils::chmod 0644, nested_dir_test_file
+copy_file NEWAPP_NAME, "#{PACKAGE_SRC_DIR}/#{APP_NAME}"
+FileUtils::chmod 0755, "#{PACKAGE_SRC_DIR}/#{APP_NAME}"
+
+# Create .zip packages from source files
+Dir.mkdir(PACKAGE_DIR)
+Dir.chdir(PACKAGE_SRC_DIR) do
+ if !system("#{ZIP_TOOL} #{PACKAGE_DIR}/app-pkg.zip .")
+ raise "Unable to create update package"
+ end
+end
+
+# Copy the install script and updater to the target
+# directory
+replace_vars("file_list.xml","#{PACKAGE_DIR}/file_list.xml",file_list_vars)
+copy_file "../#{UPDATER_NAME}", "#{PACKAGE_DIR}/#{UPDATER_NAME}"
+
+# Run the updater using the new syntax
+#
+# Run the application from the install directory to
+# make sure that it looks in the correct directory for
+# the file_list.xml file and packages
+#
+install_path = File.expand_path(INSTALL_DIR)
+Dir.chdir(INSTALL_DIR) do
+ flags = "--force-elevated" if force_elevation
+ debug_flags = "gdb --args" if run_in_debugger
+ cmd = "#{debug_flags} #{PACKAGE_DIR}/#{UPDATER_NAME} #{flags} --install-dir \"#{install_path}\" --package-dir \"#{PACKAGE_DIR}\" --script file_list.xml --auto-close"
+ puts "Running '#{cmd}'"
+ system(cmd)
+end
+
+# TODO - Correctly wait until updater has finished
+sleep(1)
+
+# Check that the app was updated
+app_path = "#{INSTALL_DIR}/#{APP_NAME}"
+output = `"#{app_path}"`
+if (output.strip != "new app starting")
+ throw "Updated app produced unexpected output: #{output}"
+end
+
+# Check that the packaged dir and install dir match
+dir_diff = compare_dirs(PACKAGE_SRC_DIR, INSTALL_DIR)
+ignored_files = ["test-dir", "test-dir/app-symlink", UPDATER_NAME]
+have_unexpected_change = false
+dir_diff.each do |path, change_type|
+ if !ignored_files.include?(path)
+ case change_type
+ when :added
+ $stderr.puts "File #{path} was not installed"
+ when :changed
+ $stderr.puts "File #{path} differs between install and package dir"
+ when :deleted
+ $stderr.puts "File #{path} was not uninstalled"
+ end
+ have_unexpected_change = true
+ end
+end
+
+if have_unexpected_change
+ throw "Unexpected differences between packaging and update dir"
+end
+
+puts "Test passed"