def test_shouldCheckIfAllSharedOptionValuesOfAllRulesOfASchedulerAreEqual( self, fix): schedName = "sched-with-shared-opts" sched = mockSched(schedName, sharedOptions=[ optInfo("ConfDir"), optInfo("DestFile"), optInfo("Version") ]) def rule(**schedOpts): return mockRule(scheduler=sched, schedOpts=schedOpts) rules = [ rule(Version="1", ConfDir="/home", DestFile="/etc/foo"), rule(Version="1", ConfDir="/etc", DestFile="/etc/foo"), rule(Version="1", ConfDir="/usr/share") ] validator = self.construct() iterToTest(validator.validate(ruleSet(*rules))).\ shouldContainMatchingInAnyOrder( stringThat.shouldInclude("ConfDir", "/home", "/etc", "/usr/share"), stringThat.shouldInclude("DestFile", "‘/etc/foo’", "‘’"))
def test_shouldReturnTheWrappedSchedsCheckErrors(fixture): iterToTest( fixture.check([buildScheduling(ExecOnSuccess="(")], subCheckErrors=["foo", "bar"])).shouldContainMatching( lambda error: "ExecOnSuccess" in error, lambda error: error == "foo", lambda error: error == "bar")
def assertIsWrongSyntax(setting): ruleName = "bad-conf" iterToTest( fixture.check([ buildScheduling(ruleName, AllowedHours=setting) ])).shouldIncludeMatching( lambda error: strToTest(error).shouldInclude( ruleName, "syntax", "AllowedHours", setting))
def test_shouldPassTheSpecifiedTag(self, fixture): logger = fixture.make(tag="beer") with fixture.testServer() as server: logger.write(b"\n") iterToTest(server.packets).shouldContainMatching( lambda packet: packet.tag == b"beer")
def test_shouldAddLocOptInfosToAvailableOptionsBasedOnPorts(): wrapped = fakeConfigurable("syncer", ports=[port(), port(), port()], availableOptions=[]) syncer = DefaultValueSynchronizer(wrapped) iterToTest(syncer.availableOptions).shouldContainMatching( lambda opt: opt.name == "Loc1" and opt.optionType == types.Location, lambda opt: opt.name == "Loc2", lambda opt: opt.name == "Loc3")
def test_shouldUseTheUtilLinuxLoggerProgramForLogging(self, fixture): logger = fixture.make(prefix=b"prefix") with fixture.testServer() as server: logger.write(b"foo\n") iterToTest(server.packets).shouldContainMatching( lambda packet: packet.message == b"prefix: foo")
def test_shouldReturnNameAndBasicInfoOfRulesEvenWithoutBuildingThem(fixture): fixture.writeAnyRule("foo") fixture.writeAnyRule("bar") fixture.writeInstanceFile("@bar") iterToTest(fixture.read(mockedFileReader=mock.mock(), loadLazyRules=False)).shouldContainMatchingInAnyOrder( lambda rule: rule.name == "foo" and not rule.enabled, lambda rule: rule.name == "bar" and rule.enabled)
def test_shouldReportErrorIfALocDoesNotExistAsADirectory(self, fix): validator = self.construct() ruleName = "rulename" iterToTest( validator.validate([ fix.validRule(), self.invalidRule(fix, ruleName) ])).shouldContainMatching( lambda error: "does not exist" in error and ruleName in error)
def test_shouldCollectParseErrorsBeforeThrowingException(fixture): with pytest.raises(OptionParseException) as ex: fixture.parser.parseOptions( [optInfo("Opt1", types.Positive), optInfo("Opt2", types.Bool)], dict(Opt1="-2", Opt2="foo")) iterToTest(ex.value.errors).shouldContainMatchingInAnyOrder( lambda error: error.optionName == "Opt1" and "negative" in error. message, lambda error: error.optionName == "Opt2" and "truth" in error. expectedType)
def test_shouldNotFailForFunctionsThatHaveAReasonableDefault( self, fixture): syncer = self.loadSynchronizerWithCode("", fixture) assert syncer.onePortMustHaveFileProtocol == False _ = syncer.availableOptions iterToTest(syncer.ports).shouldContainMatching( lambda port: "file" in port.supportedProtocols and \ not port.isWrittenTo, lambda port: "file" in port.supportedProtocols and port.isWrittenTo) assert syncer.versionsOf(mkSyncerOpts(), "/mnt/data/bar", 1) == [] assert syncer.check(mkSyncerOpts()) == []
def test_shouldNotProcessListFilesOutputToEnhanceItsSpeedIfRequested( self, fixture): options = dict(ListFilesExactly=False) writeFileTree(fixture.loc1, ["folder", ["sub", "foo", "bar"]]) version = fixture.getSingleVersion(additionalOptions=options) iterToTest( fixture.listPort1Files( "folder", version, recursively=True, additionalOpts=options)).shouldContainInAnyOrder( "sub", "sub/foo", "sub/bar")
def test_shouldFindSyntaxErrorsInItsOptions(self, fixture): assert fixture.check( dict(AdditionalSyncOpts="--exclude '**/.*'")) == [] iterToTest( fixture.check( dict(AdditionalSyncOpts="--exclude '", RemoteShellCommand="("))).shouldContainMatchingInAnyOrder( stringThat.shouldInclude("AdditionalSyncOpts", "unexpected"), stringThat.shouldInclude("RemoteShellCommand", "unexpected"))
def test_shouldPrintTheActualMountPointIfTheAssertionTurnsOutFalse( self, fix): mountPoint = fix.tmpdir.mkdir("mount") with nonEmptyFSMountedAt(mountPoint): loc1 = mountPoint.mkdir("sub").mkdir("loc1") rule = mockRule(loc1=str(loc1), options=dict(MustBeMountPoint="1")) errors = self.construct().validate(ruleSet(rule)) iterToTest(errors).shouldContainMatching( stringThat.shouldInclude("actual", str(mountPoint) + "’"))
def test_shouldLogSystemExceptionsInLessDetail(self, fixture): class SysException(BaseException): pass def raiseException(logger): raise SysException() with pytest.raises(SysException): fixture.log.logExecution("foo", constantTimeClock(), raiseException) iterToTest(fixture.executionsOf("foo")).shouldContainMatching( lambda execution: strToTest(execution.output).\ shouldInclude("exception").but.shouldNotInclude("traceback"))
def test_shouldUseTheSpecifiedFacilityAndSeverity(self, fixture): logger = fixture.make(facility="mail", severity="warning") with fixture.testServer() as server: logger.write(b"\n") logger.write(b"\n", severity="err") logger.write(b"\n", facility="user") iterToTest(server.packets).shouldContainMatching( lambda packet: packet.facility == "mail" and packet.severity == "warning", lambda packet: packet.facility == "mail" and packet. severity == "err", lambda packet: packet.facility == "user" and packet.severity == "warning")
def test_shouldReturnEachSyncerCheckErrorWithAnAppropriatePrefix( self, fix): rule1 = mockRule("first", syncerName="syncer1", syncerCheckErrors=["Wrong option syntax"]) rule2 = mockRule( "second", syncerName="syncer2", syncerCheckErrors=["Contradictory values", "Unreadable File"]) iterToTest(self.construct().validate(ruleSet(rule1, rule2))).\ shouldContainMatchingInAnyOrder( stringThat.shouldInclude("syntax", "first", "syncer1"), stringThat.shouldInclude("Contradictory", "second", "syncer2"), stringThat.shouldInclude("Unreadable", "second", "syncer2"))
def test_shouldTurnEachCheckErrorFromTheUsedSchedulersIntoAString( self, fix): sched1, sched2 = mockSched("first"), mockSched("second") rule1, rule2 = mockRule(scheduler=sched1), mockRule(scheduler=sched2) validator = self.construct() sched1.expectCalls( schedCallWithRules("check", rule1, ret=["foo", "bar"])) sched2.expectCalls(schedCallWithRules("check", rule2, ret=["quux"])) iterToTest(validator.validate(ruleSet(rule1, rule2))).\ shouldContainMatchingInAnyOrder( stringThat.shouldInclude("first", "reported error", "foo"), stringThat.shouldInclude("first", "bar"), stringThat.shouldInclude("second", "quux"))
def test_shouldBeAbleToDryTestTheRsyncCommandThatWouldBeUsedToSync( self, fixture): assert "DryRun" in fixture.optionNames iterToTest(fixture.check(dict(DryRun=True, AdditionalSyncOpts="--bar"))).\ shouldContainMatching(stringThat.shouldInclude("unknown option", "bar")) (fixture.loc1 / "file").write("") assert fixture.check({}) == [] assert not os.path.isfile(str(fixture.loc2 / "file")) fixture.loc1.chmod(0o300) iterToTest(fixture.check(dict(DryRun=True))).shouldContainMatching( stringThat.shouldInclude("Permission denied")) assert fixture.check(dict(DryRun=False)) == []
def test_shouldCheckSyntaxOfScriptsWithoutExecutingThem(fixture, tmpdir): flagFile = str(tmpdir / "flag") erroneousCode = "touch {0}\n(echo foo".format(flagFile) schedulings = [ buildScheduling("touching", ExecOnFailure=erroneousCode), buildScheduling(ExecBefore="{") ] iterToTest(fixture.check(schedulings)).shouldContainMatching( lambda error: strToTest(error).shouldInclude( "unexpected", "ExecOnFailure", "syntax", "touching"), lambda error: "ExecBefore" in error) assert not os.path.isfile(flagFile)
def test_shouldReturnALazyRuleForEachFileAndBuildWithTheFactoryWhenLoadIsCalled( fixture): fixture.writeAnyRule("rule-1") fixture.writeAnyRule("rule-2") fileReader = mock.mock() lazyRules = fixture.read(fileReader, loadLazyRules=False, namePrefix="a-") assert lazyRules[0].name.startswith("a-rule-") ruleOpts1, schedOpts1, syncerOpts1, ruleOpts2, schedOpts2, syncerOpts2 = \ object(), object(), object(), object(), object(), object() fileReader.expectCallsInAnyOrder( readCall(paths=[fixture.rulePath("rule-1")], ret=sectionsDict(ruleOpts1, schedOpts1, syncerOpts1)), readCall(paths=[fixture.rulePath("rule-2")], ret=sectionsDict(ruleOpts2, schedOpts2, syncerOpts2))) firstConstructedRule = object() secondConstructedRule = object() fixture.factory.expectCallsInAnyOrder( buildCall(name="a-rule-1", ruleOpts=ruleOpts1, schedOpts=schedOpts1, syncerOpts=syncerOpts1, ret=firstConstructedRule), buildCall(name="a-rule-2", ruleOpts=ruleOpts2, schedOpts=schedOpts2, syncerOpts=syncerOpts2, ret=secondConstructedRule)) assert iterToTest(rule.load() for rule in lazyRules).\ shouldContainInAnyOrder(firstConstructedRule, secondConstructedRule)
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 test_shouldTreatFirstLineOfPortOutputAsWrittenToFlag(fixture): def protocolsCall(number, ret): return mock.callMatching("callFuzzy", lambda funcName, args, _: funcName == "info-of-port" and args[0] == number, ret=ret) fixture.functions.expectCallsInAnyOrder( protocolsCall("1", ["1", "a", "b"]), protocolsCall("2", ["1", "c"]), protocolsCall("3", ["0", "d", "e", "f"]), protocolsCall("4", [])) iterToTest(fixture.syncer.ports).shouldContainMatching( lambda port: port.supportedProtocols == ["a", "b"] and port.isWrittenTo, lambda port: port.supportedProtocols == ["c"] and port.isWrittenTo, lambda port: port.supportedProtocols == ["d", "e", "f"] and \ not port.isWrittenTo)
def test_shouldFindSyntaxErrorsInItsOptions(self, fixture): assert fixture.check( dict(AdditionalSyncOpts="--one-file-system", ExcludedDirs="/foo")) == [] iterToTest( fixture.check( dict(AdditionalSyncOpts="'", AdditionalOptsBothWays="'", RemoteShellCommand="("))).shouldContainMatchingInAnyOrder( stringThat.shouldInclude("unexpected", "AdditionalOptsBothWays"), stringThat.shouldInclude("unexpected", "AdditionalSyncOpts"), stringThat.shouldInclude("unexpected", "RemoteShellCommand"))
def test_shouldLogAndRethrowExceptions(self, fixture): class TestException(Exception): def __str__(self): return "we have a problem" def raiseException(logFile): raise TestException() with pytest.raises(TestException): fixture.log.logExecution("foo", constantTimeClock(), raiseException) iterToTest(fixture.executionsOf("foo")).shouldContainMatching( lambda execution: "internal" in execution.output and "exception" in execution.output and "we have a problem" in execution.output and not execution.succeeded)
def test_shouldRememberTheVersionTimestampInAFileAndElseFallBackOnTheMTime( self, fixture): someFile = fixture.loc1.join("file") someFile.write("") fixture.changeMTime(str(someFile), 23) fixture.sync() assert fixture.versionsOf("does-not-exist", 1) == [] iterToTest(fixture.versionsOf( "file", 1)).shouldContainMatching(lambda version: version.year > 1970) (fixture.loc2 / ".sibt-rsync-timestamp").remove() fixture.versionsOf("file", 1) == \ [datetime(1970, 1, 1, 0, 0, 23, tzinfo=timezone.utc)]
def test_shouldCallVisitorWithEachSchedAndItsRulesUntilNotNoneIsReturned( fixture): sched1, sched2 = mockScheds(2) rule1, rule2, rule3 = fixture.ruleWithSched(sched1), \ fixture.ruleWithSched(sched1), \ fixture.ruleWithSched(sched2) ruleSet = fixture.makeRuleSet(rule1, rule2, rule3) visited = [] def visit(sched, rules): visited.append((sched, set(rules))) assert ruleSet.visitSchedulers(visit) is None iterToTest(visited).shouldContainInAnyOrder((sched1, {rule1, rule2}), (sched2, {rule3})) assert ruleSet.visitSchedulers(lambda *args: "foo") == "foo"
def test_shouldBeAbleToListDirsInLoc1AsTheyWereInThePastWithoutRecursion( self, fixture): version = self.setUpTestTreeSyncAndDeleteIt(fixture, self.fileNameWithNewline, dict()) iterToTest( fixture.listPort1Files("[folder],", version, recursively=False)).shouldContainInAnyOrder( self.fileNameWithNewline, ".file2", "sub/") assert fixture.listPort1Files("[folder],/" + self.fileNameWithNewline, version, recursively=False) == \ [self.fileNameWithNewline] assert fixture.listPort1Files(".", version, recursively=False) == \ ["[folder],/"]
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_shouldUseTheIncrementsAsVersions(self, fixture): sameFile, topFile, folder, oldFile, newFile = writeFileTree( fixture.loc1, [ ".", "samefile [1]", "file [2]", ["usr [3]", "oldfile [4]", "newfile [5]"] ]) sameFile.write("same") newFile.remove() topFile.write("old") oldVersion, newVersion = self.getTwoVersions( fixture, doBetweenSyncs=lambda: (topFile.write("new"), newFile.write(""), oldFile.remove())) assert len(fixture.versionsOf("usr", 1)) == 2 assert fixture.versionsOf("not-there", 1) == [] assert len(fixture.versionsOf("usr/newfile", 1)) == 1 iterToTest(fixture.listPort1Files(".", oldVersion)).shouldContainInAnyOrder( "samefile", "file", "usr/", "usr/oldfile") iterToTest(fixture.listPort1Files(".", newVersion)).shouldContainInAnyOrder( "samefile", "file", "usr/", "usr/newfile") fixture.restorePort1File("usr", oldVersion, None) assert os.listdir(str(folder)) == ["oldfile"] assert topFile.read() == "new" fixture.restorePort1File(".", oldVersion, None) assert topFile.read() == "old" fixture.restorePort1File(".", newVersion, None) assert topFile.read() == "new" assert os.listdir(str(folder)) == ["newfile"] assert set(os.listdir(str( fixture.loc1))) == {"usr", "samefile", "file"}
def test_shouldCorrectlyReadExecutionsThatAreStillInProgress(self, fixture): startTime = anyUTCDateTime() executionsInThisProcess = [] executionsInOtherProcess = [] def execute(logger): logger.write(b"output\n") executionsInThisProcess.extend(fixture.executionsOf("quux")) executionsInOtherProcess.extend(fixture.inNewProcess(r""" return fixture.executionsOf("quux")""")) return True fixture.log.logExecution("quux", constantTimeClock(startTime), execute) iterToTest(executionsInOtherProcess).shouldContainMatching( lambda execution: execution.startTime == startTime and execution.output == "output\n" and execution.finished is False) iterToTest(executionsInThisProcess).shouldContainMatching( lambda execution: execution.finished is False)