def test_shouldTreatLocsCorrespondingToPortsAsMinimumOptions(fixture): def locOptInfo(number): return optInfo("Loc" + str(number), types.Location) sched = fakeConfigurable("scheduler") syncer = fakeConfigurable("synchronizer", ports=[port(), port(), port(), port()], availableOptions=[ locOptInfo(1), locOptInfo(2), locOptInfo(3), locOptInfo(4) ]) loc1Through3 = { "Loc1": loc("/some-place"), "Loc2": loc("/place"), "Loc3": loc("/bar") } with pytest.raises(ConfigConsistencyException) as ex: fixture.factory.build("rulename", sched, syncer, {}, {}, mkSyncerOpts(**loc1Through3), True) strToTest(str(ex.value)).shouldIncludeInOrder("not", "minimum opt").andAlso.\ shouldInclude("Loc4") with noException(): fixture.factory.build( "rule", sched, syncer, {}, {}, mkSyncerOpts(Loc4=loc("/fourth"), **loc1Through3), True)
def test_shouldThrowExceptionForNonTrivialNotImplementedFunctions( self, fixture): syncer = self.loadSynchronizerWithCode("", fixture) with pytest.raises(SynchronizerFuncNotImplementedException): syncer.listFiles(mkSyncerOpts(), lambda *_: None, "/tmp/file", 1, anyUTCDateTime(), False) with pytest.raises(SynchronizerFuncNotImplementedException): syncer.sync(mkSyncerOpts())
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_shouldReturnVersionsGotFromSynchronizerIfFileIsWithinAPort(fixture): syncer = mockSyncer(ports=[port(), port(), port()]) syncerOptions = mkSyncerOpts(Loc1=location("/mnt/data/loc1"), Loc2=location("/mnt/backup/loc2"), Loc3=location("/mnt/foo/loc3")) rule = fixture.ruleWith(mockedSynchronizer=syncer, syncerOptions=syncerOptions) ret = orderedDateTimes(2) 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() check(location("/mnt/data/loc1/blah"), "blah", 1) check(location("/mnt/backup/loc2/one/two/"), "one/two", 2) check(location("/mnt/foo/loc3/bar/../"), ".", 3) assert len(versionsOf(rule, location("/mnt/data/quux"))) == 0
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_shouldThrowAnExceptionIfLocOptionsHaveProtocolsNotSupportedBySyncer( fixture): syncer = mockSyncer() syncer.ports = [port(["a", "b"]), port(["c"])] fixture.ruleWith(mockedSynchronizer=syncer, syncerOptions=mkSyncerOpts( Loc1=remoteLocation(protocol="b"), Loc2=remoteLocation(protocol="c"))) with pytest.raises(UnsupportedProtocolException) as ex: fixture.ruleWith(mockedSynchronizer=syncer, syncerOptions=mkSyncerOpts( Loc1=remoteLocation(protocol="b"), Loc2=remoteLocation(protocol="d"))) assert ex.value.optionName == "Loc2" assert ex.value.protocol == "d" assert ex.value.supportedProtocols == ["c"]
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_shouldThrowExceptionIfInUnstablePhaseWhileGettingVersions(fixture): syncer = mockSyncer() syncer.versionsOf = lambda *_: [anyUTCDateTime()] rule = fixture.ruleWith(mockedSynchronizer=syncer, syncerOptions=mkSyncerOpts(Loc1=location("/loc1"))) rule.versionsOf(location("/not-in-a-port"), PositiveUnstablePhaseDetector()) with pytest.raises(UnstablePhaseException): rule.versionsOf(location("/loc1"), PositiveUnstablePhaseDetector())
def call(self, funcName, testOptions, inputOptions): returnValue = object() args = (object(), object()) def subFunc(options, *passedArgs): assert passedArgs == args testOptions(options) return returnValue setattr(self.wrapped, funcName, subFunc) func = getattr(self.syncer, funcName) assert func(mkSyncerOpts(**inputOptions), *args) == returnValue
def test_shouldFormatOptionValuesBasedOnTheirType(fixture): enum = types.Enum("Foo", "Bar") rule = ruleWith(schedOpts=dict(Encrypt=True, Compress=False), syncerOpts=mkSyncerOpts(Interval=timedelta(days=5, minutes=1, seconds=2), Choice=enum.Bar)) fixture.printer.show(rule) fixture.output.string.shouldIncludeLinePatterns( "*Encrypt*Yes*", "*Compress*No*", "*Interval*5 days 1 minute 2 seconds*", "*Choice*Bar*")
def checkWriteLocs(writtenToFlags, expectedWriteLocs, expectedNonWriteLocs, loc2=loc2): syncer = mockSyncer() syncer.ports = [port(isWrittenTo=flag) for flag in writtenToFlags] rule = fixture.ruleWith(mockedSynchronizer=syncer, syncerOptions=mkSyncerOpts(Loc1=loc1, Loc2=loc2)) assert set(rule.writeLocs) == set(expectedWriteLocs) assert set(rule.nonWriteLocs) == set(expectedNonWriteLocs)
def test_shouldEnforceSpecialInvariantThatOnePortMustHaveFileProtocol(fixture): syncer = mockSyncer() syncer.onePortMustHaveFileProtocol = True syncer.ports = [port(["file", "remote"]), port(["file", "remote"])] with pytest.raises(UnsupportedProtocolException) as ex: fixture.ruleWith(mockedSynchronizer=syncer, syncerOptions=mkSyncerOpts( Loc1=remoteLocation(protocol="remote"), Loc2=remoteLocation(protocol="remote"))) assert "at least one" in ex.value.explanation rule = fixture.ruleWith(mockedSynchronizer=syncer, syncerOptions=mkSyncerOpts( Loc1=remoteLocation(protocol="remote", path="/foo"), Loc2=remoteLocation(protocol="file", path="/bar"))) with pytest.raises(UnsupportedProtocolException) as ex: rule.restore(remoteLocation(protocol="file", path="/bar/file"), version(rule), remoteLocation(protocol="remote"), detector())
def ruleWith(self, name="some-rule", scheduler=None, mockedSynchronizer=None, schedOptions={}, syncerOptions=mkSyncerOpts()): if mockedSynchronizer is None: mockedSynchronizer = mockSyncer() if "Loc1" not in syncerOptions: syncerOptions["Loc1"] = location("/mnt") if "Loc2" not in syncerOptions: syncerOptions["Loc2"] = location("/etc") return SyncRule(name, {}, schedOptions, syncerOptions, False, scheduler, mockedSynchronizer, self.log)
def test_shouldAssignRestoreTargetToThePortTheFileToBeRestoredWasFoundIn( fixture): syncer = mockSyncer() syncer.ports = [port(["a"]), port(["b"])] loc1 = remoteLocation(protocol="a", path="/foo") rule = fixture.ruleWith(mockedSynchronizer=syncer, syncerOptions=mkSyncerOpts(Loc1=loc1, Loc2=remoteLocation( protocol="b", path="/bar"))) with pytest.raises(UnsupportedProtocolException) as ex: rule.restore(loc1, version(rule), remoteLocation(protocol="b"), detector()) assert ex.value.supportedProtocols == ["a"]
def optsWith(self, options): assert not str(self.loc1).endswith("/") options["Loc1"] = self.location1FromPath(str(self.loc1)) options["Loc2"] = self.location2FromPath(str(self.loc2)) return mkSyncerOpts(**options)
def test_shouldThrowExceptionIfInUnstablePhaseWhenRestoring(fixture): rule = fixture.ruleWith(syncerOptions=mkSyncerOpts(Loc1=location("/data"))) with pytest.raises(UnstablePhaseException): rule.restore(location("/data"), version(rule), None, PositiveUnstablePhaseDetector())
def callBuild(ruleOptions, schedulerOptions, synchronizerOptions): fixture.factory.build("rule", scheduler, synchronizer, ruleOptions, schedulerOptions, mkSyncerOpts(**synchronizerOptions), True)
def test_shouldThrowExceptionIfRuleNameContainsInvalidCharacters(fixture): with pytest.raises(RuleNameInvalidException) as ex: fixture.factory.build("foo@with space", fakeConfigurable("sched"), fakeConfigurable("syncer", ports=[]), {}, {}, mkSyncerOpts(), False) assert ex.value.invalidCharacter == " "
def buildRuleWithNoOpts(self): return self.factory.build("name", fakeConfigurable(), fakeConfigurable(ports=[]), {}, {}, mkSyncerOpts(), False)
def assertFailureWithSyncCode(self, code, fixture): syncer = self.loadSynchronizerWithCode(code, fixture) with pytest.raises(ExternalFailureException) as ex: syncer.sync(mkSyncerOpts()) return ex.value