def test_shouldParseOptionValuesAndRemoveNameBeforePassingThemOn(fixture): schedOptInfo, syncerOptInfo = object(), object() sched = fakeConfigurable("sched", availableOptions=[schedOptInfo]) syncer = fakeConfigurable("syncer", availableOptions=[syncerOptInfo]) oldRuleOpts = {"Opt": "abc"} oldSchedOpts, oldSyncerOpts = {"Name": "sched", "N": "2"}, \ {"Name": "syncer", "A": "yes"} newSchedOpts, newSyncerOpts = {"N": 2}, {"A": True} fixture.parser.expectCallsInAnyOrder( mock.callMatching("parseOptions", lambda infos, opts: opts == dict(N="2") and infos[0] is schedOptInfo, ret=newSchedOpts), mock.callMatching("parseOptions", lambda infos, opts: opts == dict(A="yes") and infos[ 0] is syncerOptInfo, ret=newSyncerOpts), mock.callMatching("parseOptions", lambda infos, opts: opts == oldRuleOpts and infos is syncrule.AvailableOptions, ret=oldRuleOpts)) fixture.ruleFactory.expectCalls( mock.callMatchingTuple( "build", lambda args: args[3] == oldRuleOpts and args[4] == newSchedOpts and args[5] == mkSyncerOpts(**newSyncerOpts))) fixture.makeReader([sched], [syncer]).readRule("name", oldRuleOpts, oldSchedOpts, oldSyncerOpts, True)
def test_shouldBeAbleToPredictItsNextExecutionWithHelpOfTheScheduler(fixture): lastEndTime, nextTime = orderedDateTimes(2) sched = mockSched() def rule(): return fixture.ruleWith(scheduler=sched) fixture.log.executions = [execution(endTime=lastEndTime)] sched.expectCalls( mock.callMatching( "nextExecutionTime", lambda scheduling: scheduling.lastExecutionTime == lastEndTime, ret=nextTime)) nextExecution = rule().nextExecution assert not nextExecution.finished assert nextExecution.startTime == nextTime sched.expectCalls( mock.callMatching("nextExecutionTime", mock.AnyArgs, ret=None)) assert rule().nextExecution is None fixture.log.executions = [] sched.expectCalls( mock.callMatching( "nextExecutionTime", lambda scheduling: scheduling.lastExecutionTime is None, ret=nextTime)) assert rule().nextExecution.startTime == nextTime fixture.log.executions = [execution(unfinished=True)] assert rule().nextExecution is None
def test_shouldPrintLineForEachScheduledRuleButNotScheduleThem(fixture): sub = mock.mock() sub.name = "sub-sched" output = mock.mock() output.expectCallsInAnyOrder( mock.callMatching( "println", lambda line: "first" in line and "sub-sched" in line), mock.callMatching("println", lambda line: "second" in line)) dry = DryScheduler(sub, output) dry.schedule([buildScheduling("first"), buildScheduling("second")]) output.checkExpectedCalls()
def test_shouldEncodeLocationsAsMultipleOptions(fixture): fixture.functions.expectCalls( mock.callMatching( "callVoid", lambda _, args, options: dictIncludes( options, { "SomePlaceProtocol": "ftp", "SomePlaceLogin": "******", "SomePlaceHost": "mansion", "SomePlacePort": "10", "SomePlacePath": "/blah/quux", "LocalProtocol": "file", "LocalPath": "/foo", "RestoreLogin": "", "RestoreHost": "blah", "RestorePath": "/foo" }))) options = { "SomePlace": remoteLocation(protocol="ftp", login="******", host="mansion", port="10", path="/blah/quux"), "Local": localLocation("/foo") } fixture.syncer.restore(options, "file", 2, anyUTCDateTime(), remoteLocation("http", host="blah", path="/foo")) fixture.functions.checkExpectedCalls()
def test_shouldConvertArgumentsAndOptionsToStringsDependingOnTheirType( fixture): enum = types.Enum("A", "B") options = { "SomePlace": location("/home//foo/"), "Loc1": location("/tmp"), "Yes": True, "No": False, "Number": 934, "Interval": timedelta(minutes=2, seconds=3.5), "Choice": enum.A } fixture.functions.expectCalls( mock.callMatching( "callVoid", lambda _, args, receivedOptions: args[ 3] == "/media/foo" and receivedOptions[ "SomePlace"] == "/home/foo" and receivedOptions["Loc1"] == "/tmp" and receivedOptions["Yes"] == "1" and receivedOptions["No"] == "0" and receivedOptions["Number"] == "934" and receivedOptions[ "Interval"] == "123" and receivedOptions["Choice"] == "A")) fixture.syncer.restore(options, "foo", 1, anyUTCDateTime(), location("/media/foo/")) fixture.functions.checkExpectedCalls()
def test_shouldForwardAnyCallsToSubScheduler(fixture): sub = mock.mock() sub.expectCallsInOrder( mock.callMatching("foo", lambda x, y: x == 1 and y == 2, ret=3)) dry = DryScheduler(sub, object()) assert dry.foo(1, 2) == 3 sub.checkExpectedCalls()
def test_shouldGiveEachSchedulerAnUnchangingVarDirectory(fixture): sched = fixture.conf.aSched("needs-lotsa-space") fixture.conf.ruleWithSyncer().withScheduler(sched).write() varDir = [] def firstCall(args): assert os.path.basename(args.varDir) == "needs-lotsa-space" varDir.append(args.varDir) return True def secondCall(args): assert args.varDir == varDir[0] return True sched.mock()[0].expectCalls(mock.callMatching("init", firstCall)) fixture.runSibt("list", "-f") sched.mock()[0].expectCalls(mock.callMatching("init", secondCall)) fixture.runSibt("list", "-f")
def expectCalls(self, *expectations): calls = [ mock.callMatching("call", functools.partial(self._callMatcher, expectedProgram, envVars), ret=exitCode, sideEffectFunc=sideEffect) for expectedProgram, exitCode, sideEffect, envVars in expectations ] self.callsMock.expectCallsInOrder(*calls)
def test_shouldPassOnAnyGivenKeywordArgsToWriteFuncs(): subLogger = mock.mock() subLogger.expectCalls( mock.callMatching("write", lambda *args, **kwargs: kwargs == dict(Foo="Bar"))) TeeLogger(subLogger).write(b"", Foo="Bar") subLogger.checkExpectedCalls()
def test_shouldWrapFunctionNotImplementedException(fixture): def throwNotImplementedEx(*args): raise ModuleFunctionNotImplementedException("") fixture.functions.expectCalls( mock.callMatching("callVoid", throwNotImplementedEx)) with pytest.raises(SynchronizerFuncNotImplementedException) as ex: fixture.syncer.sync({}) assert ex.value.synchronizerName == fixture.syncer.name
def check(path, expectedRelativePath, expectedLoc): syncer.expectCalls( mock.callMatching( "versionsOf", lambda options, path, locNumber: path == expectedRelativePath and locNumber == expectedLoc and options == syncerOptions, ret=ret)) assert set(versionsOf( rule, path)) == {version(rule, ret[0]), version(rule, ret[1])} syncer.checkExpectedCalls()
def test_shouldSplitFuzzyOutputForTypeAndNameOfAvailableOptions(fixture): ret = ["Default", "b B"] fixture.functions.expectCalls( mock.callMatching("callFuzzy", lambda funcName, *_: funcName == "available-options", ret=ret)) assert iterToTest(fixture.syncer.availableOptions).shouldContainMatching( lambda opt: opt.name == "Default" and opt.optionType == types.String, lambda opt: opt.name == "B" and opt.optionType == types.Bool)
def test_shouldAllowExactlyTheExpectedCalls(fixture): mocked = mock.mock() mocked.expectCalls( mock.callMatching("allowed", lambda a, b: [a, b] == [1, 2])) with pytest.raises(AssertionError): mocked.allowed(1, 3) mocked.allowed(1, 2) with pytest.raises(AssertionError): mocked.allowed(1, 2)
def test_shouldCallAppropriateFunctionForSynchronization(fixture): options = mkSyncerOpts(One="1", Two="two") fixture.functions.expectCalls( mock.callMatching( "callVoid", lambda funcName, args, usedOptions: funcName == "sync" and len(args) == 0 and usedOptions == dict(options))) fixture.syncer.sync(options) fixture.functions.checkExpectedCalls()
def test_shouldCallRestoreWithAUnixTimestampWithMilliseconds(fixture): path = "path/to/file" expectedArgs = [path, "1", "93,460", ""] time = EpochPlus93Point46Sec fixture.functions.expectCalls( mock.callMatching( "callVoid", lambda funcName, args, _: funcName == "restore" and list(args) == expectedArgs)) fixture.syncer.restore({}, path, 1, time, None) fixture.functions.checkExpectedCalls()
def getLoggedOutput(self, logInput, *formatArgs, maxVerbosity=10, prefix="sibt", **kwargs): output = mock.mock() ret = [None] def storeResult(string): ret[0] = string return True output.expectCalls(mock.callMatching("println", storeResult)) logger = PrefixingErrorLogger(output, prefix, maxVerbosity) logger.log(logInput, *formatArgs, **kwargs) return ret[0]
def test_shouldFindSyncersAndSchedsByTheirNameOptions(fixture): sched = fakeConfigurable("sched-b") syncer = fakeConfigurable("syncer") fixture.parser.parseOptions = lambda _, opts: opts fixture.ruleFactory.expectCalls( mock.callMatching( "build", lambda name, receivedSched, receivedSyncer, *_: name == "sys" and receivedSched is sched and receivedSyncer is syncer)) reader = fixture.makeReader([fakeConfigurable("sched-a"), sched], [syncer]) reader.readRule("sys", {}, {"Name": "sched-b"}, {"Name": "syncer"}, False)
def test_shouldParseUnixTimestampsWithAndWithoutMillisecondsAsVersions( fixture): path = "/etc/config" fixture.functions.expectCalls( mock.callMatching( "callFuzzy", lambda funcName, args, _: funcName == "versions-of" and args[ 0] == path and args[1] == "2", ret=["250", "0,999", toTimestamp("2013-05-10T13:05:20") + ",025"])) iterToTest(fixture.syncer.versionsOf({}, path, 2)).shouldContainInAnyOrder( datetime(1970, 1, 1, 0, 4, 10, 0, timezone.utc), datetime(1970, 1, 1, 0, 0, 0, 999000, timezone.utc), datetime(2013, 5, 10, 13, 5, 20, 25000, timezone.utc))
def makeMockCall(program, predicateOrTuple, ret=[], delimiter="\n", returningNotImplementedStatus=False, **otherKwargs): expectedDelimiter = delimiter matcher = ( lambda calledProgram, args, delimiter="\n": calledProgram == program and (predicateOrTuple(args) if callable(predicateOrTuple) else args == predicateOrTuple) and (delimiter == expectedDelimiter or expectedDelimiter is DontCheck)) return mock.callMatching("getOutput", matcherThrowingNotImplementedFailure(matcher) if \ returningNotImplementedStatus else matcher, ret=ret, **otherKwargs)
def test_shouldBeAbleToTestKeywordArguments(fixture): mocked = mock.mock() mocked.expectCallsInAnyOrder( mock.call("foo", (4, ), {"arg": 2}, anyNumber=True), mock.callMatching("bar", lambda *args, **kwargs: args == (4, ) and kwargs == {"arg": 2}, anyNumber=True)) mocked.foo(4, arg=2) with pytest.raises(AssertionError): mocked.foo(4, arg=3) with pytest.raises(AssertionError): mocked.foo(4) mocked.bar(4, arg=2) with pytest.raises(AssertionError): mocked.bar(4, arg=0)
def test_shouldEvaluateExactOutputAndCallTheClientWhenListingFiles(fixture): listing = ["foo", "bar"] visitedFiles = [] def visitor(fileName): visitedFiles.append(fileName) path = "some/file" expectedOptions = {"Opt": "bar"} fixture.functions.expectCalls( mock.callMatching( "callExact", lambda funcName, args, options: funcName == "list-files" and list( args) == [path, "2", "93,460", "0"], ret=listing)) fixture.syncer.listFiles(expectedOptions, visitor, path, 2, EpochPlus93Point46Sec, False) assert visitedFiles == listing
def test_shouldNotScheduleIfAnyRuleDiffersFromTheOthersInASharedOption( fixture): schedMock, sched = fixture.conf.aSched().\ withSharedOptions("f TmpFolder").mock() baseRule = fixture.conf.ruleWithSyncer().withScheduler(sched) rule1 = baseRule.withAnyName().withSchedOpts(TmpFolder="/tmp").write() rule2 = baseRule.withAnyName().withSchedOpts(TmpFolder="/tmp").write() schedMock.expectCalls( mock.callMatching( "schedule", lambda schedulings: schedulings[0].options["TmpFolder"] .path == "/tmp")) fixture.runSibt("schedule", rule1.name, rule2.name) fixture.stderr.shouldBeEmpty() fixture.shouldHaveExitedWithStatus(0) sched.mock() rule2.withSchedOpts(TmpFolder="/var/tmp").write() fixture.runSibt("schedule", rule1.name, rule2.name) fixture.shouldHaveExitedWithStatus(1) fixture.stderr.shouldInclude("TmpFolder", "differ", "/tmp", "/var/tmp")
def test_shouldWrapAllParseExceptionsItGetsInAConsistencyEx(fixture): def fail(_, opts): if "A" not in opts or opts["A"] == "3": raise OptionParseException( ["rule-foo" if "A" not in opts else "sched-bar"]) return True sched, syncer = fakeConfigurable("sched"), fakeConfigurable("syncer") fixture.parser.expectCalls( mock.callMatching("parseOptions", fail, anyNumber=True, ret={})) with pytest.raises(ConfigConsistencyException) as ex: fixture.makeReader([sched], [syncer]).readRule("rule", {}, { "Name": "sched", "A": "3" }, { "Name": "syncer", "A": "0" }, False) strToTest(ex.value.message).shouldIncludeInOrder("[Scheduler]", "sched-bar").\ andAlso.shouldIncludeInOrder("[Rule]", "rule-foo").andAlso.\ shouldNotInclude("[Synchronizer]")
def schedCallWithRules(action, *rules, **kwargs): return mock.callMatching( action, lambda schedulingSet: set(schedulingSet) == set(rule.scheduling for rule in rules), **kwargs)
def protocolsCall(number, ret): return mock.callMatching("callFuzzy", lambda funcName, args, _: funcName == "info-of-port" and args[0] == number, ret=ret)
def shouldThrow(timestamp): fixture.functions.expectCalls( mock.callMatching("callFuzzy", lambda *_: True, ret=[timestamp])) with pytest.raises(ValueError) as ex: fixture.syncer.versionsOf({}, "foo", 1) strToTest(str(ex)).shouldInclude("timestamp", "format")