Fix/remove tests from the gutted updater

This commit is contained in:
Petr Mrázek 2013-12-15 23:46:48 +01:00
parent b0e8037feb
commit b773ef08af
10 changed files with 45 additions and 357 deletions

View File

@ -56,9 +56,7 @@ class UpdateScriptFile
}
};
/** Stores information about the packages and files included
* in an update, parsed from an XML file.
*/
/** Stores information about the files included in an update, parsed from an XML file. */
class UpdateScript
{
public:

View File

@ -142,7 +142,7 @@ void UpdaterOptions::parse(int argc, char** argv)
showVersion = parser.getFlag("version");
forceElevated = parser.getFlag("force-elevated");
autoClose = parser.getFlag("auto-close");
if (installDir.empty())
{
// if no --install-dir argument is present, try parsing
@ -152,3 +152,4 @@ void UpdaterOptions::parse(int argc, char** argv)
}
}

View File

@ -5,21 +5,19 @@ if (APPLE)
set(HELPER_SHARED_SOURCES ../StlSymbolsLeopard.cpp)
endif()
# Create helper binaries for unit tests
add_executable(oldapp
old_app.cpp
${HELPER_SHARED_SOURCES}
)
add_executable(newapp
new_app.cpp
${HELPER_SHARED_SOURCES}
)
# # Create helper binaries for unit tests
# add_executable(oldapp
# old_app.cpp
# ${HELPER_SHARED_SOURCES}
# )
# add_executable(newapp
# new_app.cpp
# ${HELPER_SHARED_SOURCES}
# )
# Install data files required by unit tests
set(TEST_FILES
file_list.xml
v2_file_list.xml
test-update.rb
)
foreach(TEST_FILE ${TEST_FILES})
@ -40,12 +38,6 @@ macro(ADD_UPDATER_TEST CLASS)
endif()
endmacro()
add_updater_test(TestUpdateScript)
add_updater_test(TestParseScript)
add_updater_test(TestUpdaterOptions)
add_updater_test(TestFileUtils)
# Add updater that that performs a complete update install
# and checks the result
find_program(RUBY_BIN ruby)
add_test(updater_TestUpdateInstall ${RUBY_BIN} test-update.rb)

View File

@ -0,0 +1,24 @@
#include "TestParseScript.h"
#include "TestUtils.h"
#include "UpdateScript.h"
#include <iostream>
#include <algorithm>
void TestParseScript::testParse()
{
UpdateScript script;
script.parse("file_list.xml");
TEST_COMPARE(script.isValid(),true);
}
int main(int,char**)
{
TestList<TestParseScript> tests;
tests.addTest(&TestParseScript::testParse);
return TestUtils::runTest(tests);
}

View File

@ -0,0 +1,8 @@
#pragma once
class TestParseScript
{
public:
void testParse();
};

View File

@ -1,27 +0,0 @@
#include "TestUpdateScript.h"
#include "TestUtils.h"
#include "UpdateScript.h"
#include <iostream>
#include <algorithm>
void TestUpdateScript::testV2Script()
{
UpdateScript newFormat;
UpdateScript oldFormat;
newFormat.parse("file_list.xml");
oldFormat.parse("v2_file_list.xml");
TEST_COMPARE(newFormat.filesToInstall(),oldFormat.filesToInstall());
TEST_COMPARE(newFormat.filesToUninstall(),oldFormat.filesToUninstall());
}
int main(int,char**)
{
TestList<TestUpdateScript> tests;
tests.addTest(&TestUpdateScript::testV2Script);
return TestUtils::runTest(tests);
}

View File

@ -1,8 +0,0 @@
#pragma once
class TestUpdateScript
{
public:
void testV2Script();
};

View File

@ -1,20 +1,5 @@
<?xml version="1.0"?>
<update version="3">
<targetVersion>2.0</targetVersion>
<platform>Test</platform>
<dependencies>
<!-- The new updater is standalone and has no dependencies,
except for standard system libraries.
!-->
</dependencies>
<packages>
<package>
<name>app-pkg</name>
<hash>$APP_PACKAGE_HASH</hash>
<size>$APP_PACKAGE_SIZE</size>
<source>http://some/dummy/URL</source>
</package>
</packages>
<install>
<file>
<name>$APP_FILENAME</name>

View File

@ -1,218 +0,0 @@
#!/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"

View File

@ -1,67 +0,0 @@
<?xml version="1.0"?>
<!-- The v2-compatible attribute lets the update script parser
know that it is dealing with a script structured for backwards
compatibility with the MD <= 1.0 updater.
!-->
<update version="3" v2-compatible="true">
<targetVersion>2.0</targetVersion>
<platform>Test</platform>
<dependencies>
<!-- The new updater is standalone and has no dependencies,
except for standard system libraries and itself.
!-->
</dependencies>
<packages>
<package>
<name>app-pkg</name>
<hash>$APP_PACKAGE_HASH</hash>
<size>$APP_PACKAGE_SIZE</size>
<source>http://some/dummy/URL</source>
</package>
</packages>
<!-- For compatibility with the update download in MD <= 1.0,
an <install> section lists the packages to download and
the real list of files to install is in the <install-v3>
section. !-->
<install>
<!-- A duplicate of the <packages> section should appear here,
except that each package is listed using the same structure
as files in the install-v3/files section.
!-->
</install>
<install-v3>
<file>
<name>$APP_FILENAME</name>
<hash>$UPDATED_APP_HASH</hash>
<size>$UPDATED_APP_SIZE</size>
<permissions>0755</permissions>
<package>app-pkg</package>
<is-main-binary>true</is-main-binary>
</file>
<file>
<name>$UPDATER_FILENAME</name>
<hash>$UPDATER_HASH</hash>
<size>$UPDATER_SIZE</size>
<permissions>0755</permissions>
</file>
<!-- Test symlink !-->
<file>
<name>test-dir/app-symlink</name>
<target>../app</target>
</file>
<file>
<name>new-dir/new-dir2/new-file.txt</name>
<hash>$TEST_FILENAME</hash>
<size>$TEST_SIZE</size>
<package>app-pkg</package>
<permissions>0644</permissions>
</file>
</install-v3>
<uninstall>
<!-- TODO - List some files to uninstall here !-->
<file>file-to-uninstall.txt</file>
<file>symlink-to-file-to-uninstall.txt</file>
</uninstall>
</update>