diff --git a/Makefile-tests.am b/Makefile-tests.am index ac63d23a..75d9d2c6 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -50,6 +50,7 @@ insttest_DATA = tests/archive-test.sh \ tests/pull-test.sh \ tests/libtest.sh \ tests/admin-test.sh \ + tests/corrupt-repo-ref.js \ $(NULL) gpginsttestdir = $(pkglibexecdir)/installed-tests/gpghome diff --git a/tests/corrupt-repo-ref.js b/tests/corrupt-repo-ref.js new file mode 100644 index 00000000..b1a797da --- /dev/null +++ b/tests/corrupt-repo-ref.js @@ -0,0 +1,88 @@ +#!/usr/bin/env gjs +// +// Copyright (C) 2014 Colin Walters +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place - Suite 330, +// Boston, MA 02111-1307, USA. + +const GLib = imports.gi.GLib; +const Gio = imports.gi.Gio; +const OSTree = imports.gi.OSTree; + +let repoPathArg = ARGV[0]; +let refToCorrupt = ARGV[1]; + +let repo = OSTree.Repo.new(Gio.File.new_for_path(repoPathArg)); + +repo.open(null); + +function listObjectChecksumsRecurse(dir, allObjects) { + dir.ensure_resolved(); + allObjects[dir.tree_get_contents_checksum() + '.dirtree'] = true; + allObjects[dir.get_checksum() + '.dirmeta'] = true; + let e = dir.enumerate_children('standard::name,standard::type', 0, null); + let info; + while ((info = e.next_file(null)) != null) { + let child = e.get_child(info); + child.ensure_resolved(); + print(info.get_name() + " is " + info.get_file_type()); + if (info.get_file_type() == Gio.FileType.DIRECTORY) { + listObjectChecksumsRecurse(child, allObjects); + } else { + allObjects[child.get_checksum() + '.filez'] = true; + } + } + e.close(null); +} + +let [,commit] = repo.resolve_rev(refToCorrupt, false); +let [,root,commit] = repo.read_commit(refToCorrupt, null); +let allObjects = {}; +allObjects[commit + '.commit'] = true; +listObjectChecksumsRecurse(root, allObjects); +let i = 0; +for (let v in allObjects) + i++; +print("commit " + commit + " refers to " + i + " objects"); +let offset = GLib.random_int_range(0, i); +let objectToCorrupt = null; +for (let v in allObjects) { + if (offset <= 0) { + objectToCorrupt = v; + break; + } + offset--; +} +print("Choosing " + objectToCorrupt + " to corrupt"); + +let loosePath = repo.get_path().resolve_relative_path('objects/' + objectToCorrupt.substring(0, 2) + "/" + objectToCorrupt.substring(2)); + +let iostream = loosePath.open_readwrite(null); +let info = iostream.query_info('standard::size', null); +let size = info.get_size(); +let byteOffsetToCorrupt = GLib.random_int_range(0, size); +iostream.seek(byteOffsetToCorrupt, GLib.SeekType.SET, null); +let datain = Gio.DataInputStream.new(iostream.get_input_stream()); +let dataout = Gio.DataOutputStream.new(iostream.get_output_stream()); +let inbyte = datain.read_byte(null); +let outbyte = (inbyte + 1) % 255; +dataout.put_byte(outbyte, null); +dataout.flush(null); +iostream.close(null); +let status = "Changed byte offset " + byteOffsetToCorrupt + " from " + inbyte + " to " + outbyte; +print(status); + +let successFile = Gio.File.new_for_path('corrupted-status.txt'); +successFile.replace_contents(status, null, false, 0, null); diff --git a/tests/test-pull-corruption.sh b/tests/test-pull-corruption.sh index b042a0c0..9a3cbf55 100755 --- a/tests/test-pull-corruption.sh +++ b/tests/test-pull-corruption.sh @@ -47,21 +47,9 @@ do_corrupt_pull_test() { fi } -# Corrupt .dirmeta -someobject=$(find ${repopath} -name '*.dirmeta' | head -1) -echo "garbage garbage garbage" > ${someobject} +# FIXME - ignore errors here since gjs in RHEL7 has the final +# unrooting bug +gjs $(dirname $0)/corrupt-repo-ref.js ${repopath} main || true +assert_file_has_content corrupted-status.txt 'Changed byte' do_corrupt_pull_test -echo "ok corrupt dirmeta" - -# Corrupt .dirtree -someobject=$(find ${repopath} -name '*.dirtree' | head -1) -echo "garbage garbage garbage" > ${someobject} -do_corrupt_pull_test -echo "ok corrupt dirtree" - -# Corrupt .filez -someobject=$(find ${repopath} -name '*.filez' | head -1) -otherobject=$(find ${repopath} -name '*.filez' | head -2 | tail -1) -cp ${someobject} ${otherobject} -do_corrupt_pull_test -echo "ok corrupt filez" +echo "ok corruption $iteration"