Created
June 18, 2015 21:08
-
-
Save clayg/4aebb0a21589d485785e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/test/unit/obj/test_reconstructor.py b/test/unit/obj/test_reconstructor.py | |
index 321ea37..ae3c155 100755 | |
--- a/test/unit/obj/test_reconstructor.py | |
+++ b/test/unit/obj/test_reconstructor.py | |
@@ -24,6 +24,7 @@ import shutil | |
import re | |
import random | |
from eventlet import Timeout | |
+import struct | |
from contextlib import closing, nested, contextmanager | |
from gzip import GzipFile | |
@@ -2512,6 +2513,59 @@ class TestObjectReconstructor(unittest.TestCase): | |
self.assertRaises(DiskFileError, self.reconstructor.reconstruct_fa, | |
job, node, dict(metadata)) | |
+ @patch_policies([ECStoragePolicy()]) | |
+ def test_reconstruct_fa_finds_itself_does_not_blow_up(self): | |
+ """ | |
+ On some backends if you ask to reconstruct a fragment that is in the | |
+ list of fragments you want to reconstruct from we were able to see | |
+ segfaults, in our code we prevent the reconstructor from excepting a | |
+ backend connection to an object server that has the same fragment | |
+ index we need to rebuild. | |
+ | |
+ Other approach would be to abort the rebuild and move on to the next | |
+ object in the hopes that the remote who has the fragment we're trying | |
+ to rebuild will eventually push it over to the correct node. | |
+ """ | |
+ job = { | |
+ 'partition': 0, | |
+ 'policy': self.policy, | |
+ } | |
+ part_nodes = self.policy.object_ring.get_part_nodes(0) | |
+ node = part_nodes[1] | |
+ metadata = { | |
+ 'name': '/a/c/o', | |
+ 'Content-Length': 0, | |
+ 'ETag': 'etag', | |
+ } | |
+ | |
+ test_data = ('rebuild' * self.policy.ec_segment_size)[:-777] | |
+ etag = md5(test_data).hexdigest() | |
+ ec_archive_bodies = make_ec_archive_bodies(self.policy, test_data) | |
+ | |
+ # instead of popping the broken body, we'll just lave it in the list | |
+ # of responses and take away something else. | |
+ broken_body = ec_archive_bodies[1] | |
+ ec_archive_bodies = ec_archive_bodies[:-1] | |
+ | |
+ def make_header(body): | |
+ metadata = self.policy.pyeclib_driver.get_metadata(body) | |
+ frag_index = struct.unpack('h', metadata[:2])[0] | |
+ return { | |
+ 'X-Object-Sysmeta-Ec-Frag-Index': frag_index, | |
+ 'X-Object-Sysmeta-Ec-Etag': etag, | |
+ } | |
+ | |
+ responses = [(200, body, make_header(body)) | |
+ for body in ec_archive_bodies] | |
+ codes, body_iter, headers = zip(*responses) | |
+ with mocked_http_conn(*codes, body_iter=body_iter, headers=headers): | |
+ df = self.reconstructor.reconstruct_fa( | |
+ job, node, metadata) | |
+ fixed_body = ''.join(df.reader()) | |
+ self.assertEqual(len(fixed_body), len(broken_body)) | |
+ self.assertEqual(md5(fixed_body).hexdigest(), | |
+ md5(broken_body).hexdigest()) | |
+ | |
if __name__ == '__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment