Beispiel #1
0
def test_create_big_file_connection_error(monkeypatch):
    # with a "big" file, we're more confident that a connection error means the
    # file alredy exists, so raise FileExistsError without hedging
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/foo123/')
    store = Storage({})
    store._new_file_url = new_file_url
    store._put = MagicMock(side_effect=ConnectionError)

    try:
        exception = FileExistsError
    except NameError:
        exception = OSError

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'
    # set file size of 1 MB ("big" file)
    with patch('osfclient.models.storage.get_local_file_size',
               return_value=2**20):
        with pytest.raises(exception):
            store.create_file('foo.txt', fake_fp)

    store._put.assert_called_once_with(new_file_url,
                                       data=fake_fp,
                                       params={'name': 'foo.txt'})

    assert fake_fp.call_count == 0
Beispiel #2
0
def test_create_new_file_subdirectory():
    # test a new file in a new subdirectory
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/bar12/')
    new_folder_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                      'osfstorage/?kind=folder')
    store = Storage({})
    store._new_file_url = new_file_url
    store._new_folder_url = new_folder_url

    def simple_put(url, params={}, data=None):
        if url == new_folder_url:
            # this is a full fledged Folder response but also works as a
            # fake for _WaterButlerFolder
            return FakeResponse(
                201, {'data': fake_responses._folder('bar12', 'bar')})
        elif url == new_file_url:
            # we don't do anything with the response, so just make it None
            return FakeResponse(201, None)
        else:
            print(url)
            assert False, 'Whoops!'

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'

    with patch.object(Storage, '_put', side_effect=simple_put) as mock_put:
        store.create_file('bar/foo.txt', fake_fp)

    expected = [
        call(new_folder_url, params={'name': 'bar'}),
        call(new_file_url, params={'name': 'foo.txt'}, data=fake_fp)
    ]
    assert mock_put.call_args_list == expected
    assert fake_fp.call_count == 0
Beispiel #3
0
def test_update_existing_file_fails():
    # test we raise an error when we fail to update a file that we think
    # exists
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/foo123/')
    store = Storage({})
    store._new_file_url = new_file_url

    def simple_OSFCore_put(url, params=None, data=None):
        if url == new_file_url:
            return FakeResponse(409, None)
        elif url.endswith("osfstorage/foo.txt"):
            return FakeResponse(200, None)

    store._files_url = 'https://api.osf.io/v2//nodes/f3szh/files/osfstorage'
    json = fake_responses.files_node(
        'f3szh',
        'osfstorage',
        # this is the key, none of the files are
        # named after the file we are trying to
        # update
        file_names=['hello.txt', 'bar.txt'])
    top_level_response = FakeResponse(200, json)

    def simple_OSFCore_get(url):
        if url == store._files_url:
            return top_level_response

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'
    with patch.object(OSFCore, '_put', side_effect=simple_OSFCore_put):
        with patch.object(OSFCore, '_get', side_effect=simple_OSFCore_get):
            with pytest.raises(RuntimeError):
                store.create_file('foo.txt', fake_fp, update=True)
Beispiel #4
0
def test_create_small_file_connection_error():
    # turn a requests.ConnectionError into a RuntimeError with a more helpful
    # message that the file might exist
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/foo123/')
    store = Storage({})
    store._new_file_url = new_file_url
    store._put = MagicMock(side_effect=ConnectionError)

    try:
        exception = RuntimeError
    except NameError:
        exception = OSError

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'
    # set file size of 1 MB minus 1 byte ("small" file)
    with patch('osfclient.models.storage.get_local_file_size',
               return_value=2**20-1):
        with pytest.raises(exception):
            store.create_file('foo.txt', fake_fp)

    store._put.assert_called_once_with(new_file_url,
                                       data=fake_fp,
                                       params={'name': 'foo.txt'})

    assert fake_fp.call_count == 0
Beispiel #5
0
def test_create_new_zero_length_file():
    # check zero length files are special cased
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/foo123/')
    store = Storage({})
    store._new_file_url = new_file_url
    store._put = MagicMock(return_value=FakeResponse(201, None))

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'
    if six.PY3:
        fake_fp.peek = lambda: ''
    if six.PY2:
        fake_fp.read = lambda: ''

    store.create_file('foo.txt', fake_fp)

    store._put.assert_called_once_with(
        new_file_url,
        # this is the important check in
        # this test
        data=b'',
        params={'name': 'foo.txt'})

    assert fake_fp.call_count == 0
