%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/waritko/go/src/github.com/odeke-em/drive/tests/
Upload File :
Create Path :
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()

Zerion Mini Shell 1.0