Changeset View
Changeset View
Standalone View
Standalone View
swh/storage/tests/test_storage.py
# Copyright (C) 2015-2019 The Software Heritage developers | # Copyright (C) 2015-2019 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU General Public License version 3, or any later version | # License: GNU General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
import copy | import copy | ||||
import datetime | import datetime | ||||
import itertools | import itertools | ||||
import queue | |||||
import random | import random | ||||
import threading | |||||
import unittest | import unittest | ||||
from collections import defaultdict | from collections import defaultdict | ||||
from unittest.mock import Mock, patch | from unittest.mock import Mock, patch | ||||
import psycopg2 | import psycopg2 | ||||
import pytest | import pytest | ||||
from hypothesis import given, strategies, settings, HealthCheck | from hypothesis import given, strategies, settings, HealthCheck | ||||
▲ Show 20 Lines • Show All 4,011 Lines • ▼ Show 20 Lines | def test_content_add_objstorage_exception(self): | ||||
self.storage.content_add([self.cont]) | self.storage.content_add([self.cont]) | ||||
self.assertEqual(e.exception.args, ('mocked broken objstorage',)) | self.assertEqual(e.exception.args, ('mocked broken objstorage',)) | ||||
missing = list(self.storage.content_missing([self.cont])) | missing = list(self.storage.content_missing([self.cont])) | ||||
self.assertEqual(missing, [self.cont['sha1']]) | self.assertEqual(missing, [self.cont['sha1']]) | ||||
@pytest.mark.db | @pytest.mark.db | ||||
class TestStorageRaceConditions(TestStorageData, StorageTestDbFixture, | |||||
unittest.TestCase): | |||||
@pytest.mark.xfail | |||||
def test_content_add_race(self): | |||||
results = queue.Queue() | |||||
def thread(): | |||||
db = None | |||||
try: | |||||
db = self.storage.get_db() | |||||
with db.transaction() as cur: | |||||
anlambert: For your information, the test also fails when not providing the `db` and `cur` parameter. Are… | |||||
Not Done Inline ActionsThey are not really (in the current state of this code). Technically, to be sure that the race condition triggers all the time, we need to add a synchronization point between the threads, so that we are sure that both transactions are open at the same time. This means synchronizing before the content_add call, but after db.transaction(). olasd: They are not really (in the current state of this code).
Technically, to be sure that the race… | |||||
ret = self.storage.content_add([self.cont], db=db, | |||||
cur=cur) | |||||
results.put((threading.get_ident(), 'data', ret)) | |||||
except Exception as e: | |||||
results.put((threading.get_ident(), 'exc', e)) | |||||
finally: | |||||
if db: | |||||
self.storage.put_db(db) | |||||
t1 = threading.Thread(target=thread) | |||||
t2 = threading.Thread(target=thread) | |||||
t1.start() | |||||
# this avoids the race condition | |||||
# import time | |||||
# time.sleep(1) | |||||
t2.start() | |||||
t1.join() | |||||
t2.join() | |||||
r1 = results.get(block=False) | |||||
r2 = results.get(block=False) | |||||
with pytest.raises(queue.Empty): | |||||
results.get(block=False) | |||||
assert r1[0] != r2[0] | |||||
assert r1[1] == 'data', 'Got exception %r in Thread%s' % (r1[2], r1[0]) | |||||
assert r2[1] == 'data', 'Got exception %r in Thread%s' % (r2[2], r2[0]) | |||||
@pytest.mark.db | |||||
@pytest.mark.property_based | @pytest.mark.property_based | ||||
class PropTestLocalStorage(CommonPropTestStorage, StorageTestDbFixture, | class PropTestLocalStorage(CommonPropTestStorage, StorageTestDbFixture, | ||||
unittest.TestCase): | unittest.TestCase): | ||||
pass | pass | ||||
class AlteringSchemaTest(TestStorageData, StorageTestDbFixture, | class AlteringSchemaTest(TestStorageData, StorageTestDbFixture, | ||||
unittest.TestCase): | unittest.TestCase): | ||||
▲ Show 20 Lines • Show All 61 Lines • Show Last 20 Lines |
For your information, the test also fails when not providing the db and cur parameter. Are they really needed ?