Beispiel #6
0
def test_update_existing_file_files_match_force_overrides_update():
    # test that adding `force=True` and `update=True` forces overwriting of the
    # remote file, since `force=True` overrides `update=True`
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/foo123/')
    store = Storage({})
    store._new_file_url = new_file_url

    def simple_OSFCore_put(url, params=None, data=None):
        if url == new_file_url:
            return FakeResponse(409, None)
        elif url.endswith("osfstorage/foo.txt"):
            return FakeResponse(200, None)

    store._files_url = 'https://api.osf.io/v2//nodes/f3szh/files/osfstorage'
    json = fake_responses.files_node('f3szh',
                                     'osfstorage',
                                     file_names=['hello.txt', 'foo.txt'])
    for i_file in range(2):
        json['data'][i_file]['attributes']['extra']['hashes']['md5'] = '0' * 32
    top_level_response = FakeResponse(200, json)

    def simple_OSFCore_get(url):
        if url == store._files_url:
            return top_level_response

    def simple_checksum(file_path):
        return '0' * 32

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'
    with patch.object(OSFCore, '_put',
                      side_effect=simple_OSFCore_put) as fake_put:
        with patch.object(OSFCore, '_get',
                          side_effect=simple_OSFCore_get) as fake_get:
            with patch('osfclient.models.storage.checksum',
                       side_effect=simple_checksum):
                store.create_file('foo.txt', fake_fp, force=True, update=True)

    assert fake_fp.call_count == 0
    assert call.peek(1) in fake_fp.mock_calls
    # should have made two PUT requests, first attempt at uploading then
    # to update the file, even though they match, since force=True overrides
    # update=True
    assert fake_put.call_count == 2
    # should have made one GET request to list files
    assert fake_get.call_count == 1
Beispiel #7
0
def test_create_new_file():
    # create a new file at the top level
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/foo123/')
    store = Storage({})
    store._new_file_url = new_file_url
    store._put = MagicMock(return_value=FakeResponse(201, None))

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'

    store.create_file('foo.txt', fake_fp)

    store._put.assert_called_once_with(new_file_url,
                                       data=fake_fp,
                                       params={'name': 'foo.txt'})

    assert fake_fp.call_count == 0
Beispiel #8
0
def test_update_existing_file_overrides_connection_error():
    # successful upload even on connection error if update=True
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/foo123/')
    store = Storage({})
    store._new_file_url = new_file_url

    def simple_OSFCore_put(url, params=None, data=None):
        if url == new_file_url:
            raise ConnectionError
        elif url.endswith("osfstorage/foo.txt"):
            return FakeResponse(200, None)

    def simple_checksum(file_path):
        return '0' * 32

    store._files_url = 'https://api.osf.io/v2//nodes/f3szh/files/osfstorage'
    json = fake_responses.files_node('f3szh',
                                     'osfstorage',
                                     file_names=['hello.txt', 'foo.txt'])
    top_level_response = FakeResponse(200, json)

    def simple_OSFCore_get(url):
        if url == store._files_url:
            return top_level_response

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'
    with patch.object(OSFCore, '_put',
                      side_effect=simple_OSFCore_put) as fake_put:
        with patch.object(OSFCore, '_get',
                          side_effect=simple_OSFCore_get) as fake_get:
            with patch('osfclient.models.storage.checksum',
                       side_effect=simple_checksum):
                store.create_file('foo.txt', fake_fp, update=True)

    assert fake_fp.call_count == 0
    assert call.peek(1) in fake_fp.mock_calls
    # should have made two PUT requests, first attempt at uploading then
    # to update the file
    assert fake_put.call_count == 2
    # should have made one GET request to list files
    assert fake_get.call_count == 1
Beispiel #9
0
def test_force_existing_file():
    # test that adding `force=True` lets you overwrite existing remote files
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/foo123/')
    store = Storage({})
    store._new_file_url = new_file_url

    def simple_OSFCore_put(url, params=None, data=None):
        if url == new_file_url:
            return FakeResponse(409, None)
        elif url.endswith("osfstorage/foo.txt"):
            return FakeResponse(200, None)

    store._files_url = 'https://api.osf.io/v2//nodes/f3szh/files/osfstorage'
    json = fake_responses.files_node('f3szh',
                                     'osfstorage',
                                     file_names=['hello.txt', 'foo.txt'])
    top_level_response = FakeResponse(200, json)

    def simple_OSFCore_get(url):
        if url == store._files_url:
            return top_level_response

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'
    with patch.object(OSFCore, '_put',
                      side_effect=simple_OSFCore_put) as fake_put:
        with patch.object(OSFCore, '_get',
                          side_effect=simple_OSFCore_get) as fake_get:
            store.create_file('foo.txt', fake_fp, force=True)

    assert fake_fp.call_count == 0
    assert call.peek(1) in fake_fp.mock_calls
    # should have made two PUT requests, first attempt at uploading then
    # to update the file
    assert fake_put.call_count == 2
    # should have made one GET request to list files
    assert fake_get.call_count == 1
Beispiel #10
0
def test_create_existing_file():
    # try to create file with a name that is already taken
    new_file_url = ('https://files.osf.io/v1/resources/9zpcy/providers/' +
                    'osfstorage/foo123/')
    store = Storage({})
    store._new_file_url = new_file_url
    store._put = MagicMock(return_value=FakeResponse(409, None))

    try:
        exception = FileExistsError
    except NameError:
        exception = OSError

    fake_fp = MagicMock()
    fake_fp.mode = 'rb'
    with pytest.raises(exception):
        store.create_file('foo.txt', fake_fp)

    store._put.assert_called_once_with(new_file_url,
                                       data=fake_fp,
                                       params={'name': 'foo.txt'})

    assert fake_fp.call_count == 0