1818import threading
1919import urllib .parse
2020import sys
21+ from mocks .http_server import HttpServerMock
2122
2223from bob .archive import DummyArchive , HttpArchive , getArchiver
2324from bob .errors import BuildError
@@ -60,7 +61,7 @@ def run(coro):
6061 with patch ('bob.archive.signal.signal' ):
6162 return runInEventLoop (coro )
6263
63- class BaseTester :
64+ class Base :
6465
6566 def __createArtifact (self , bid , version = "1" ):
6667 bid = hexlify (bid ).decode ("ascii" )
@@ -90,6 +91,23 @@ def __createBuildId(self, bid):
9091 f .write (b'\x00 ' * 20 )
9192 return name
9293
94+ def setUp (self ):
95+ # create repo
96+ self .repo = TemporaryDirectory ()
97+
98+ # add artifacts
99+ self .dummyFileName = self .__createArtifact (DOWNLOAD_ARITFACT )
100+ self .__createArtifact (WRONG_VERSION_ARTIFACT , "0" )
101+ self .__createBuildId (DOWNLOAD_ARITFACT )
102+
103+ self .executor = getProcessPoolExecutor ()
104+
105+ def tearDown (self ):
106+ self .executor .shutdown ()
107+ self .repo .cleanup ()
108+
109+ class BaseTester (Base ):
110+
93111 def __testArtifact (self , bid ):
94112 bid = hexlify (bid ).decode ("ascii" )
95113 artifact = os .path .join (self .repo .name , bid [0 :2 ], bid [2 :4 ], bid [4 :] + "-1.tgz" )
@@ -152,13 +170,7 @@ def __getSingleArchiveInstance(self, spec):
152170 return getArchiver (recipes )
153171
154172 def setUp (self ):
155- # create repo
156- self .repo = TemporaryDirectory ()
157-
158- # add artifacts
159- self .dummyFileName = self .__createArtifact (DOWNLOAD_ARITFACT )
160- self .__createArtifact (WRONG_VERSION_ARTIFACT , "0" )
161- self .__createBuildId (DOWNLOAD_ARITFACT )
173+ super ().setUp ()
162174
163175 # create ERROR_DOWNLOAD_ARTIFACT that is there but cannot be opened
164176 bid = hexlify (ERROR_DOWNLOAD_ARTIFACT ).decode ("ascii" )
@@ -178,12 +190,6 @@ def setUp(self):
178190 with open (name , "wb" ) as f :
179191 f .write (b'\x00 ' )
180192
181- self .executor = getProcessPoolExecutor ()
182-
183- def tearDown (self ):
184- self .executor .shutdown ()
185- self .repo .cleanup ()
186-
187193 # standard tests for options
188194 def testOptions (self ):
189195 """Test that wantDownload/wantUpload options work"""
@@ -672,3 +678,43 @@ def _setArchiveSpec(self, spec):
672678 spec ["download" ] = "cp {}/$BOB_REMOTE_ARTIFACT $BOB_LOCAL_ARTIFACT" .format (self .repo .name )
673679 spec ["upload" ] = "mkdir -p {P}/${{BOB_REMOTE_ARTIFACT%/*}} && cp $BOB_LOCAL_ARTIFACT {P}/$BOB_REMOTE_ARTIFACT" .format (P = self .repo .name )
674680
681+ class TestHttpArchiveRetries (Base , TestCase ):
682+
683+ def setUp (self ):
684+ super ().setUp ()
685+ self .spec = {'backend' : 'http' , 'name' : 'http-archive' , 'flags' : ['download' , 'upload' , 'managed' ]}
686+
687+ def _getHttpArchiveInstance (self , port ):
688+ self .spec ["url" ] = "http://localhost:{}/" .format (port )
689+ recipes = DummyRecipeSet (self .spec )
690+ return getArchiver (recipes )
691+
692+ def _testRetries (self , r ):
693+ self .spec ['retries' ] = r
694+ # server will fail as often as retries in spec
695+ with HttpServerMock (repoPath = self .repo .name , retries = r ) as srv :
696+ archive = self ._getHttpArchiveInstance (srv .port )
697+ archive .wantDownloadLocal (True )
698+ with TemporaryDirectory () as tmp :
699+ audit = os .path .join (tmp , "audit.json.gz" )
700+ content = os .path .join (tmp , "workspace" )
701+ self .assertTrue (run (archive .downloadPackage (DummyStep (), DOWNLOAD_ARITFACT , audit , content ,
702+ executor = self .executor )))
703+ # server fails one more time than retries in archive sepc -> fail
704+ with HttpServerMock (repoPath = self .repo .name , retries = r + 1 ) as srv :
705+ archive = self ._getHttpArchiveInstance (srv .port )
706+ archive .wantDownloadLocal (True )
707+ with TemporaryDirectory () as tmp :
708+ audit = os .path .join (tmp , "audit.json.gz" )
709+ content = os .path .join (tmp , "workspace" )
710+ self .assertFalse (run (archive .downloadPackage (DummyStep (), DOWNLOAD_ARITFACT , audit , content ,
711+ executor = self .executor )))
712+
713+ def testRetriesWithNoRetries (self ):
714+ self ._testRetries (0 )
715+
716+ def testRetriesWithOneRetry (self ):
717+ self ._testRetries (1 )
718+
719+ def testRetriesWithMultipleRetries (self ):
720+ self ._testRetries (5 )
0 commit comments