From bb4089be305a86216b63c11f508445b129a57716 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 2 Jan 2011 13:03:46 +0000 Subject: Remove code. It is going to get rewritten. It does not pass even simple black box testing at the moment. --- blackboxtest | 37 ++ createfiles-ext3-with-dirindex-0B.png | Bin 5518 -> 0 bytes createfiles-ext3-with-dirindex-16384B.png | Bin 4634 -> 0 bytes createfiles-ext3-with-dirindex-4096B.png | Bin 6216 -> 0 bytes createfiles-ext3-with-dirindex-8192B.png | Bin 5567 -> 0 bytes createfiles-plot.sh | 51 --- createfiles.output-ext3-with-dirindex | 528 ------------------------ createfiles.py | 162 -------- genbackupdata.py | 660 ------------------------------ tests.py | 565 ------------------------- 10 files changed, 37 insertions(+), 1966 deletions(-) delete mode 100644 createfiles-ext3-with-dirindex-0B.png delete mode 100644 createfiles-ext3-with-dirindex-16384B.png delete mode 100644 createfiles-ext3-with-dirindex-4096B.png delete mode 100644 createfiles-ext3-with-dirindex-8192B.png delete mode 100755 createfiles-plot.sh delete mode 100644 createfiles.output-ext3-with-dirindex delete mode 100755 createfiles.py delete mode 100644 genbackupdata.py delete mode 100755 tests.py diff --git a/blackboxtest b/blackboxtest index b1d3ccd..e54519e 100755 --- a/blackboxtest +++ b/blackboxtest @@ -20,6 +20,7 @@ '''Run some black box tests for genbackupdata.''' +import hashlib import logging import os import random @@ -166,6 +167,33 @@ class GenbackupdataTestCase(unittest.TestCase): size += st.st_size return size + def checksum(self, pathname): + '''Return MD5 checksum for contents of a file.''' + s = hashlib.new('md5') + f = open(pathname, 'rb') + while True: + data = f.read(64*1024) + if not data: + break + s.update(data) + f.close() + return s.hexdigest() + + def checksums(self, root): + '''Return sorted list of (pathname, checksum) pairs for reg. files.''' + result = [] + prefix = self.path(root) + os.sep + for dirname, subdirs, filenames in os.walk(self.path(root)): + for filename in filenames: + pathname = self.path(dirname, filename) + st = os.lstat(pathname) + if stat.S_ISREG(st.st_mode): + assert pathname.startswith(prefix) + relative = pathname[len(prefix):] + result.append((relative, self.checksum(pathname))) + result.sort() + return result + def assert_equal_stat_fields(self, filename, stat1, stat2, fieldname): field1 = getattr(stat1, fieldname) field2 = getattr(stat2, fieldname) @@ -241,6 +269,15 @@ class GenbackupdataTests(GenbackupdataTestCase): self.genbackupdata([self.path('data'), '--create=%d' % bytes]) self.assertEqual(self.apparent_size('data'), bytes) + def test_creates_same_data_every_time(self): + size = '10m' # big enough to allow both ample text and binary data + self.genbackupdata([self.path('data1'), '--create', size]) + self.genbackupdata([self.path('data2'), '--create', size]) + sums1 = self.checksums('data1') + sums2 = self.checksums('data2') + self.assertEqual(len(sums1), len(sums2)) + for n in range(1, len(sums1)): + self.assertEqual(sums1[:n], sums2[:n]) if __name__ == '__main__': logging.basicConfig(filename='blackboxtest.log', diff --git a/createfiles-ext3-with-dirindex-0B.png b/createfiles-ext3-with-dirindex-0B.png deleted file mode 100644 index 102801f..0000000 Binary files a/createfiles-ext3-with-dirindex-0B.png and /dev/null differ diff --git a/createfiles-ext3-with-dirindex-16384B.png b/createfiles-ext3-with-dirindex-16384B.png deleted file mode 100644 index eb9e863..0000000 Binary files a/createfiles-ext3-with-dirindex-16384B.png and /dev/null differ diff --git a/createfiles-ext3-with-dirindex-4096B.png b/createfiles-ext3-with-dirindex-4096B.png deleted file mode 100644 index 6682c3b..0000000 Binary files a/createfiles-ext3-with-dirindex-4096B.png and /dev/null differ diff --git a/createfiles-ext3-with-dirindex-8192B.png b/createfiles-ext3-with-dirindex-8192B.png deleted file mode 100644 index e63387d..0000000 Binary files a/createfiles-ext3-with-dirindex-8192B.png and /dev/null differ diff --git a/createfiles-plot.sh b/createfiles-plot.sh deleted file mode 100755 index c4a7e19..0000000 --- a/createfiles-plot.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh -# -# A small script to generate graphs from createfiles.py output. There will -# be one createfiles-$SIZE.png file for each size of output, graphing the -# various algorithms at various sizes. - -set -e - -input="$1" - -algos=$(awk '$2 == "files/s" { print $3 }' "$input" | sort -u) -sizes=$(awk '/^Measuring/ { print $(NF-1) }' "$input" | sort -un) - -for size in $sizes -do - plot="" - - for x in $algos - do - awk -vx=$x -vsize=$size ' - /^Measuring/ { - if ($(NF-1) == size) { - n = $6 - ok = 1 - } else { - ok = 0 - } - } - ok && $3 == x { - print n, $1 >> x ".dat" - }' "$input" - if [ "$plot" = "" ] - then - plot="plot \"$x.dat\" with lines" - else - plot="$plot, \"$x.dat\" with lines" - fi - done - - gnuplot < "createfiles-$size.png" -set terminal png -set title "Size $size" -$plot -eof - - for x in $algos - do - rm "$x.dat" - done - -done diff --git a/createfiles.output-ext3-with-dirindex b/createfiles.output-ext3-with-dirindex deleted file mode 100644 index 72e9a46..0000000 --- a/createfiles.output-ext3-with-dirindex +++ /dev/null @@ -1,528 +0,0 @@ -Measuring 7 functions for creating 10 files of 0 bytes - - 41487 files/s onedir All files in one directory - 34721 files/s subdirsof100 Files in subdirs, each with up to 100 files - 35727 files/s subdirsof250 Files in subdirs, each with up to 250 files - 34606 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 15082 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 15169 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 15219 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 1000 files of 0 bytes - - 38065 files/s onedir All files in one directory - 44621 files/s subdirsof100 Files in subdirs, each with up to 100 files - 41822 files/s subdirsof250 Files in subdirs, each with up to 250 files - 36725 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 16732 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 16327 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 15492 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 2000 files of 0 bytes - - 37583 files/s onedir All files in one directory - 43994 files/s subdirsof100 Files in subdirs, each with up to 100 files - 41007 files/s subdirsof250 Files in subdirs, each with up to 250 files - 36047 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 16692 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 16200 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 15404 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 4000 files of 0 bytes - - 36298 files/s onedir All files in one directory - 43217 files/s subdirsof100 Files in subdirs, each with up to 100 files - 40305 files/s subdirsof250 Files in subdirs, each with up to 250 files - 35675 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 16520 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 16102 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 15307 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 8000 files of 0 bytes - - 35039 files/s onedir All files in one directory - 42752 files/s subdirsof100 Files in subdirs, each with up to 100 files - 39964 files/s subdirsof250 Files in subdirs, each with up to 250 files - 35321 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 15394 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 15941 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 15280 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 16000 files of 0 bytes - - 34941 files/s onedir All files in one directory - 42378 files/s subdirsof100 Files in subdirs, each with up to 100 files - 39506 files/s subdirsof250 Files in subdirs, each with up to 250 files - 35237 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 14456 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 15912 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 15183 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 32000 files of 0 bytes - - 34194 files/s onedir All files in one directory - 42020 files/s subdirsof100 Files in subdirs, each with up to 100 files - 38924 files/s subdirsof250 Files in subdirs, each with up to 250 files - 35041 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 16385 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 15051 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 15164 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 64000 files of 0 bytes - - 29784 files/s onedir All files in one directory - 41785 files/s subdirsof100 Files in subdirs, each with up to 100 files - 38778 files/s subdirsof250 Files in subdirs, each with up to 250 files - 31200 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 15282 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 14932 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 14309 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 128000 files of 0 bytes - - 31150 files/s onedir All files in one directory - 30689 files/s subdirsof100 Files in subdirs, each with up to 100 files - 38397 files/s subdirsof250 Files in subdirs, each with up to 250 files - 30766 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 14921 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 15011 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 14034 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 256000 files of 0 bytes - - 29211 files/s onedir All files in one directory - 19747 files/s subdirsof100 Files in subdirs, each with up to 100 files - 35337 files/s subdirsof250 Files in subdirs, each with up to 250 files - 28877 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 14432 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 14121 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 14065 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 512000 files of 0 bytes - - 24449 files/s onedir All files in one directory - 21297 files/s subdirsof100 Files in subdirs, each with up to 100 files - 24421 files/s subdirsof250 Files in subdirs, each with up to 250 files - 25494 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 13814 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 13897 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 13321 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 1024000 files of 0 bytes - - 20239 files/s onedir All files in one directory - 20728 files/s subdirsof100 Files in subdirs, each with up to 100 files - 23730 files/s subdirsof250 Files in subdirs, each with up to 250 files - 26271 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 13227 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 13837 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 12941 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 10 files of 4096 bytes - - 23630 files/s onedir All files in one directory - 21654 files/s subdirsof100 Files in subdirs, each with up to 100 files - 21687 files/s subdirsof250 Files in subdirs, each with up to 250 files - 21834 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 11364 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 11822 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 11808 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 1000 files of 4096 bytes - - 21001 files/s onedir All files in one directory - 24392 files/s subdirsof100 Files in subdirs, each with up to 100 files - 23646 files/s subdirsof250 Files in subdirs, each with up to 250 files - 21926 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 12504 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 12236 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 11767 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 2000 files of 4096 bytes - - 21391 files/s onedir All files in one directory - 24029 files/s subdirsof100 Files in subdirs, each with up to 100 files - 21909 files/s subdirsof250 Files in subdirs, each with up to 250 files - 20476 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 11577 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 11167 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 10509 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 4000 files of 4096 bytes - - 21258 files/s onedir All files in one directory - 23132 files/s subdirsof100 Files in subdirs, each with up to 100 files - 21925 files/s subdirsof250 Files in subdirs, each with up to 250 files - 20587 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 12205 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 11882 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 11340 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 8000 files of 4096 bytes - - 19734 files/s onedir All files in one directory - 18496 files/s subdirsof100 Files in subdirs, each with up to 100 files - 12523 files/s subdirsof250 Files in subdirs, each with up to 250 files - 20460 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 12078 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 11650 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 11207 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 16000 files of 4096 bytes - - 20482 files/s onedir All files in one directory - 20108 files/s subdirsof100 Files in subdirs, each with up to 100 files - 19301 files/s subdirsof250 Files in subdirs, each with up to 250 files - 20069 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 10945 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 10651 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 10582 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 32000 files of 4096 bytes - - 9755 files/s onedir All files in one directory - 6502 files/s subdirsof100 Files in subdirs, each with up to 100 files - 18511 files/s subdirsof250 Files in subdirs, each with up to 250 files - 18066 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 10939 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 9046 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 10583 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 64000 files of 4096 bytes - - 3890 files/s onedir All files in one directory - 5069 files/s subdirsof100 Files in subdirs, each with up to 100 files - 14446 files/s subdirsof250 Files in subdirs, each with up to 250 files - 18703 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 10159 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 9593 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 9773 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 128000 files of 4096 bytes - - 5949 files/s onedir All files in one directory - 6611 files/s subdirsof100 Files in subdirs, each with up to 100 files - 15273 files/s subdirsof250 Files in subdirs, each with up to 250 files - 5965 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 9935 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 9203 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 6478 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 256000 files of 4096 bytes - - 4751 files/s onedir All files in one directory - 8139 files/s subdirsof100 Files in subdirs, each with up to 100 files - 6566 files/s subdirsof250 Files in subdirs, each with up to 250 files - 10514 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 7560 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 7301 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 9719 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 512000 files of 4096 bytes - - 3535 files/s onedir All files in one directory - 3437 files/s subdirsof100 Files in subdirs, each with up to 100 files - 4330 files/s subdirsof250 Files in subdirs, each with up to 250 files - 6881 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 4924 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 4542 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 7061 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 1024000 files of 4096 bytes - - 2710 files/s onedir All files in one directory - 4207 files/s subdirsof100 Files in subdirs, each with up to 100 files - 4564 files/s subdirsof250 Files in subdirs, each with up to 250 files - 5296 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 4537 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 4645 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 5819 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 10 files of 8192 bytes - - 19373 files/s onedir All files in one directory - 18316 files/s subdirsof100 Files in subdirs, each with up to 100 files - 18658 files/s subdirsof250 Files in subdirs, each with up to 250 files - 17765 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 10673 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 10719 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 10763 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 1000 files of 8192 bytes - - 18659 files/s onedir All files in one directory - 19490 files/s subdirsof100 Files in subdirs, each with up to 100 files - 17477 files/s subdirsof250 Files in subdirs, each with up to 250 files - 17948 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 11172 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 10809 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 10212 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 2000 files of 8192 bytes - - 18249 files/s onedir All files in one directory - 19500 files/s subdirsof100 Files in subdirs, each with up to 100 files - 18248 files/s subdirsof250 Files in subdirs, each with up to 250 files - 17029 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 10853 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 10562 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 10424 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 4000 files of 8192 bytes - - 17060 files/s onedir All files in one directory - 18711 files/s subdirsof100 Files in subdirs, each with up to 100 files - 17258 files/s subdirsof250 Files in subdirs, each with up to 250 files - 16282 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 9925 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 10461 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 10164 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 8000 files of 8192 bytes - - 16615 files/s onedir All files in one directory - 18280 files/s subdirsof100 Files in subdirs, each with up to 100 files - 18477 files/s subdirsof250 Files in subdirs, each with up to 250 files - 17209 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 10573 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 10560 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 10102 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 16000 files of 8192 bytes - - 15661 files/s onedir All files in one directory - 19164 files/s subdirsof100 Files in subdirs, each with up to 100 files - 18020 files/s subdirsof250 Files in subdirs, each with up to 250 files - 16883 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 10678 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 10305 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 10060 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 32000 files of 8192 bytes - - 16703 files/s onedir All files in one directory - 5068 files/s subdirsof100 Files in subdirs, each with up to 100 files - 17810 files/s subdirsof250 Files in subdirs, each with up to 250 files - 16753 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 10521 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 9306 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 9704 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 64000 files of 8192 bytes - - 8254 files/s onedir All files in one directory - 4493 files/s subdirsof100 Files in subdirs, each with up to 100 files - 10132 files/s subdirsof250 Files in subdirs, each with up to 250 files - 9293 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 9015 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 10250 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 8196 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 128000 files of 8192 bytes - - 5450 files/s onedir All files in one directory - 5504 files/s subdirsof100 Files in subdirs, each with up to 100 files - 5132 files/s subdirsof250 Files in subdirs, each with up to 250 files - 3632 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 6036 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 6438 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 6124 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 256000 files of 8192 bytes - - 3934 files/s onedir All files in one directory - 4512 files/s subdirsof100 Files in subdirs, each with up to 100 files - 4862 files/s subdirsof250 Files in subdirs, each with up to 250 files - 4884 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 4759 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 4793 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 4859 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 512000 files of 8192 bytes - - 3896 files/s onedir All files in one directory - 2877 files/s subdirsof100 Files in subdirs, each with up to 100 files - 3482 files/s subdirsof250 Files in subdirs, each with up to 250 files - 3635 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 3426 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 3750 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 3865 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 1024000 files of 8192 bytes - - 3826 files/s onedir All files in one directory - 2922 files/s subdirsof100 Files in subdirs, each with up to 100 files - 3340 files/s subdirsof250 Files in subdirs, each with up to 250 files - 3487 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 3076 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 3731 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 3703 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 10 files of 16384 bytes - - 15104 files/s onedir All files in one directory - 14559 files/s subdirsof100 Files in subdirs, each with up to 100 files - 14619 files/s subdirsof250 Files in subdirs, each with up to 250 files - 14533 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 9310 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 9243 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 9259 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 1000 files of 16384 bytes - - 14222 files/s onedir All files in one directory - 14999 files/s subdirsof100 Files in subdirs, each with up to 100 files - 14608 files/s subdirsof250 Files in subdirs, each with up to 250 files - 13958 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 9369 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 9190 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 8849 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 2000 files of 16384 bytes - - 13653 files/s onedir All files in one directory - 14240 files/s subdirsof100 Files in subdirs, each with up to 100 files - 13868 files/s subdirsof250 Files in subdirs, each with up to 250 files - 13063 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 8971 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 8574 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 8931 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 4000 files of 16384 bytes - - 13586 files/s onedir All files in one directory - 14100 files/s subdirsof100 Files in subdirs, each with up to 100 files - 13760 files/s subdirsof250 Files in subdirs, each with up to 250 files - 12727 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 8825 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 8567 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 7580 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 8000 files of 16384 bytes - - 13429 files/s onedir All files in one directory - 14343 files/s subdirsof100 Files in subdirs, each with up to 100 files - 13183 files/s subdirsof250 Files in subdirs, each with up to 250 files - 12703 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 9021 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 9018 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 8445 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 16000 files of 16384 bytes - - 12358 files/s onedir All files in one directory - 13828 files/s subdirsof100 Files in subdirs, each with up to 100 files - 13826 files/s subdirsof250 Files in subdirs, each with up to 250 files - 13549 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 8919 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 8951 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 8736 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 32000 files of 16384 bytes - - 7278 files/s onedir All files in one directory - 8634 files/s subdirsof100 Files in subdirs, each with up to 100 files - 9575 files/s subdirsof250 Files in subdirs, each with up to 250 files - 9640 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 9092 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 8398 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 8670 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 64000 files of 16384 bytes - - 3188 files/s onedir All files in one directory - 2988 files/s subdirsof100 Files in subdirs, each with up to 100 files - 3205 files/s subdirsof250 Files in subdirs, each with up to 250 files - 3400 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 3310 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 3233 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 3392 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 128000 files of 16384 bytes - - 2506 files/s onedir All files in one directory - 2420 files/s subdirsof100 Files in subdirs, each with up to 100 files - 2596 files/s subdirsof250 Files in subdirs, each with up to 250 files - 2671 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 2489 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 2191 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 2496 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 256000 files of 16384 bytes - - 2098 files/s onedir All files in one directory - 2010 files/s subdirsof100 Files in subdirs, each with up to 100 files - 2093 files/s subdirsof250 Files in subdirs, each with up to 250 files - 2084 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 2148 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 2208 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 2085 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 512000 files of 16384 bytes - - 2031 files/s onedir All files in one directory - 1585 files/s subdirsof100 Files in subdirs, each with up to 100 files - 1930 files/s subdirsof250 Files in subdirs, each with up to 250 files - 1996 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 1924 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 1984 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 2001 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - -Measuring 7 functions for creating 1024000 files of 16384 bytes - - 2002 files/s onedir All files in one directory - 1689 files/s subdirsof100 Files in subdirs, each with up to 100 files - 1927 files/s subdirsof250 Files in subdirs, each with up to 250 files - 1980 files/s subdirsof1000 Files in subdirs, each with up to 1000 files - 1747 files/s subsubdirsof100 Files in two-level tree, up to 100 files each - 1959 files/s subsubdirsof250 Files in two-level tree, up to 250 files each - 1954 files/s subsubdirsof1000 Files in two-level tree, up to 1000 files each - - diff --git a/createfiles.py b/createfiles.py deleted file mode 100755 index 3a46c53..0000000 --- a/createfiles.py +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/python - -# Create lots of (empty) files in various ways, to see which way is fastest. - - -import errno -import gc -import os -import optparse -import shutil -import sys -import timeit - - -ROOT = "create.tmp" - - -def create_dir(dirname): - full_name = os.path.join(ROOT, dirname) - try: - os.mkdir(full_name) - except os.error, e: - if e.errno != errno.EEXIST: - raise e - -def create_file(filename, size): - full_name = os.path.join(ROOT, filename) - f = file(full_name, "w") - f.write("x" * size) - f.close() - -def cleanup(): - while os.path.exists(ROOT): - try: - shutil.rmtree(ROOT) - except os.error, e: - if e.errno != errno.ENOENT: - raise e - os.mkdir(ROOT) - -def onedir(count, size): - """All files in one directory""" - for i in range(count): - create_file("%d" % i, size) - -def subdirsofN(N, count, size): - prev_subdir = None - for i in range(count): - subdir = i / N - if subdir != prev_subdir: - create_dir("%d" % subdir) - prev_subdir = subdir - create_file("%d/%d" % (subdir, i), size) - -def subdirsof100(count, size): - """Files in subdirs, each with up to 100 files""" - subdirsofN(100, count, size) - -def subdirsof250(count, size): - """Files in subdirs, each with up to 250 files""" - subdirsofN(250, count, size) - -def subdirsof1000(count, size): - """Files in subdirs, each with up to 1000 files""" - subdirsofN(1000, count, size) - -def subsubdirsofN(N, count, size): - prev = None - for i in range(count): - subsubdir = i / N - subdir = subsubdir / N - if (subdir, subsubdir) != prev: - create_dir("%d" % subdir) - create_dir("%d/%d" % (subdir, subsubdir)) - prev_subdir = (subdir, subsubdir) - create_file("%d/%d/%d" % (subdir, subsubdir, i), size) - -def subsubdirsof100(count, size): - """Files in two-level tree, up to 100 files each""" - subsubdirsofN(100, count, size) - -def subsubdirsof250(count, size): - """Files in two-level tree, up to 250 files each""" - subsubdirsofN(250, count, size) - -def subsubdirsof1000(count, size): - """Files in two-level tree, up to 1000 files each""" - subsubdirsofN(1000, count, size) - -funcs = [ - onedir, # disabled, because it exposes a bug in ext3+dir_index - subdirsof100, - subdirsof250, - subdirsof1000, - subsubdirsof100, - subsubdirsof250, - subsubdirsof1000, - ] - -def measure(func, count, size): - cleanup() - gc.collect() - timer = timeit.Timer(stmt='%s(%d, %d)' % (func.func_name, count, size), - setup="from __main__ import %s" % func.func_name) - return timer.timeit(number=1) - -def check(func, count, size): - cleanup() - func(count, size) - actual_count = 0 - for dirname, _, filenames in os.walk(ROOT): - actual_count += len(filenames) - for name in [os.path.join(dirname, x) for x in filenames]: - actual_size = os.path.getsize(name) - assert size == actual_size, \ - "size is %d, should be %d" % (actual_size, size) - assert count == actual_count, \ - "count=%d and actual_count=%d should be identical" % \ - (count, actual_count) - -def parse_args(args): - p = optparse.OptionParser() - - p.add_option("-c", "--check", action="store_true", default=False, - help="Check that all functions actually work") - p.add_option("-s", "--size", action="store", type="int", metavar="SIZE", - default=0, help="Create files of SIZE bytes (default: 0)") - - return p.parse_args(args) - - -def main(): - options, counts = parse_args(sys.argv[1:]) - - if counts: - counts = [int(x) for x in counts] - else: - counts = [10000] - - for count in counts: - print "Measuring %d functions for creating %d files of %d bytes" % \ - (len(funcs), count, options.size) - print - - namelen = max(len(func.func_name) for func in funcs) - - for func in funcs: - if options.check: - check(func, count, options.size) - secs = measure(func, count, options.size) - speed = count/secs - print "%6.0f files/s %-*s %s" % \ - (speed, namelen, func.func_name, func.__doc__) - sys.stdout.flush() - print - print - - cleanup() - os.rmdir(ROOT) - -if __name__ == "__main__": - main() diff --git a/genbackupdata.py b/genbackupdata.py deleted file mode 100644 index 2fbb416..0000000 --- a/genbackupdata.py +++ /dev/null @@ -1,660 +0,0 @@ -# Copyright (C) 2007 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 2 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, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - -"""Generate backup test data""" - - -import hashlib -import optparse -import os -import random -import sys - - -KiB = 2 ** 10 # A kibibyte -MiB = 2 ** 20 # A mebibyte -GiB = 2 ** 30 # A gibibyte -TiB = 2 ** 40 # A tebibyte - -# Defaults for various settings in the BackupData class. -DEFAULT_SEED = 0 -DEFAULT_BINARY_CHUNK_SIZE = KiB -DEFAULT_TEXT_FILE_SIZE = 10 * KiB -DEFAULT_BINARY_FILE_SIZE = 10 * MiB -DEFAULT_TEXT_DATA_PERCENTAGE = 10.0 -DEFAULT_MAX_FILES_PER_DIRECTORY = 256 -DEFAULT_MODIFY_PERCENTAGE = 10 - -# Random filler text for generating text data. -if True: #pragma: no cover: - LOREM_IPSUM = """ -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim -veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea -commodo consequat. Duis aute irure dolor in reprehenderit in voluptate -velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint -occaecat cupidatat non proident, sunt in culpa qui officia deserunt -mollit anim id est laborum. -""" - - -class BackupData: - - """This class represents the directory with backup data""" - - def __init__(self): - self._dirname = None - self._seed = 0 - self._prng = None - self._chunk_size = DEFAULT_BINARY_CHUNK_SIZE - self._text_file_size = DEFAULT_TEXT_FILE_SIZE - self._binary_file_size = DEFAULT_BINARY_FILE_SIZE - self._text_data_percentage = DEFAULT_TEXT_DATA_PERCENTAGE - self._max_files_per_directory = DEFAULT_MAX_FILES_PER_DIRECTORY - self._modify_percentage = DEFAULT_MODIFY_PERCENTAGE - self._preexisting_file_count = 0 - self._preexisting_data_size = 0 - self._filename_counter = 0 - self._current_dir_no = 0 - self._next_filecount = 0 - - # The zlib compression algorithm gives up if it gets a block of - # 32 KiB bytes it can't find in its dictionary. It completely - # ignores such a block, meaning that if it is repeated, then - # it ignores it repeatedly. Most importantly for us, it doesn't - # compress the repeats, either. Thus, to generate lots of - # uncompressible binary data, we can generate a blob and repeat - # that. Thanks to Richard Braakman for the idea. - self._binary_blob_size = 64 * 1024 # Safety factor of 2 - self._binary_blob = None - - def set_directory(self, dirname): - """Set the directory to be operated on - - Note that this must be set exactly once. Setting it twice will cause - an assertion error, and not setting it will cause other errors. - - """ - - assert self._dirname is None - self._dirname = dirname - - def get_directory(self): - """Return the directory being operated on, or None if not set""" - return self._dirname - - def create_directory(self): - """Create the backup data directory, if it doesn't exist already""" - if not os.path.exists(self._dirname): - os.mkdir(self._dirname) - - def get_seed(self): - """Return the initial seed for the pseudo-random number generator""" - return self._seed - - def set_seed(self, seed): - """Set the initial seed for the pseudo-random number generator - - The seed will be used when the generator is first initialized. - It is initialized implicitly as soon as something in this class - needs randomness. Setting the seed after the generator has been - initialized causes an assertion failure. - - """ - - assert self.get_prng() is None - self._seed = seed - - def get_prng(self): - """Return reference to the psuedo-random number generator being used - - Return None, if one hasn't be initialized yet. - - """ - - return self._prng - - def init_prng(self): - """Initialize the psuedo-random number generator (using seed)""" - if self._prng is None: - self._prng = random.Random() - self._prng.seed(self._seed) - - def get_text_file_size(self): - """Return size of newly created text files""" - return self._text_file_size - - def set_text_file_size(self, size): - """Set size of newly created text files""" - self._text_file_size = size - - def get_binary_file_size(self): - """Return size of newly created binary files""" - return self._binary_file_size - - def set_binary_file_size(self, size): - """Set size of newly created binary files""" - self._binary_file_size = size - - def get_text_data_percentage(self): - """Return percentage of text data of new data that gets created""" - return self._text_data_percentage - - def set_text_data_percentage(self, percent): - """Set percentage of text data of new data that gets created""" - self._text_data_percentage = percent - - def get_max_files_per_directory(self): - """Return current setting of maximum number of files per directory""" - return self._max_files_per_directory - - def set_max_files_per_directory(self, count): - """Set maximum number of files per directory""" - self._max_files_per_directory = count - - def get_preexisting_file_count(self): - """Return count of files that existed in directory in the beginning""" - return self._preexisting_file_count - - def set_preexisting_file_count(self, count): - """Set count of files that existed in directory in the beginning - - This is useful only for unit tests. - - """ - self._preexisting_file_count = count - - def get_preexisting_data_size(self): - """Return size of data that existed in directory in the beginning""" - return self._preexisting_data_size - - def set_preexisting_data_size(self, size): - """Set size of data that existed in directory in the beginning - - This is useful only for unit tests. - - """ - self._preexisting_data_size = size - - def get_relative_file_count(self, percent): - """Return PERCENT percent of pre-existing file count""" - return int(0.01 * percent * self.get_preexisting_file_count()) - - def get_relative_data_size(self, percent): - """Return PERCENT percent of pre-existing data""" - return int(0.01 * percent * self.get_preexisting_data_size()) - - def find_preexisting_files(self): - """Find all the files that exists in the directory right now""" - count = 0 - size = 0 - if os.path.exists(self._dirname): - for root, dirs, filenames in os.walk(self._dirname): - count += len(filenames) - for filename in filenames: - size += os.path.getsize(os.path.join(root, filename)) - self.set_preexisting_file_count(count) - self.set_preexisting_data_size(size) - - def _choose_directory(self): - """Choose directory in which to create the next file""" - - while True: - dirname = os.path.join(self._dirname, - "dir%d" % self._current_dir_no) - if not os.path.exists(dirname): - self._next_filecount = 0 - break - if (self._next_filecount > 0 and - self._next_filecount < self._max_files_per_directory): - break - self._current_dir_no += 1 - return dirname - - def next_filename(self): - """Choose the name of the next filename - - The file does not currently exist. This is not, however, a guarantee - that no other process won't create it before we do. Thus, this - is NOT a secure way to create temporary files. But it's good enough - for our intended purpose. - - For simplified unit testing, the names are very easily predictable, - but it is probably a bad idea for external code to rely on this. - - """ - - dirname = self._choose_directory() - while True: - filename = os.path.join(dirname, - "file%d" % self._filename_counter) - if not os.path.exists(filename): - self._next_filecount += 1 - return filename - self._filename_counter += 1 - - def generate_text_data(self, size): - """Generate SIZE characters of text data""" - if size <= len(LOREM_IPSUM): - return LOREM_IPSUM[:size] - else: - full = size / len(LOREM_IPSUM) - rest = size % len(LOREM_IPSUM) - return "".join(([LOREM_IPSUM] * full) + [LOREM_IPSUM[:rest]]) - - def generate_binary_data_well(self, size): - """Generate SIZE bytes of more or less random binary junk""" - - # The following code has had some fine manual fine tuning done - # to it. This has made it a bit ugly, but faster. On a - # "Intel(R) Core(TM)2 Duo CPU L9400 @ 1.86GHz", it produces - # about 25 MB/s. - - chunks = [] - sum = hashlib.sha1() - chunk_size = len(sum.digest()) - - initial_bytes = min(size, 128) - for i in range(initial_bytes / chunk_size): - sum.update(chr(random.getrandbits(8))) - chunk = sum.digest() - chunks.append(chunk) - - size -= len(chunks) * chunk_size - for i in range(size / chunk_size): - sum.update("a") - chunk = sum.digest() - chunks.append(chunk) - - if size % chunk_size > 0: - sum.update(chr(random.getrandbits(8))) - chunk = sum.digest() - chunks.append(chunk[:size % chunk_size]) - - return "".join(chunks) - - - def generate_binary_data(self, size): - """Generate SIZE bytes of binary junk. - - This is different from generate_binary_data_well in that - it makes use of _binary_blob (and generates that if it does - not yet exist). - - """ - - if self._binary_blob is None: - self._binary_blob = self.generate_binary_data_well( - self._binary_blob_size) - if size <= len(self._binary_blob): - return self._binary_blob[:size] - else: - full = size / len(self._binary_blob) - rest = size % len(self._binary_blob) - return "".join(([self._binary_blob] * full) + - [self._binary_blob[:rest]]) - - def create_subdirectories(self, filename): - """Create the sub-directories that are needed to create filename""" - subdir = os.path.dirname(filename) - if not os.path.exists(subdir): - os.makedirs(subdir) - - def create_text_file(self, size): - """Create a new text file of the desired size""" - filename = self.next_filename() - self.create_subdirectories(filename) - f = file(filename, "w") - f.write(self.generate_text_data(size)) - f.close() - - def get_binary_chunk_size(self): - """Return the size of chunks used when writing binary data""" - return self._chunk_size - - def set_binary_chunk_size(self, size): - """Set the size of chunks used when writing binary data""" - self._chunk_size = size - - def create_binary_file(self, size): - """Create a new binary file of the desired size""" - filename = self.next_filename() - self.create_subdirectories(filename) - f = file(filename, "w") - # We write the data in chunks, so as not to keep the entire file - # contents in memory at a time. Since the size may be very large, - # we might otherwise run out of swap. - while size >= self._chunk_size: - f.write(self.generate_binary_data(self._chunk_size)) - size -= self._chunk_size - f.write(self.generate_binary_data(size)) - f.close() - - def _create_files_of_a_kind(self, size, file_size, create_one): - """Create files with create_one""" - while size > 0: - this_size = min(size, file_size) - create_one(this_size) - size -= this_size - - def create_files(self, size): - """Create new files, totalling SIZE bytes in size""" - text_size = int(0.01 * self._text_data_percentage * size) - bin_size = size - text_size - - self._create_files_of_a_kind(text_size, self.get_text_file_size(), - self.create_text_file) - self._create_files_of_a_kind(bin_size, self.get_binary_file_size(), - self.create_binary_file) - - def find_files(self): - """Find all non-directory files in the test data set""" - files = [] - for root, dirs, filenames in os.walk(self._dirname): - for filename in filenames: - files.append(os.path.join(root, filename)) - return files - - def choose_files_randomly(self, count): - """Choose COUNT files randomly""" - files = self.find_files() - if len(files) >= count: - self.init_prng() - files = self._prng.sample(files, count) - return files - - def delete_files(self, count): - """Delete COUNT files""" - if os.path.exists(self._dirname): - for file in self.choose_files_randomly(count): - os.remove(file) - - def rename_files(self, count): - """Rename COUNT files to new names""" - if os.path.exists(self._dirname): - for file in self.choose_files_randomly(count): - new_file = self.next_filename() - self.create_subdirectories(new_file) - os.rename(file, new_file) - - def link_files(self, count): - """Create COUNT new filenames that are hard links to existing files""" - if os.path.exists(self._dirname): - for file in self.choose_files_randomly(count): - new_file = self.next_filename() - self.create_subdirectories(new_file) - os.link(file, new_file) - - def get_modify_percentage(self): - """Return how many percent to grow each file with modify_files()""" - return self._modify_percentage - - def set_modify_percentage(self, percent): - """Set how many percent to grow each file with modify_files()""" - self._modify_percentage = percent - - def append_data(self, filename, data): - """Append data to a file""" - f = file(filename, "a") - f.write(data) - f.close() - - def _modify_files_of_a_kind(self, filenames, size, generate_data): - """Modify files by appending data to them""" - while size > 0: - filename = self._prng.choice(filenames) - this_size = os.path.getsize(filename) - amount = min(int(0.01 * self._modify_percentage * this_size), - size) - self.append_data(filename, generate_data(amount)) - size -= amount - - def modify_files(self, size): - """Modify existing files by appending to them - - SIZE gives the total amount of new data for all files. - Files are chosen at random, and new data is appended to them. - The amount appended to each file is set by - set_modify_percentage. The data is split between text and - binary data according to set_text_data_percentage. - - """ - - if os.path.exists(self._dirname): - files = self.find_files() - - text_size = int(0.01 * self._text_data_percentage * size) - bin_size = size - text_size - - self.init_prng() - self._modify_files_of_a_kind(files, text_size, - self.generate_text_data) - self._modify_files_of_a_kind(files, bin_size, - self.generate_binary_data) - - - -class CommandLineParser: - - """Parse the command line for the genbackupdata utility""" - - def __init__(self, backup_data): - self._bd = backup_data - self._parser = self._create_option_parser() - - def _create_option_parser(self): - """Create the OptionParser we need""" - - p = optparse.OptionParser() - - p.add_option("--seed", - help="Set pseudo-random number generator seed to SEED") - - p.add_option("--max-count", - action="store", - metavar="COUNT", - help="Allow at most COUNT files per directory") - - p.add_option("-p", "--percentage-text-data", - action="store", - metavar="PERCENT", - help="Make PERCENT of new data textual, not binary") - - p.add_option("-t", "--text-file-size", - action="store", - metavar="SIZE", - help="Make new text files be of size SIZE") - - p.add_option("-b", "--binary-file-size", - action="store", - metavar="SIZE", - help="Make new binary files be of size SIZE") - - p.add_option("-c", "--create", - action="store", - metavar="SIZE", - help="Create SIZE amount of new files") - - p.add_option("-d", "--delete", - action="store", - metavar="COUNT", - help="Delete COUNT files") - - p.add_option("-r", "--rename", - action="store", - metavar="COUNT", - help="Rename COUNT files") - - p.add_option("-l", "--link", - action="store", - metavar="COUNT", - help="Create COUNT new hard links") - - p.add_option("-m", "--modify", - action="store", - metavar="SIZE", - help="Grow total data size by SIZE") - - p.add_option("--modify-percentage", - action="store", - metavar="PERCENT", - help="Increase file size by PERCENT") - - return p - - def parse_size(self, size, base_size=None): - """Parse a SIZE argument (absolute, relative, with/without suffix)""" - - suffixes = (("k", KiB), ("m", MiB), ("g", GiB), ("t", TiB)) - - for suffix, factor in suffixes: - if size.lower().endswith(suffix): - return int(float(size[:-len(suffix)]) * factor) - - if size.endswith("%"): - if base_size is None: - return 0 - else: - return int(float(size[:-1]) * 0.01 * base_size) - - return int(size) - - def parse_count(self, count, base_count=None): - """Parse a COUNT argument (absolute, relative, with/without suffix)""" - - suffixes = (("k", 10**3), ("m", 10**6), ("g", 10**9), ("t", 10**12)) - - for suffix, factor in suffixes: - if count.lower().endswith(suffix): - return int(float(count[:-len(suffix)]) * factor) - - if count.endswith("%"): - if base_count is None: - return 0 - else: - return int(float(count[:-1]) * 0.01 * base_count) - - return int(count) - - def parse(self, args): - """Parse command line arguments""" - options, args = self._parser.parse_args(args) - - if len(args) == 1: - self._bd.set_directory(args[0]) - self._bd.find_preexisting_files() - - if options.seed: - self._bd.set_seed(int(options.seed)) - - if options.max_count: - self._bd.set_max_files_per_directory(int(options.max_count)) - - if options.percentage_text_data: - self._bd.set_text_data_percentage( - float(options.percentage_text_data)) - - if options.modify_percentage: - self._bd.set_modify_percentage(float(options.modify_percentage)) - - if options.text_file_size: - self._bd.set_text_file_size( - self.parse_size(options.text_file_size)) - - if options.binary_file_size: - self._bd.set_binary_file_size( - self.parse_size(options.binary_file_size)) - - if options.create: - options.create = self.parse_size(options.create, - self._bd.get_preexisting_data_size()) - - if options.modify: - options.modify = self.parse_size(options.modify, - self._bd.get_preexisting_data_size()) - - if options.delete: - options.delete = self.parse_count(options.delete, - self._bd.get_preexisting_file_count()) - - if options.rename: - options.rename = self.parse_count(options.rename, - self._bd.get_preexisting_file_count()) - - if options.link: - options.link = self.parse_count(options.link, - self._bd.get_preexisting_file_count()) - - return options, args - - -class AppException(Exception): - - def __str__(self): - return self._str - - -class NeedExactlyOneDirectoryName(AppException): - - def __init__(self): - self._str = ("Need exactly one command line argument, " - "giving directory name") - - -class Application: - - """The main program""" - - def __init__(self, args): - self._args = args - self._bd = BackupData() - self._clp = CommandLineParser(self._bd) - self._error = sys.stderr.write - - def set_error_writer(self, writer): - self._error = writer - - def run(self): - """Execute the desired operations""" - try: - options, args = self._clp.parse(self._args) - - if len(args) != 1: - raise NeedExactlyOneDirectoryName() - - if options.delete: - self._bd.delete_files(options.delete) - - if options.rename: - self._bd.rename_files(options.rename) - - if options.link: - self._bd.link_files(options.link) - - if options.modify: - self._bd.modify_files(options.modify) - - if options.create: - self._bd.create_files(options.create) - - except AppException, e: - self._error(str(e) + "\n") - sys.exit(1) - - -if __name__ == "__main__": #pragma: no cover - Application(sys.argv[1:]).run() diff --git a/tests.py b/tests.py deleted file mode 100755 index 4466fc0..0000000 --- a/tests.py +++ /dev/null @@ -1,565 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2007 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 2 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, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - -"""Unit tests for genbackupdata.py""" - - -import os -import shutil -import unittest -import zlib - -import genbackupdata - - -class BackupDataTests(unittest.TestCase): - - dirname = "tests.dir" - - def remove_dir(self): - """Remove a directory, if it exists""" - if os.path.exists(self.dirname): - shutil.rmtree(self.dirname) - - def create(self, filename, contents): - """Create a new file with the desired contents""" - dirname = os.path.dirname(filename) - if not os.path.exists(dirname): - os.makedirs(dirname) - f = file(filename, "w") - f.write(contents) - f.close() - - def read_file(self, filename): - """Return the entire contents of a file""" - f = file(filename) - data = f.read() - f.close() - return data - - def setUp(self): - self.remove_dir() - self.bd = genbackupdata.BackupData() - self.bd.set_directory(self.dirname) - - def tearDown(self): - del self.bd - self.remove_dir() - - def testSetsDirectoryCorrect(self): - self.failUnlessEqual(self.bd.get_directory(), self.dirname) - - def testDoesNotCreateDirectoryAtOnce(self): - self.failIf(os.path.exists(self.dirname)) - - def testCreatesDirectory(self): - self.bd.create_directory() - self.failUnless(os.path.exists(self.dirname)) - - def testDoesNotFailWhenCreatingDirectoryWhenItExistsAlready(self): - self.bd.create_directory() - self.bd.create_directory() - - def testHasCorrectDefaultSeed(self): - self.failUnlessEqual(self.bd.get_seed(), genbackupdata.DEFAULT_SEED) - - def testCorrectlySetsSeed(self): - self.bd.set_seed(12765) - self.failUnlessEqual(self.bd.get_seed(), 12765) - - def testHasNoPRNGInitially(self): - self.failUnlessEqual(self.bd.get_prng(), None) - - def testCreatesPRNGWhenRequested(self): - self.bd.init_prng() - self.failIfEqual(self.bd.get_prng(), None) - - def testFailsIfSeedGetsSetAfterPRNGHasBeenCreatedTwice(self): - self.bd.init_prng() - self.failUnlessRaises(AssertionError, self.bd.set_seed, 12765) - - def testHasCorrectDefaultBinaryChunkSize(self): - self.failUnlessEqual(self.bd.get_binary_chunk_size(), - genbackupdata.DEFAULT_BINARY_CHUNK_SIZE) - - def testCorrectlySetsBinaryChunkSize(self): - self.bd.set_binary_chunk_size(12765) - self.failUnlessEqual(self.bd.get_binary_chunk_size(), 12765) - - def testHasCorrectDefaultTextFileSize(self): - self.failUnlessEqual(self.bd.get_text_file_size(), - genbackupdata.DEFAULT_TEXT_FILE_SIZE) - - def testCorrectlySetsTextFileSize(self): - self.bd.set_text_file_size(12765) - self.failUnlessEqual(self.bd.get_text_file_size(), 12765) - - def testHasCorrectDefaultBinaryFileSize(self): - self.failUnlessEqual(self.bd.get_binary_file_size(), - genbackupdata.DEFAULT_BINARY_FILE_SIZE) - - def testCorrectlySetsBinaryFileSize(self): - self.bd.set_binary_file_size(12765) - self.failUnlessEqual(self.bd.get_binary_file_size(), 12765) - - def testHasCorrectDefaultTextDataPercentage(self): - self.failUnlessEqual(self.bd.get_text_data_percentage(), - genbackupdata.DEFAULT_TEXT_DATA_PERCENTAGE) - - def testCorrectlySetsTextDataPercentage(self): - self.bd.set_text_data_percentage(42.0) - self.failUnlessEqual(self.bd.get_text_data_percentage(), 42.0) - - def testHasCorrectDefaultMaxFilesPerDirectory(self): - self.failUnlessEqual(self.bd.get_max_files_per_directory(), - genbackupdata.DEFAULT_MAX_FILES_PER_DIRECTORY) - - def testCorrectlySetsMaxFilesPerDirectory(self): - self.bd.set_max_files_per_directory(12765) - self.failUnlessEqual(self.bd.get_max_files_per_directory(), 12765) - - def testSetsPreExistingFileCountToZeroByDefault(self): - self.failUnlessEqual(self.bd.get_preexisting_file_count(), 0) - - def testCanFakePreExistingFileCount(self): - self.bd.set_preexisting_file_count(12765) - self.failUnlessEqual(self.bd.get_preexisting_file_count(), 12765) - - def testSetsPreExistingDataSizeToZeroByDefault(self): - self.failUnlessEqual(self.bd.get_preexisting_data_size(), 0) - - def testCanFakePreExistingDataSize(self): - self.bd.set_preexisting_data_size(12765) - self.failUnlessEqual(self.bd.get_preexisting_data_size(), 12765) - - def testFindsPreExistingFilesAndDAtaCorrectly(self): - file_count = 10 - file_size = self.bd.get_text_file_size() - data = self.bd.generate_text_data(file_size) - for i in range(file_count): - self.create(self.bd.next_filename(), data) - self.bd.find_preexisting_files() - self.failUnlessEqual(self.bd.get_preexisting_file_count(), file_count) - self.failUnlessEqual(self.bd.get_preexisting_data_size(), - file_count * file_size) - - def testComputesRelativeFileCountCorrectly(self): - self.bd.set_preexisting_file_count(12765) - self.failUnlessEqual(self.bd.get_relative_file_count(10), 1276) - - def testComputesRelativeDataSizeCorrectly(self): - self.bd.set_preexisting_data_size(12765) - self.failUnlessEqual(self.bd.get_relative_data_size(10), 1276) - - def testFindsNoPreExistingFilesWhenDirectoryDoesNotExist(self): - self.bd.find_preexisting_files() - self.failUnlessEqual(self.bd.get_preexisting_file_count(), 0) - - def testFindsNoPreExistingDataWhenDirectoryDoesNotExist(self): - self.bd.find_preexisting_files() - self.failUnlessEqual(self.bd.get_preexisting_data_size(), 0) - - def testChoosesFirstFilenameCorrectly(self): - filename = self.bd.next_filename() - self.failUnless(filename.startswith(self.dirname)) - - def testChoosesFirstFilenameCorrectlyTwice(self): - filename1 = self.bd.next_filename() - filename2 = self.bd.next_filename() - self.failUnlessEqual(filename1, filename2) - - def testChoosesFilenameCorrectlyWhenFirstOneExistsAlready(self): - self.bd.create_directory() - filename1 = self.bd.next_filename() - self.create(filename1, "") - filename2 = self.bd.next_filename() - self.failIfEqual(filename1, filename2) - - def testChoosesSameDirectoryUntilMaxFileLimitIsReached(self): - self.bd.set_max_files_per_directory(10) # For speed - self.bd.create_directory() - chosen = self.bd._choose_directory() - for i in range(self.bd.get_max_files_per_directory()): - self.failUnlessEqual(self.bd._choose_directory(), chosen) - self.create(self.bd.next_filename(), "") - - def testChoosesNewDirectoryWhenMaxFileLimitIsReached(self): - self.bd.set_max_files_per_directory(10) # For speed - self.bd.create_directory() - chosen = self.bd._choose_directory() - for i in range(self.bd.get_max_files_per_directory()): - self.create(self.bd.next_filename(), "") - self.failIfEqual(self.bd._choose_directory(), chosen) - - def testGeneratesSmallAmountOfTextDataCorrectly(self): - n = 128 - self.failUnlessEqual(self.bd.generate_text_data(n), - genbackupdata.LOREM_IPSUM[:n]) - - def testGeneratesLargeAmountOfTextDataCorrectly(self): - n = len(genbackupdata.LOREM_IPSUM) - self.failUnlessEqual(self.bd.generate_text_data(n * 2), - genbackupdata.LOREM_IPSUM * 2) - - def testGeneratesRequestedAmountOfBinaryDataWell(self): - n = 37 - self.failUnlessEqual(len(self.bd.generate_binary_data_well(n)), n) - - def testGeneratesRequestedAmountOfBinaryDataQuickly(self): - n = 128 - self.failUnlessEqual(len(self.bd.generate_binary_data(n)), n) - - def testGeneratesRequestedLargeAmountOfBinaryData(self): - n = self.bd._binary_blob_size + 1 - self.failUnlessEqual(len(self.bd.generate_binary_data(n)), n) - - def testGeneratesBinaryDataWhichDoesNotCompressWell(self): - n = self.bd._binary_blob_size * 4 - data = zlib.compress(self.bd.generate_binary_data(n)) - self.failUnless(len(data) > 0.95* n) - - def testCreatesSubdirectoriesCorrectly(self): - filename = os.path.join(self.dirname, "subdir", "filename") - self.bd.create_subdirectories(filename) - self.failUnless(os.path.isdir(os.path.dirname(filename))) - - def testCreatesTextFileCorrectly(self): - size = self.bd.get_text_file_size() - filename = self.bd.next_filename() - self.bd.create_text_file(size) - self.failUnless(os.path.isfile(filename)) - self.failUnlessEqual(self.read_file(filename), - self.bd.generate_text_data(size)) - - def testCreatesBinaryFileCorrectly(self): - size = self.bd.get_binary_chunk_size() + 1 - filename = self.bd.next_filename() - self.bd.create_binary_file(size) - self.failUnless(os.path.isfile(filename)) - self.failUnlessEqual(os.path.getsize(filename), size) - - def failUnlessTextFile(self, filename): - data = self.read_file(filename) - self.failUnlessEqual(data, self.bd.generate_text_data(len(data))) - - def testCreatesTextFilesOnlyCorrectly(self): - self.bd.set_text_data_percentage(100) - count = 10 - size = count * self.bd.get_text_file_size() - self.bd.create_files(size) - self.bd.find_preexisting_files() - self.failUnlessEqual(self.bd.get_preexisting_file_count(), count) - self.failUnlessEqual(self.bd.get_preexisting_data_size(), size) - for root, dirs, filenames in os.walk(self.dirname): - for filename in filenames: - pathname = os.path.join(root, filename) - self.failUnlessTextFile(pathname) - - def failIfTextFile(self, filename): - data = self.read_file(filename) - self.failIfEqual(data, self.bd.generate_text_data(len(data))) - - def testCreatesNoTextFilesCorrectly(self): - self.bd.set_text_data_percentage(0) - count = 1 - size = count * self.bd.get_text_file_size() - self.bd.create_files(size) - self.bd.find_preexisting_files() - self.failUnlessEqual(self.bd.get_preexisting_file_count(), 1) - self.failUnlessEqual(self.bd.get_preexisting_data_size(), size) - for root, dirs, filenames in os.walk(self.dirname): - for filename in filenames: - pathname = os.path.join(root, filename) - self.failIfTextFile(pathname) - - def testDeletesFilesCorrectly(self): - size = 100 - self.bd.set_text_file_size(1) - self.bd.set_binary_file_size(1) - self.bd.create_files(size) - self.bd.find_preexisting_files() - count = self.bd.get_preexisting_file_count() - to_delete = count/3 - remaining = count - to_delete - self.bd.delete_files(to_delete) - self.bd.find_preexisting_files() - self.failUnlessEqual(self.bd.get_preexisting_file_count(), remaining) - - def testRenamesFilesCorrectly(self): - self.bd.create_directory() - filename = self.bd.next_filename() - self.create(filename, "") - new_filename = self.bd.next_filename() - self.bd.rename_files(1) - self.failIf(os.path.exists(filename)) - self.failUnless(os.path.exists(new_filename)) - - def testCreatesLinksCorrectly(self): - self.bd.create_directory() - filename = self.bd.next_filename() - self.create(filename, "") - new_filename = self.bd.next_filename() - self.bd.link_files(1) - self.failUnless(os.path.samefile(filename, new_filename)) - - def testHasCorrectDefaultModifyPercentage(self): - self.failUnlessEqual(self.bd.get_modify_percentage(), - genbackupdata.DEFAULT_MODIFY_PERCENTAGE) - - def testCorrectlySetsModifyPercentage(self): - self.bd.set_modify_percentage(42.0) - self.failUnlessEqual(self.bd.get_modify_percentage(), 42.0) - - def testModifyFiles(self): - size = 100 - self.bd.create_directory() - filename = self.bd.next_filename() - orig_data = "x" * size - self.create(filename, orig_data) - self.bd.modify_files(size) - self.failUnlessEqual(len(self.read_file(filename)), 2 * size) - - -class CommandLineParserTests(unittest.TestCase): - - dirname = "tests.dir" - - def setUp(self): - self.bd = genbackupdata.BackupData() - self.bd.set_directory(self.dirname) - self.clp = genbackupdata.CommandLineParser(self.bd) - - def tearDown(self): - del self.bd - del self.clp - - def testDoesNotTouchDefaultsWithEmptyCommandLine(self): - self.failUnlessEqual(self.bd.get_seed(), genbackupdata.DEFAULT_SEED) - self.failUnlessEqual(self.bd.get_binary_chunk_size(), - genbackupdata.DEFAULT_BINARY_CHUNK_SIZE) - self.failUnlessEqual(self.bd.get_text_file_size(), - genbackupdata.DEFAULT_TEXT_FILE_SIZE) - self.failUnlessEqual(self.bd.get_binary_file_size(), - genbackupdata.DEFAULT_BINARY_FILE_SIZE) - self.failUnlessEqual(self.bd.get_text_data_percentage(), - genbackupdata.DEFAULT_TEXT_DATA_PERCENTAGE) - self.failUnlessEqual(self.bd.get_max_files_per_directory(), - genbackupdata.DEFAULT_MAX_FILES_PER_DIRECTORY) - self.failUnlessEqual(self.bd.get_modify_percentage(), - genbackupdata.DEFAULT_MODIFY_PERCENTAGE) - - def testParsesPlainSizeCorrectly(self): - self.failUnlessEqual(self.clp.parse_size("12765"), 12765) - - def testParsesAbsoluteSizeSuffixesCorrectly(self): - self.failUnlessEqual(self.clp.parse_size("3k"), 3 * genbackupdata.KiB) - self.failUnlessEqual(self.clp.parse_size("3K"), 3 * genbackupdata.KiB) - self.failUnlessEqual(self.clp.parse_size("3m"), 3 * genbackupdata.MiB) - self.failUnlessEqual(self.clp.parse_size("3M"), 3 * genbackupdata.MiB) - self.failUnlessEqual(self.clp.parse_size("3g"), 3 * genbackupdata.GiB) - self.failUnlessEqual(self.clp.parse_size("3G"), 3 * genbackupdata.GiB) - self.failUnlessEqual(self.clp.parse_size("3t"), 3 * genbackupdata.TiB) - self.failUnlessEqual(self.clp.parse_size("3T"), 3 * genbackupdata.TiB) - - def testParsesRelativeSizeSuffixCorrectly(self): - self.failUnlessEqual(self.clp.parse_size("10%", 12765), 1276) - - def testParsesRelativeSizeSuffixCorrectlyWithMissingBaseSize(self): - self.failUnlessEqual(self.clp.parse_size("10%"), 0) - - def testParsesPlainCountCorrectly(self): - self.failUnlessEqual(self.clp.parse_count("12765"), 12765) - - def testParsesAbsoluteCountSuffixesCorrectly(self): - self.failUnlessEqual(self.clp.parse_count("3k"), 3 * 10**3) - self.failUnlessEqual(self.clp.parse_count("3K"), 3 * 10**3) - self.failUnlessEqual(self.clp.parse_count("3m"), 3 * 10**6) - self.failUnlessEqual(self.clp.parse_count("3M"), 3 * 10**6) - self.failUnlessEqual(self.clp.parse_count("3g"), 3 * 10**9) - self.failUnlessEqual(self.clp.parse_count("3G"), 3 * 10**9) - self.failUnlessEqual(self.clp.parse_count("3t"), 3 * 10**12) - self.failUnlessEqual(self.clp.parse_count("3T"), 3 * 10**12) - - def testParsesRelativeCountSuffixCorrectly(self): - self.failUnlessEqual(self.clp.parse_count("10%", 12765), 1276) - - def testParsesRelativeCountSuffixCorrectlyWithMissingBaseSize(self): - self.failUnlessEqual(self.clp.parse_count("10%"), 0) - - def testHandlesOptionForSeed(self): - optons, args = self.clp.parse(["--seed=12765"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(self.bd.get_seed(), 12765) - - def testHandlesOptionForMaxCount(self): - options, args = self.clp.parse(["--max-count=12765"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(self.bd.get_max_files_per_directory(), 12765) - - def testHandlesOptionForPercentageTextData(self): - options, args = self.clp.parse(["--percentage-text-data=4.2"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(self.bd.get_text_data_percentage(), 4.2) - - def testHandlesOptionForTextFileSize(self): - options, args = self.clp.parse(["--text-file-size=12765"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(self.bd.get_text_file_size(), 12765) - - def testHandlesOptionForTextFileSizeWithSuffix(self): - options, args = self.clp.parse(["--text-file-size=1t"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(self.bd.get_text_file_size(), genbackupdata.TiB) - - def testHandlesOptionForBinaryFileSizeWithSuffix(self): - options, args = self.clp.parse(["--binary-file-size=1t"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(self.bd.get_binary_file_size(), - genbackupdata.TiB) - - def testHandlesOptionForCreate(self): - options, args = self.clp.parse(["--create=1t"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(options.create, genbackupdata.TiB) - - def testHandlesOptionForCreateWithRelativeSize(self): - self.bd.set_preexisting_data_size(12765) - options, args = self.clp.parse(["--create=10%"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(options.create, 1276) - - def testHandlesOptionForDelete(self): - options, args = self.clp.parse(["--delete=12765"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(options.delete, 12765) - - def testHandlesOptionForDeleteWithRelativeCount(self): - self.bd.set_preexisting_file_count(12765) - options, args = self.clp.parse(["--delete=10%"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(options.delete, 1276) - - def testHandlesOptionForRename(self): - options, args = self.clp.parse(["--rename=12765"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(options.rename, 12765) - - def testHandlesOptionForLink(self): - options, args = self.clp.parse(["--link=12765"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(options.link, 12765) - - def testHandlesOptionForModify(self): - options, args = self.clp.parse(["--modify=12765"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(options.modify, 12765) - - def testHandlesOptionForModifyPercentage(self): - options, args = self.clp.parse(["--modify-percentage=4.2"]) - self.failUnlessEqual(args, []) - self.failUnlessEqual(self.bd.get_modify_percentage(), 4.2) - - -class ApplicationTests(unittest.TestCase): - - dirname = "tests.dir" - - def remove_dir(self): - """Remove a directory, if it exists""" - if os.path.exists(self.dirname): - shutil.rmtree(self.dirname) - - def setUp(self): - self.remove_dir() - - def tearDown(self): - self.remove_dir() - - def file_count(self): - count = 0 - for root, dirs, filenames in os.walk(self.dirname): - count += len(filenames) - return count - - def data_size(self): - size = 0 - for root, dirs, filenames in os.walk(self.dirname): - for filename in filenames: - size += os.path.getsize(os.path.join(root, filename)) - return size - - def file_list(self): - files = [] - for root, dirs, filenames in os.walk(self.dirname): - for filename in filenames: - files.append(os.path.join(root, filename)) - return files - - def nop(self, *args): - pass - - def testTerminatesWithoutDirectory(self): - app = genbackupdata.Application([]) - app.set_error_writer(self.nop) - self.failUnlessRaises(SystemExit, app.run) - - def apprun(self, args): - app = genbackupdata.Application(args) - app.run() - - def testCreatesFirstGenerationCorrectly(self): - self.apprun(["-c10k", self.dirname]) - self.failUnlessEqual(self.data_size(), 10 * genbackupdata.KiB) - - def testIncreasesSecondGenerationCorrectly(self): - self.apprun(["-c10k", self.dirname]) - self.apprun(["-c10k", self.dirname]) - self.failUnlessEqual(self.data_size(), 20 * genbackupdata.KiB) - - def testModifiesSecondGenerationCorrectly(self): - self.apprun(["-c10k", self.dirname]) - count = self.file_count() - self.apprun(["-m1k", self.dirname]) - self.failUnlessEqual(self.data_size(), 11 * genbackupdata.KiB) - self.failUnlessEqual(self.file_count(), count) - - def testDeletesFilesForSecondGenerationCorrectly(self): - self.apprun(["-c10k", self.dirname]) - count = self.file_count() - self.apprun(["-d2", self.dirname]) - self.failUnlessEqual(self.file_count(), count - 2) - - def testRenamesFilesForSecondGenerationCorrectly(self): - self.apprun(["-c10k", self.dirname]) - files1 = self.file_list() - self.apprun(["-r2", self.dirname]) - files2 = self.file_list() - self.failIfEqual(sorted(files1), sorted(files2)) - self.failUnlessEqual(len(files1), len(files2)) - - def testLinksFilesForSecondGenerationCorrectly(self): - self.apprun(["-c10k", self.dirname]) - files1 = self.file_list() - self.apprun(["-l2", self.dirname]) - files2 = self.file_list() - self.failUnlessEqual(len(files1) + 2, len(files2)) - - -if __name__ == "__main__": - unittest.main() -- cgit v1.2.1