%PDF- %PDF-
Direktori : /home/waritko/go/src/github.com/odeke-em/drive/tests/ |
Current File : //home/waritko/go/src/github.com/odeke-em/drive/tests/drive_test.py |
#!/usr/bin/env python # Copyright 2015 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import hashlib import os import re import subprocess import sys import traceback from contextlib import contextmanager # config g_testdir = 'testdir' g_drive_bin = 'drive' g_fail_stop = False # global variables count_ok = 0 count_bad = 0 g_driveignore_fn = os.path.join(g_testdir, '.driveignore') def init(): if not os.path.exists(g_drive_bin): print 'Drive executable (path=%s) not found' % repr(g_drive_bin) sys.exit(1) if not os.path.exists(os.path.join(g_testdir, '.gd')): print 'Please init drive folder %s/ first' % g_testdir sys.exit(1) if Drive.list('') != []: print 'Warning! This test tool has destructive side-effect and will erase you drive' sys.exit(1) def expect_eq(expected, actual): global count_ok, count_bad if expected != actual: print '[expected]', repr(expected) print '[actual]', repr(actual) print 'failed' count_bad += 1 raise Exception else: count_ok += 1 def expect_ne(not_expected, actual): global count_ok, count_bad if not_expected == actual: print '[not expected equal]', repr(actual) print 'failed' count_bad += 1 raise Exception else: count_ok += 1 def expect_true(actual): expect_eq(True, bool(actual)) class Drive: @classmethod def run(cls, cmd, *args, **argd): extraflags = argd.get('extraflags', []) if type(extraflags) not in (list, tuple): extraflags = [extraflags] cmd = [g_drive_bin] + [cmd] + list(extraflags) + list(args) #print '$', if argd.get('input') is not None: if re.match(r'^[\x32-\x79\n]+$', argd.get('input')): print 'echo "%s" |' % argd.get('input'), else: print 'echo ... |', print subprocess.list2cmdline(cmd) try: cwd = os.getcwd() os.chdir(g_testdir) if argd.get('input') is None: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) else: p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) finally: os.chdir(cwd) out, err = p.communicate(argd.get('input')) return p.returncode, out, err @classmethod def run_ok(cls, *args, **argd): returncode, out, err = cls.run(*args, **argd) if returncode != 0: if out != '': print '[stdout]' sys.stdout.write(out) if err != '': print '[stderr]' sys.stdout.write(err) expect_eq(0, returncode) return returncode, out, err @classmethod def run_fail(cls, *args, **argd): returncode, out, err = cls.run(*args, **argd) if returncode == 0: if out != '': print '[stdout]' sys.stdout.write(out) if err != '': print '[stderr]' sys.stdout.write(err) expect_ne(0, returncode) return returncode, out, err @classmethod def push_piped(cls, filename, content, **argd): return cls.run_ok('push', '-piped', filename, input=content, **argd) @classmethod def pull_piped(cls, filename, **argd): _, out, _ = cls.run_ok('pull', '-piped', filename, **argd) return out @classmethod def trash(cls, *filename, **argd): return cls.run_ok('trash', *filename, **argd) @classmethod def list(cls, path='', recursive=False, **argd): extraflags = ['-no-prompt'] if recursive: extraflags += ['-r', '-m=-1'] _, out, _ = cls.run_ok('list', path, extraflags=extraflags, **argd) return sorted(out.splitlines()) @classmethod def erase_all(cls): to_trash = [] for path in cls.list(''): assert path[0] == '/' and path[1:] to_trash.append(path[1:]) if to_trash: cls.trash(*to_trash, input='y') cls.run_ok('emptytrash', '-no-prompt') @contextmanager def setup_files(name, *files): print '#', name try: os.unlink(g_driveignore_fn) except OSError: pass for path, content in files: Drive.push_piped(path, content) try: yield except Exception: if g_fail_stop: raise traceback.print_exc() print '# clean up' Drive.erase_all() print def verify_files(*files): for path, content in files: expect_eq(content, Drive.pull_piped(path)) def test_basic(): # Most tests depend on these functionality fn = 'foo.txt' data = 'foobar' print '# basic tests' Drive.push_piped(fn, data) expect_eq(data, Drive.pull_piped(fn)) Drive.trash(fn, input='y') print def test_list(): with setup_files('list empty drive'): expect_eq([], Drive.list('')) with setup_files('list folder', ['a/b/c.txt', 'foobar']): expect_eq(['/a'], Drive.list('')) expect_eq(['/a/b'], Drive.list('a')) expect_eq(['/a/b/c.txt'], Drive.list('a/b')) with setup_files('list file, issue #97', ['a/b/c.txt', 'foobar']): expect_eq(['/a/b/c.txt'], Drive.list('a/b/c.txt')) with setup_files('list not-found, issue #95'): _, out, err = Drive.run_fail('list', 'not-found') expect_eq('', out) expect_ne('', err) def test_rename(): with setup_files('rename file in root', ['a.txt', 'a']): Drive.run_ok('rename', 'a.txt', 'abc.txt') expect_eq(['/abc.txt'], Drive.list()) with setup_files('rename file in folder', ['b/b.txt', 'b']): Drive.run_ok('rename', 'b/b.txt', 'c.txt') expect_eq(['/b', '/b/c.txt'], Drive.list(recursive=True)) # special cases with setup_files('rename file to self in root', ['b.txt', 'b']): Drive.run_ok('rename', 'b.txt', 'b.txt') expect_eq(['/b.txt'], Drive.list(recursive=True)) with setup_files('rename file to self in folder', ['b/b.txt', 'b']): Drive.run_ok('rename', 'b/b.txt', 'b.txt') expect_eq(['/b', '/b/b.txt'], Drive.list(recursive=True)) with setup_files('rename to existing file', ['a.txt', 'a'], ['b.txt', 'b']): _, out, err = Drive.run_fail('rename', 'a.txt', 'b.txt') expect_true('already exists' in err) expect_eq(['/a.txt', '/b.txt'], Drive.list(recursive=True)) verify_files(['a.txt', 'a'], ['b.txt', 'b']) with setup_files('rename special path handling', ['a/b/c.txt', 'c'], ['a/a.txt', 'a']): Drive.run_ok('rename', 'a/a.txt', 'b/c.txt') expect_eq(['/a', '/a/b', '/a/b/c.txt', '/a/b/c.txt'], Drive.list(recursive=True)) def test_move(): # basic case with setup_files('move folder to another', ['a/a.txt', 'a'], ['b/b.txt', 'b']): Drive.run_ok('move', 'a', 'b') expect_eq(['/b', '/b/a', '/b/a/a.txt', '/b/b.txt'], Drive.list(recursive=True)) with setup_files('move multiple files', ['a/a.txt', 'a'], ['b/b.txt', 'b'], ['c/c.txt', 'c']): Drive.run_ok('move', 'a/a.txt', 'b/b.txt', 'c') expect_eq(['/a', '/b', '/c', '/c/a.txt', '/c/b.txt', '/c/c.txt'], Drive.list(recursive=True)) Drive.run_ok('move', 'c/a.txt', 'c/b.txt', 'c/c.txt', '') expect_eq(['/a', '/a.txt', '/b', '/b.txt', '/c', '/c.txt'], Drive.list(recursive=True)) with setup_files('move file to file', ['a.txt', 'a'], ['b.txt', 'b']): Drive.run_fail('move', 'a.txt', 'b.txt') expect_eq(['/a.txt', '/b.txt'], Drive.list(recursive=True)) verify_files(['a.txt', 'a'], ['b.txt', 'b']) # special cases with setup_files('move file to the same folder', ['a/b.txt', 'b']): Drive.run_ok('move', 'a/b.txt', 'a') expect_eq(['/a', '/a/b.txt'], Drive.list(recursive=True)) with setup_files('move folder to its parent', ['a/b/c.txt', 'c']): Drive.run_ok('move', 'a/b', 'a') expect_eq(['/a', '/a/b', '/a/b/c.txt'], Drive.list(recursive=True)) with setup_files('move folder to its child', ['a/b/c.txt', 'c']): Drive.run_fail('move', 'a', 'a/b') expect_eq(['/a', '/a/b', '/a/b/c.txt'], Drive.list(recursive=True)) with setup_files('move multiple files and duplicated', ['a/foo.txt', 'a'], ['b/foo.txt', 'b'], ['c/c.txt', 'c']): _, _, err = Drive.run_ok('move', 'a/foo.txt', 'b/foo.txt', 'c') expect_ne('', err) expect_eq(['/a', '/b', '/b/foo.txt', '/c', '/c/c.txt', '/c/foo.txt'], Drive.list(recursive=True)) def test_stat(): cases = [ '', 'foobar', ''.join(map(chr, range(256))), ] for data in cases: print 'try', repr(data) with setup_files('stat file with size=%d' % len(data), ['foo.txt', data]): _, out, _ = Drive.run_ok('stat', 'foo.txt') expect_true(re.search(r'Bytes\s+%s' % len(data), out)) expect_true(re.search(r'DirType\s+file', out)) expect_true(re.search(r'MimeType\s+text/plain', out)) expect_true(re.search(r'Md5Checksum\s+%s' % hashlib.md5(data).hexdigest(), out)) def test_pull(): with setup_files('pull -piped not-found file, issue #95'): _, out, err = Drive.run_fail('pull', '-piped', 'not-found') expect_eq('', out) expect_ne('', err) with setup_files('pull -piped folder', ['a/a.txt', '']): _, out, err = Drive.run_fail('pull', '-piped', 'a') expect_eq('', out) expect_ne('', err) def test_trash(): with setup_files('trash file', ['a.txt', 'a']): Drive.trash('a.txt', input='y') expect_eq([], Drive.list()) with setup_files('trash folder', ['a/b.txt', 'b']): Drive.trash('a/b.txt', input='y') expect_eq(['/a'], Drive.list(recursive=True)) Drive.trash('a', input='y') expect_eq([], Drive.list()) with setup_files('trash multiple files', ['a.txt', ''], ['b.txt', ''], ['c.txt', '']): _, _, err = Drive.run_ok('trash', 'a.txt', 'b.txt', 'c.txt', input='y') expect_eq([], Drive.list()) with setup_files('trash non-existing file'): _, _, err = Drive.run_fail('trash', 'not-found', input='y') expect_ne('', err) def main(): init() test_basic() test_list() test_rename() test_move() test_stat() test_pull() test_trash() print 'ok', count_ok print 'bad', count_bad if __name__ == '__main__': main()