#!/usr/bin/python # # Black-box test dupfiles. # Copyright 2010 Lars Wirzenius # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os import shutil import subprocess import tempfile class TestCase(object): def __init__(self): self.tempdir = tempfile.mkdtemp() self.identical = [] def setUp(self): pass def tearDown(self): pass def cleanup(self): shutil.rmtree(self.tempdir) def create(self, name, content): file(os.path.join(self.tempdir, name), 'w').write(content) def hardlink(self, name, newname): os.link(os.path.join(self.tempdir, name), os.path.join(self.tempdir, newname)) def symlink(self, name, newname): os.symlink(os.path.join(self.tempdir, name), os.path.join(self.tempdir, newname)) def test(self): p = subprocess.Popen(['./dupfiles', self.tempdir], stdout=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode: raise Exception('dupfiles error: %d\n' % p.returncode) identical = self.identical[:] for line in stdout.splitlines(): if not line: continue line = line.strip() if line.startswith(self.tempdir + '/'): line = line[len(self.tempdir + '/'):] if line in identical: identical.remove(line) else: raise Exception('dupfiles found extra dup: %s' % line) if identical: raise Exception('dupfiles failed to find:\n%s' % '\n'.join(identical)) class DifferentFilesOfSameSize(TestCase): def setUp(self): self.create('foo', 'foo') self.create('bar', 'bar') class TwoIdenticalFiles(TestCase): def setUp(self): self.create('foo', 'foo') self.create('bar', 'foo') self.identical = ['foo', 'bar'] class TwoHardlinksToSameContent(TestCase): def setUp(self): self.create('foo', 'foo') self.hardlink('foo', 'bar') self.identical = [] class TwoHardlinksToSameContentPlusSecondIdenticalCopy(TestCase): def setUp(self): self.create('foo', 'foo') self.hardlink('foo', 'bar') self.create('foobar', 'foo') self.identical = ['foo', 'bar', 'foobar'] class Symlink(TestCase): def setUp(self): self.create('foo', 'foo') self.symlink('foo', 'bar') self.identical = [] def main(): klasses = [o for name, o in globals().iteritems() if type(o) == type(object) and issubclass(o, TestCase) and o != TestCase] for klass in klasses: try: test = klass() test.setUp() test.test() test.tearDown() test.cleanup() except Exception, e: print 'Test FAIL: %s' % klass.__name__ raise e else: print "Test PASS: %s" % klass.__name__ if __name__ == '__main__': main()