def testNodePidDied(self): from rmake.multinode import workernode m = mock.mockClass(workernode.rMakeWorkerNodeServer)() m._mock.enableMethod('_pidDied') cmd = mock.mockClass(command.Command, mock_runInit=True) cmd = cmd(None, 'foo', 1) cmd.pid = 377 cmd._mock.disable('readPipe') m._mock.set(commands=[cmd]) m._pidDied(377, 255) # check to make sure self.client.commandErrored was called w/ the # right parameters f = failure.CommandFailed('foo', 'unexpectedly killed with signal 127') m.commandErrored._mock.assertCalled('foo', f) m._mock.enableMethod('commandErrored') m.commandErrored(cmd, 'Command foo unexpectedly died with exit code 4') assert(m.commands == []) m._mock.set(commands=[cmd]) mock.mockMethod(m.commandErrored) m._pidDied(377, 1024) f = failure.CommandFailed('foo', 'unexpectedly died with exit code 4') m.commandErrored._mock.assertCalled( 'foo', f) assert(m.commands == []) m._pidDied(365, 1024) m.commandErrored._mock.assertNotCalled()
def _setupMockCommand(self, jobId, troveTup): from rmake.worker import command from rmake.messagebus import messages from rmake.multinode import messages as mnmessages from rmake.multinode import workernode # test how the node responds to various messages sent in from our # fake client. buildTrove = self.newBuildTrove(jobId, *troveTup) commandClass = mock.mockClass(command.BuildCommand, mock_runInit=True) buildCommand = commandClass(self.getNodeCfg(), 'CMD-1', jobId, mock.MockObject(), self.buildCfg, mock.MockObject(), buildTrove, targetLabel=self.cfg.buildLabel, builtTroves=[]) buildCommand._mock.disable('chrootFactory') buildCommand._mock.disable('chroot') buildCommand.chroot._mock.set(pid=50) buildCommand.chroot._mock.set( buildTrove=lambda *args, **kw: ('/tmp/foo', 50)) buildCommand._mock.disable('readPipe') buildCommand._mock.disable('writePipe') return buildCommand
def testProductDirectoryError(self): productStoreClass = mock.mockClass(dirstore.CheckoutProductStore) productStore = productStoreClass() productStore._mock.enable('_testProductDirectory') err = self.assertRaises(errors.RbuildError, productStore._testProductDirectory, self.workDir) assert(str(err) == "No product directory at %r" %self.workDir)
def testProductDirectoryError(self): productStoreClass = mock.mockClass(dirstore.CheckoutProductStore) productStore = productStoreClass() productStore._mock.enable('_testProductDirectory') err = self.assertRaises(errors.RbuildError, productStore._testProductDirectory, self.workDir) assert (str(err) == "No product directory at %r" % self.workDir)
def testNodeServer(self): from rmake.messagebus import messages from rmake.multinode import messages as mnmessages from rmake.multinode import workernode # test how the node responds to various messages sent in from our # fake client. server, sessionClient = self._setupMockNode() trv = self.addComponent('simple:source', '1', [('simple.recipe', recipes.simpleRecipe)]) # send a build command buildTrove = self.newBuildTrove(1, *trv.getNameVersionFlavor()) m = mnmessages.BuildCommand('CMD-1', self.buildCfg, 1, buildTrove, [], [], self.cfg.buildLabel, targetNode='WORKER-foo') # this should result in the command being queued... mock.mockMethod(server.queueCommand) mock.mockMethod(server.chrootManager.getRootFactory) sessionClient.handle_message(m) commandClass = server.queueCommand._mock.calls[0][0][0] self.assertEquals(commandClass, command.BuildCommand) commandClass = mock.mockClass(command.BuildCommand, mock_enable=['pid'], getCommandId=lambda: 'CMD-1', isErrored=lambda: False) server.queueCommand._mock.method(commandClass, self.cfg, 1, 'CMD-1') assert(server.listQueuedCommands()) # pretend we forked this command... mock.mockFunctionOnce(os, 'fork', 342) server._serveLoopHook() assert(server.listCommands()) # and now it's died... mock.mockFunctionOnce(os, 'waitpid', (342, 0)) server._serveLoopHook() assert(not server.listCommands()) self._check(sessionClient, mnmessages.CommandStatus, destination='/commandstatus', commandId='CMD-1', status=mnmessages.CommandStatus.COMPLETED) # let's create another command, one that fails on initialization commandClass = command.Command def _raise(*args, **kw): raise RuntimeError('foo') mock.replaceFunctionOnce(commandClass, '__init__', _raise) server.queueCommand._mock.method(commandClass, self.cfg, 'CMD-1') server._serveLoopHook() self._check(sessionClient, mnmessages.CommandStatus, destination='/commandstatus', commandId='CMD-1', status=mnmessages.CommandStatus.ERROR)
def testNodeServerInitializationFailure(self): from rmake.multinode import workernode serverClass = mock.mockClass(workernode.rMakeWorkerNodeServer, mockEnable='__init__') s = serverClass() err = RuntimeError('foo') s._mock.raiseErrorOnAccess(err) self.assertRaises(RuntimeError, workernode.rMakeWorkerNodeServer.__init__, s, self.getNodeCfg()) args = s.error._mock.popCall()[0] assert(args[0] == 'Error initializing Node Server:\n %s\n%s') assert(args[1] == err)
def testGetSourceTrovesFromJob(self): repos = mock.mockClass(repocache.CachingTroveSource)() trv1 = self.newBuildTrove(1, *self.makeTroveTuple('bar:source')) trv1Tup = trv1.getNameVersionFlavor(True) trv1.setConfig(self.buildCfg) job = self.newJob() job.addBuildTrove(trv1) mock.mockFunction(recipeutil.loadSourceTroves, {trv1Tup: 'result'}) rc = recipeutil.getSourceTrovesFromJob(job, [trv1], repos, self.rmakeCfg.reposName) self.failUnlessEqual(rc, {trv1Tup: 'result'}) args, kw = recipeutil.loadSourceTroves._mock.popCall() assert (args[3] == [trv1])
def testGetSourceTrovesFromJob(self): repos = mock.mockClass(repocache.CachingTroveSource)() trv1 = self.newBuildTrove(1, *self.makeTroveTuple('bar:source')) trv1Tup = trv1.getNameVersionFlavor(True) trv1.setConfig(self.buildCfg) job = self.newJob() job.addBuildTrove(trv1) mock.mockFunction(recipeutil.loadSourceTroves, {trv1Tup: 'result'}) rc = recipeutil.getSourceTrovesFromJob(job, [trv1], repos, self.rmakeCfg.reposName) self.failUnlessEqual(rc, {trv1Tup: 'result'}) args, kw = recipeutil.loadSourceTroves._mock.popCall() assert(args[3] == [trv1])
def testNodeRPCClient(self): from rmake.multinode import workernode from rmake.worker import command server, sessionClient = self._setupMockNode() mock.mockMethod(server.client._logger.logRPCCall) rpcClient = workernode.WorkerNodeRPCClient(server.client.getBusClient(), sessionClient.sessionId) assert(tuple(rpcClient.listCommands()) == ([], [])) commandClass = mock.mockClass(command.BuildCommand, getCommandId=lambda: 'CMD-1', mock_enable=['pid', 'commandInfo']) server.queueCommand(commandClass, None, 'CMD-1') mock.mockFunctionOnce(os, 'fork', 342) server._serveLoopHook() self.assertEquals(rpcClient.listCommands(), ([], [('CMD-1', 342)]))
def testGetChangeSet(self): # Now mock ChangesetCache, to log things origChangesetCache = netreposproxy.ChangesetCache lockLogFile = os.path.join(self.workDir, "locks.log") class MockChangesetCache(origChangesetCache): llf = file(lockLogFile, "a") def get(slf, key, shouldLock=True): csPath = origChangesetCache.hashKey(slf, key) ret = origChangesetCache.get(slf, key, shouldLock=shouldLock) if shouldLock and ret is None: slf.llf.write("Lock acquired for %s\n" % csPath) self.assertTrue(os.path.exists(csPath + '.lck')) return ret def set(slf, key, value): csPath = origChangesetCache.hashKey(slf, key) if csPath in slf.locksMap: slf.llf.write("Releasing lock for %s\n" % csPath) return origChangesetCache.set(slf, key, value) def resetLocks(slf): for csPath in sorted(slf.locksMap): slf.llf.write("Resetting unused lock for %s\n" % csPath) return origChangesetCache.resetLocks(slf) self.mock(netreposproxy, 'ChangesetCache', MockChangesetCache) cfg = netserver.ServerConfig() cfg.changesetCacheDir = os.path.join(self.workDir, "changesetCache") cfg.proxyContentsDir = os.path.join(self.workDir, "proxyContents") prs = netreposproxy.ProxyRepositoryServer(cfg, "/someUrl") rawUrl = '/blah' headers = {'X-Conary-Proxy-Host': 'repos.example.com'} prs.setBaseUrlOverride(rawUrl, headers, isSecure=True) # callWrapper normally sets this, but nothing here invokes it prs._serverName = 'repos.example.com' caller = mock.mockClass(netreposproxy.ProxyCaller)() caller._getBasicUrl._mock.setDefaultReturn('http://blah') caller.checkVersion._mock.setDefaultReturn([51, 52, 53]) # Make sure we present the fingerprints in non-sorted order, we need # to verify we sort them suf = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' fingerprints = ['aac3aac3' + suf, 'aaa1aaa1' + suf, 'aab2aab2' + suf] caller.getChangeSetFingerprints._mock.setDefaultReturn(fingerprints) csSizes = [12, 13, 14] allInfo = [(str(x), 'trovesNeeded%d' % i, 'filesNeeded%d' % i, 'removedTroves%d' % i, str(x)) for i, x in enumerate(csSizes)] csFileObj = file(os.path.join(self.workDir, "changeset"), "w+") magic = netreposproxy.filecontainer.FILE_CONTAINER_MAGIC fver = netreposproxy.filecontainer.FILE_CONTAINER_VERSION_FILEID_IDX fver = netreposproxy.filecontainer.struct.pack("!I", fver) for i, csSize in enumerate(csSizes): csFileObj.write(magic) csFileObj.write(fver) rest = csSize - len(magic) - len(fver) csFileObj.write((chr(ord('a') + i) * rest)) csFileObj.seek(0) changeSetList = [(x, (None, None), (None, None), False) for x in ['a', 'b', 'c']] caller.getChangeSet._mock.appendReturn( ('http://repos.example.com/my-changeset-url', allInfo), 53, changeSetList, False, True, False, True, 2007022001, False, False) urlOpener = mock.MockObject() uo = mock.MockObject() self.mock(netreposproxy.transport, 'ConaryURLOpener', urlOpener) urlOpener._mock.setDefaultReturn(uo) uo.open._mock.appendReturn(csFileObj, 'http://repos.example.com/my-changeset-url', forceProxy=caller._lastProxy, headers=[('X-Conary-Servername', 'repos.example.com')]) authToken = AuthToken(None, None, []) clientVersion = 51 prs.getChangeSet(caller, authToken, clientVersion, changeSetList, recurse=False, withFiles=True, withFileContents=False, excludeAutoSource=True) MockChangesetCache.llf.close() f = file(lockLogFile) contents = [x.strip() for x in f] sortedFP = sorted(fingerprints) logEntries1 = contents[:len(fingerprints)] self.assertEqual(logEntries1, [ 'Lock acquired for %s/%s/%s-2007022001.1' % (cfg.changesetCacheDir, fp[:2], fp[2:]) for fp in sortedFP ]) logEntries2 = contents[len(fingerprints):2 * len(fingerprints)] self.assertEqual(logEntries2, [ 'Releasing lock for %s/%s/%s-2007022001.1' % (cfg.changesetCacheDir, fp[:2], fp[2:]) for fp in fingerprints ]) # We're not releasing locks we didn't close self.assertEqual(len(contents), 2 * len(fingerprints))
def testGetChangeSet(self): # Now mock ChangesetCache, to log things origChangesetCache = netreposproxy.ChangesetCache lockLogFile = os.path.join(self.workDir, "locks.log") class MockChangesetCache(origChangesetCache): llf = file(lockLogFile, "a") def get(slf, key, shouldLock = True): csPath = origChangesetCache.hashKey(slf, key) ret = origChangesetCache.get(slf, key, shouldLock=shouldLock) if shouldLock and ret is None: slf.llf.write("Lock acquired for %s\n" % csPath) self.assertTrue(os.path.exists(csPath + '.lck')) return ret def set(slf, key, value): csPath = origChangesetCache.hashKey(slf, key) if csPath in slf.locksMap: slf.llf.write("Releasing lock for %s\n" % csPath) return origChangesetCache.set(slf, key, value) def resetLocks(slf): for csPath in sorted(slf.locksMap): slf.llf.write("Resetting unused lock for %s\n" % csPath) return origChangesetCache.resetLocks(slf) self.mock(netreposproxy, 'ChangesetCache', MockChangesetCache) cfg = netserver.ServerConfig() cfg.changesetCacheDir = os.path.join(self.workDir, "changesetCache") cfg.proxyContentsDir = os.path.join(self.workDir, "proxyContents") prs = netreposproxy.ProxyRepositoryServer(cfg, "/someUrl") rawUrl = '/blah' headers = {'X-Conary-Proxy-Host' : 'repos.example.com'} prs.setBaseUrlOverride(rawUrl, headers, isSecure = True) # callWrapper normally sets this, but nothing here invokes it prs._serverName = 'repos.example.com' caller = mock.mockClass(netreposproxy.ProxyCaller)() caller._getBasicUrl._mock.setDefaultReturn('http://blah') caller.checkVersion._mock.setDefaultReturn([51, 52, 53]) # Make sure we present the fingerprints in non-sorted order, we need # to verify we sort them suf = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' fingerprints = ['aac3aac3' + suf, 'aaa1aaa1' + suf, 'aab2aab2' + suf] caller.getChangeSetFingerprints._mock.setDefaultReturn(fingerprints) csSizes = [ 12, 13, 14 ] allInfo = [ (str(x), 'trovesNeeded%d' % i, 'filesNeeded%d' % i, 'removedTroves%d' % i, str(x)) for i, x in enumerate(csSizes) ] csFileObj = file(os.path.join(self.workDir, "changeset"), "w+") magic = netreposproxy.filecontainer.FILE_CONTAINER_MAGIC fver = netreposproxy.filecontainer.FILE_CONTAINER_VERSION_FILEID_IDX fver = netreposproxy.filecontainer.struct.pack("!I", fver) for i, csSize in enumerate(csSizes): csFileObj.write(magic) csFileObj.write(fver) rest = csSize - len(magic) - len(fver) csFileObj.write((chr(ord('a') + i) * rest)) csFileObj.seek(0) changeSetList = [ (x, (None, None), (None, None), False) for x in ['a', 'b', 'c'] ] caller.getChangeSet._mock.appendReturn( ('http://repos.example.com/my-changeset-url', allInfo), 53, changeSetList, False, True, False, True, 2007022001, False, False) urlOpener = mock.MockObject() uo = mock.MockObject() self.mock(netreposproxy.transport, 'ConaryURLOpener', urlOpener) urlOpener._mock.setDefaultReturn(uo) uo.open._mock.appendReturn( csFileObj, 'http://repos.example.com/my-changeset-url', forceProxy=caller._lastProxy, headers=[('X-Conary-Servername', 'repos.example.com')]) authToken = AuthToken(None, None, []) clientVersion = 51 prs.getChangeSet(caller, authToken, clientVersion, changeSetList, recurse = False, withFiles = True, withFileContents = False, excludeAutoSource = True) MockChangesetCache.llf.close() f = file(lockLogFile) contents = [ x.strip() for x in f ] sortedFP = sorted(fingerprints) logEntries1 = contents[:len(fingerprints)] self.assertEqual(logEntries1, [ 'Lock acquired for %s/%s/%s-2007022001.1' % (cfg.changesetCacheDir, fp[:2], fp[2:]) for fp in sortedFP ]) logEntries2 = contents[len(fingerprints):2 * len(fingerprints)] self.assertEqual(logEntries2, [ 'Releasing lock for %s/%s/%s-2007022001.1' % (cfg.changesetCacheDir, fp[:2], fp[2:]) for fp in fingerprints ]) # We're not releasing locks we didn't close self.assertEqual(len(contents), 2 * len(fingerprints))