示例#1
0
 def test_mergeData(self):
     """
     Verify we don't lose keys which are present in the old but not
     replaced in the new.
     """
     old = ConfigDict({
         "Scheduling": ConfigDict({
             "iMIP": ConfigDict({
                 "Enabled": True,
                 "Receiving": ConfigDict({
                     "Username": "******",
                     "Server": "example.com",
                 }),
                 "Sending": ConfigDict({
                     "Username": "******",
                 }),
                 "AddressPatterns": ["mailto:.*"],
             }),
         }),
     })
     new = ConfigDict({
         "Scheduling": ConfigDict({
             "iMIP": ConfigDict({
                 "Enabled": False,
                 "Receiving": ConfigDict({
                     "Username": "******",
                 }),
             }),
         }),
     })
     mergeData(old, new)
     self.assertEquals(old.Scheduling.iMIP.Receiving.Server, "example.com")
     self.assertEquals(old.Scheduling.iMIP.Sending.Username, "plugh")
示例#2
0
    def read(self):
        """
        Reads in the data contained in the writable plist file.

        @return: C{ConfigDict}
        """
        if os.path.exists(self.fileName):
            self.currentConfigSubset = ConfigDict(
                mapping=plistlib.readPlist(self.fileName))
        else:
            self.currentConfigSubset = ConfigDict()
示例#3
0
    def test_matchClientFixes(self):
        """
        Test that L{matchClientFixes} correctly identifies clients with matching fix tokens.
        """
        c = ConfigDict()
        c.ClientFixes = {
            "fix1": [
                "Client/1\\.0.*",
                "Client/1\\.1(\\..*)?",
                "Client/2",
            ],
            "fix2": [
                "Other/1\\.0.*",
            ],
        }
        _updateClientFixes(c)
        _updateClientFixes(c)

        # Valid matches
        for ua in (
                "Client/1.0 FooBar/2",
                "Client/1.0.1 FooBar/2",
                "Client/1.0.1.1 FooBar/2",
                "Client/1.1 FooBar/2",
                "Client/1.1.1 FooBar/2",
                "Client/2 FooBar/2",
        ):
            self.assertEqual(
                matchClientFixes(c, ua),
                set(("fix1", )),
                msg="Did not match {}".format(ua),
            )

        # Valid non-matches
        for ua in (
                "Client/1 FooBar/2",
                "Client/1.10 FooBar/2",
                "Client/2.0 FooBar/2",
                "Client/2.0.1 FooBar/2",
                "Client FooBar/2",
                "Client/3 FooBar/2",
                "Client/3.0 FooBar/2",
                "Client/10 FooBar/2",
                "Client/10.0 FooBar/2",
                "Client/10.0.1 FooBar/2",
                "Client/10.0.1 (Client/1.0) FooBar/2",
                "Client/10.0.1 (foo Client/1.0 bar) FooBar/2",
        ):
            self.assertEqual(
                matchClientFixes(c, ua),
                set(),
                msg="Incorrectly matched {}".format(ua),
            )
    def test_matchClientFixes(self):
        """
        Test that L{matchClientFixes} correctly identifies clients with matching fix tokens.
        """
        c = ConfigDict()
        c.ClientFixes = {
            "fix1": [
                "Client/1\\.0.*",
                "Client/1\\.1(\\..*)?",
                "Client/2",
            ],
            "fix2": [
                "Other/1\\.0.*",
            ],
        }
        _updateClientFixes(c)
        _updateClientFixes(c)

        # Valid matches
        for ua in (
            "Client/1.0 FooBar/2",
            "Client/1.0.1 FooBar/2",
            "Client/1.0.1.1 FooBar/2",
            "Client/1.1 FooBar/2",
            "Client/1.1.1 FooBar/2",
            "Client/2 FooBar/2",
        ):
            self.assertEqual(
                matchClientFixes(c, ua),
                set(("fix1",)),
                msg="Did not match {}".format(ua),
            )

        # Valid non-matches
        for ua in (
            "Client/1 FooBar/2",
            "Client/1.10 FooBar/2",
            "Client/2.0 FooBar/2",
            "Client/2.0.1 FooBar/2",
            "Client FooBar/2",
            "Client/3 FooBar/2",
            "Client/3.0 FooBar/2",
            "Client/10 FooBar/2",
            "Client/10.0 FooBar/2",
            "Client/10.0.1 FooBar/2",
            "Client/10.0.1 (Client/1.0) FooBar/2",
            "Client/10.0.1 (foo Client/1.0 bar) FooBar/2",
        ):
            self.assertEqual(
                matchClientFixes(c, ua),
                set(),
                msg="Incorrectly matched {}".format(ua),
            )
示例#5
0
    def test_ConfigDict(self):
        configDict = ConfigDict({
            "a": "A",
            "b": "B",
            "c": "C",
        })

        # Test either syntax inbound
        configDict["d"] = "D"
        configDict.e = "E"

        # Test either syntax outbound
        for key in "abcde":
            value = key.upper()

            self.assertEquals(configDict[key], value)
            self.assertEquals(configDict.get(key), value)
            self.assertEquals(getattr(configDict, key), value)

            self.assertIn(key, configDict)
            self.assertTrue(hasattr(configDict, key))

        self.assertEquals(configDict.a, "A")
        self.assertEquals(configDict.d, "D")
        self.assertEquals(configDict.e, "E")

        # Test either syntax for delete
        del configDict["d"]
        delattr(configDict, "e")

        # Test either syntax for absence
        for key in "de":
            self.assertNotIn(key, configDict)
            self.assertFalse(hasattr(configDict, key))
            self.assertRaises(KeyError, lambda: configDict[key])
            self.assertRaises(AttributeError, getattr, configDict, key)

        self.assertRaises(AttributeError, lambda: configDict.e)
        self.assertRaises(AttributeError, lambda: configDict.f)

        # Keys may not begin with "_" in dict syntax
        def set():
            configDict["_x"] = "X"

        self.assertRaises(KeyError, set)

        # But attr syntax is OK
        configDict._x = "X"
        self.assertEquals(configDict._x, "X")
    def test_ConfigDict(self):
        configDict = ConfigDict({
            "a": "A",
            "b": "B",
            "c": "C",
        })

        # Test either syntax inbound
        configDict["d"] = "D"
        configDict.e = "E"

        # Test either syntax outbound
        for key in "abcde":
            value = key.upper()

            self.assertEquals(configDict[key], value)
            self.assertEquals(configDict.get(key), value)
            self.assertEquals(getattr(configDict, key), value)

            self.assertIn(key, configDict)
            self.assertTrue(hasattr(configDict, key))

        self.assertEquals(configDict.a, "A")
        self.assertEquals(configDict.d, "D")
        self.assertEquals(configDict.e, "E")

        # Test either syntax for delete
        del configDict["d"]
        delattr(configDict, "e")

        # Test either syntax for absence
        for key in "de":
            self.assertNotIn(key, configDict)
            self.assertFalse(hasattr(configDict, key))
            self.assertRaises(KeyError, lambda: configDict[key])
            self.assertRaises(AttributeError, getattr, configDict, key)

        self.assertRaises(AttributeError, lambda: configDict.e)
        self.assertRaises(AttributeError, lambda: configDict.f)

        # Keys may not begin with "_" in dict syntax
        def set():
            configDict["_x"] = "X"
        self.assertRaises(KeyError, set)

        # But attr syntax is OK
        configDict._x = "X"
        self.assertEquals(configDict._x, "X")
    def test_overridesConfig(self):
        """
        Test that values on the command line's -o and --option options
        overide the config file
        """
        myConfig = ConfigDict(DEFAULT_CONFIG)
        myConfigFile = self.mktemp()
        writePlist(myConfig, myConfigFile)

        argv = [
            "-f", myConfigFile,
            "-o", "EnableSACLs",
            "-o", "HTTPPort=80",
            "-o", "BindAddresses=127.0.0.1,127.0.0.2,127.0.0.3",
            "-o", "DocumentRoot=/dev/null",
            "-o", "UserName=None",
            "-o", "EnableProxyPrincipals=False",
        ]

        self.config.parseOptions(argv)

        self.assertEquals(config.EnableSACLs, True)
        self.assertEquals(config.HTTPPort, 80)
        self.assertEquals(config.BindAddresses,
                          ["127.0.0.1", "127.0.0.2", "127.0.0.3"])
        self.assertEquals(config.DocumentRoot, "/dev/null")
        self.assertEquals(config.UserName, None)
        self.assertEquals(config.EnableProxyPrincipals, False)

        argv = ["-o", "Authentication=This Doesn't Matter"]

        self.assertRaises(UsageError, self.config.parseOptions, argv)
示例#8
0
 def test_missingCertificate(self):
     success, _ignore_reason = verifyTLSCertificate(
         ConfigDict({
             "SSLCertificate": "missing",
             "SSLKeychainIdentity": "missing",
         }))
     self.assertFalse(success)
示例#9
0
    def test_updates(self):
        content = """<plist version="1.0">
    <dict>
        <key>key1</key>
        <string>before</string>
        <key>key2</key>
        <integer>10</integer>
    </dict>
</plist>"""
        self.fp.setContent(PREAMBLE + content)
        config = ConfigDict()
        writable = WritableConfig(config, self.configFile)
        writable.read()
        writable.set({"key1": "after"})
        writable.set({"key2": 15})
        writable.set({"key2": 20})  # override previous set
        writable.set({"key3": ["a", "b", "c"]})
        self.assertEquals(writable.currentConfigSubset, {
            "key1": "after",
            "key2": 20,
            "key3": ["a", "b", "c"]
        })
        writable.save()

        writable2 = WritableConfig(config, self.configFile)
        writable2.read()
        self.assertEquals(writable2.currentConfigSubset, {
            "key1": "after",
            "key2": 20,
            "key3": ["a", "b", "c"]
        })
示例#10
0
 def test_getPubSubAPSConfiguration(self):
     config = ConfigDict({
         "EnableSSL" : True,
         "ServerHostName" : "calendars.example.com",
         "SSLPort" : 8443,
         "HTTPPort" : 8008,
         "Notifications" : {
             "Services" : {
                 "APNS" : {
                     "CalDAV" : {
                         "Topic" : "test topic",
                     },
                     "SubscriptionRefreshIntervalSeconds" : 42,
                     "SubscriptionURL" : "apns",
                     "Environment" : "prod",
                     "Enabled" : True,
                 },
             },
         },
     })
     result = getPubSubAPSConfiguration(("CalDAV", "foo",), config)
     self.assertEquals(
         result,
         {
             "SubscriptionRefreshIntervalSeconds": 42,
             "SubscriptionURL": "https://calendars.example.com:8443/apns",
             "APSBundleID": "test topic",
             "APSEnvironment": "prod"
         }
     )
示例#11
0
 def test_emptyCertificate(self):
     certFilePath = FilePath(self.mktemp())
     certFilePath.setContent("")
     success, _ignore_reason = verifyTLSCertificate(
         ConfigDict({
             "SSLCertificate": certFilePath.path,
         }))
     self.assertFalse(success)
    def test_getLanguage(self):
        """
        Test that getLanguage( ) examines config.
        """

        self.assertEquals(
            getLanguage(ConfigDict({"Localization": {
                "Language": "xyzzy"
            }})), "xyzzy")
示例#13
0
    def test_specifyConfigFile(self):
        """
        Test that specifying a config file from the command line
        loads the global config with those values properly.
        """
        myConfig = ConfigDict(DEFAULT_CONFIG)

        myConfig.Authentication.Basic.Enabled = False
        myConfig.HTTPPort = 80
        myConfig.ServerHostName = "calendar.calenderserver.org"

        myConfigFile = self.mktemp()
        writePlist(myConfig, myConfigFile)

        args = ["-f", myConfigFile]

        self.config.parseOptions(args)

        self.assertEquals(config.ServerHostName, myConfig["ServerHostName"])
        self.assertEquals(config.HTTPPort, myConfig.HTTPPort)
        self.assertEquals(config.Authentication.Basic.Enabled, myConfig.Authentication.Basic.Enabled)
    def setUp(self):
        TestCase.setUp(self)
        self.options = TestCalDAVOptions()
        self.options.parent = Options()
        self.options.parent["gid"] = None
        self.options.parent["uid"] = None
        self.options.parent["nodaemon"] = None

        self.config = ConfigDict(DEFAULT_CONFIG)

        accountsFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/accounts.xml")
        resourcesFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/resources.xml")
        augmentsFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/augments.xml")
        pemFile = os.path.join(sourceRoot, "twistedcaldav/test/data/server.pem")

        self.config["DirectoryService"] = {
            "params": {"xmlFile": accountsFile},
            "type": "twistedcaldav.directory.xmlfile.XMLDirectoryService"
        }

        self.config["ResourceService"] = {
            "params": {"xmlFile": resourcesFile},
        }

        self.config["AugmentService"] = {
            "params": {"xmlFiles": [augmentsFile]},
            "type": "twistedcaldav.directory.augment.AugmentXMLDB"
        }

        self.config.UseDatabase    = False
        self.config.ServerRoot     = self.mktemp()
        self.config.ConfigRoot     = "config"
        self.config.ProcessType    = "Single"
        self.config.SSLPrivateKey  = pemFile
        self.config.SSLCertificate = pemFile
        self.config.EnableSSL      = True
        self.config.Memcached.Pools.Default.ClientEnabled = False
        self.config.Memcached.Pools.Default.ServerEnabled = False
        self.config.DirectoryAddressBook.Enabled = False

        self.config.SudoersFile = ""

        if self.configOptions:
            self.config.update(self.configOptions)

        os.mkdir(self.config.ServerRoot)
        os.mkdir(os.path.join(self.config.ServerRoot, self.config.DocumentRoot))
        os.mkdir(os.path.join(self.config.ServerRoot, self.config.DataRoot))
        os.mkdir(os.path.join(self.config.ServerRoot, self.config.ConfigRoot))

        self.configFile = self.mktemp()

        self.writeConfig()
示例#15
0
    def set(self, data):
        """
        Merges data into a ConfigDict of changes intended to be saved to disk
        when save( ) is called.

        @param data: a dict containing new values
        @type data: C{dict}
        """
        if not isinstance(data, ConfigDict):
            data = ConfigDict(mapping=data)
        mergeData(self.currentConfigSubset, data)
        self.dirty = True
示例#16
0
 def __init__(self, wrappedConfig, fileName):
     """
     @param wrappedConfig: the Config object to read from
     @type wrappedConfig: C{Config}
     @param fileName: the full path to the modifiable plist
     @type fileName: C{str}
     """
     self.config = wrappedConfig
     self.fileName = fileName
     self.changes = None
     self.currentConfigSubset = ConfigDict()
     self.dirty = False
示例#17
0
    def test_specifyConfigFile(self):
        """
        Test that specifying a config file from the command line
        loads the global config with those values properly.
        """
        myConfig = ConfigDict(DEFAULT_CONFIG)

        myConfig.Authentication.Basic.Enabled = False
        myConfig.HTTPPort = 80
        myConfig.ServerHostName = "calendar.calenderserver.org"

        myConfigFile = self.mktemp()
        writePlist(myConfig, myConfigFile)

        args = ["-f", myConfigFile]

        self.config.parseOptions(args)

        self.assertEquals(config.ServerHostName, myConfig["ServerHostName"])
        self.assertEquals(config.HTTPPort, myConfig.HTTPPort)
        self.assertEquals(config.Authentication.Basic.Enabled,
                          myConfig.Authentication.Basic.Enabled)
示例#18
0
    def test_readSuccessful(self):
        content = """<plist version="1.0">
    <dict>
        <key>string</key>
        <string>foo</string>
    </dict>
</plist>"""
        self.fp.setContent(PREAMBLE + content)

        config = ConfigDict()
        writable = WritableConfig(config, self.configFile)
        writable.read()
        self.assertEquals(writable.currentConfigSubset, {"string": "foo"})
示例#19
0
 def test_bogusCertificate(self):
     certFilePath = FilePath(self.mktemp())
     certFilePath.setContent("bogus")
     keyFilePath = FilePath(self.mktemp())
     keyFilePath.setContent("bogus")
     success, _ignore_reason = verifyTLSCertificate(
         ConfigDict({
             "SSLCertificate": certFilePath.path,
             "SSLPrivateKey": keyFilePath.path,
             "SSLAuthorityChain": "",
             "SSLMethod": "SSLv3_METHOD",
             "SSLCiphers":
             "ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM",
             "SSLKeychainIdentity": "missing",
         }))
     self.assertFalse(success)
示例#20
0
    def test_specifyDictPath(self):
        """
        Test that we can specify command line overrides to leafs using
        a "/" seperated path.  Such as "-o MultiProcess/ProcessCount=1"
        """
        myConfig = ConfigDict(DEFAULT_CONFIG)
        myConfigFile = self.mktemp()
        writePlist(myConfig, myConfigFile)

        argv = [
            "-o", "MultiProcess/ProcessCount=102",
            "-f", myConfigFile,
        ]

        self.config.parseOptions(argv)

        self.assertEquals(config.MultiProcess["ProcessCount"], 102)
示例#21
0
    def command_writeConfig(self, command):
        """
        Write config to secondary, writable plist

        @param command: the dictionary parsed from the plist read from stdin
        @type command: C{dict}
        """
        writable = WritableConfig(config, config.WritableConfigFile)
        writable.read()
        valuesToWrite = command.get("Values", {})
        # Note: values are unicode if they contain non-ascii
        for keyPath, value in flattenDictionary(valuesToWrite):
            if keyPath in WRITABLE_CONFIG_KEYS:
                writable.set(setKeyPath(ConfigDict(), keyPath, value))
        try:
            writable.save(restart=False)
        except Exception, e:
            self.respond(command, {"error": str(e)})
    def test_processLocalizationFiles(self):
        """
        Make sure that on OS X the .lproj files are converted properly.
        """
        if sys.platform == "darwin":
            tmpdir = self.mktemp()

            settings = ConfigDict({
                "TranslationsDirectory": os.path.join(os.path.dirname(__file__), "data", "translations"),
                "LocalesDirectory": tmpdir,
            })

            processLocalizationFiles(settings)

            self.assertTrue(os.path.exists(os.path.join(tmpdir, "Testlang", "LC_MESSAGES", "calendarserver.mo")))

            with translationTo('Testlang', localeDir=tmpdir):
                self.assertEquals(_("String1"), "string 1")
                self.assertEquals(_("String2"), "string 2")
示例#23
0
    def test_processArgs(self):
        """
        Ensure utf-8 encoded command line args are handled properly
        """
        content = """<plist version="1.0">
    <dict>
        <key>key1</key>
        <string>before</string>
    </dict>
</plist>"""
        self.fp.setContent(PREAMBLE + content)
        config = ConfigDict()
        writable = WritableConfig(config, self.configFile)
        writable.read()
        processArgs(writable, ["key1=\xf0\x9f\x92\xa3"], restart=False)
        writable2 = WritableConfig(config, self.configFile)
        writable2.read()
        self.assertEquals(writable2.currentConfigSubset,
                          {'key1': u'\U0001f4a3'})
示例#24
0
    def setUp(self):
        super(InboundTests, self).setUp()

        yield self.buildStoreAndDirectory()
        self.receiver = MailReceiver(self.store, self.directory)
        self.retriever = MailRetriever(
            self.store, self.directory,
            ConfigDict({
                "Type": "pop",
                "UseSSL": False,
                "Server": "example.com",
                "Port": 123,
                "Username": "******",
            }))

        def decorateTransaction(txn):
            txn._mailRetriever = self.retriever

        self.store.callWithNewTransactions(decorateTransaction)
        module = getModule(__name__)
        self.dataPath = module.filePath.sibling("data")
示例#25
0
    def test_setsParent(self):
        """
        Test that certain values are set on the parent (i.e. twistd's
        Option's object)
        """
        myConfig = ConfigDict(DEFAULT_CONFIG)
        myConfigFile = self.mktemp()
        writePlist(myConfig, myConfigFile)

        argv = [
            "-f", myConfigFile,
            "-o", "PIDFile=/dev/null",
            "-o", "umask=63",
            # integers in plists & calendarserver command line are always
            # decimal; umask is traditionally in octal.
        ]

        self.config.parseOptions(argv)

        self.assertEquals(self.config.parent["pidfile"], "/dev/null")
        self.assertEquals(self.config.parent["umask"], 0077)
示例#26
0
 def test_updateMultiProcess(self):
     def stubProcessCount(*args):
         return 3
     self.patch(twistedcaldav.stdconfig, "computeProcessCount", stubProcessCount)
     configDict = ConfigDict({
         "MultiProcess" : {
             "ProcessCount" : 0,
             "MinProcessCount" : 2,
             "PerCPU" : 1,
             "PerGB" : 1,
         },
         "Postgres" : {
             "ExtraConnections" : 5,
             "BuffersToConnectionsRatio" : 1.5,
         },
         "SharedConnectionPool" : False,
         "MaxDBConnectionsPerPool" : 10,
     })
     _updateMultiProcess(configDict)
     self.assertEquals(45, configDict.Postgres.MaxConnections)
     self.assertEquals(67, configDict.Postgres.SharedBuffers)
示例#27
0
    def test_keyPath(self):
        d = ConfigDict()
        setKeyPath(d, "one", "A")
        setKeyPath(d, "one", "B")
        setKeyPath(d, "two.one", "C")
        setKeyPath(d, "two.one", "D")
        setKeyPath(d, "two.two", "E")
        setKeyPath(d, "three.one.one", "F")
        setKeyPath(d, "three.one.two", "G")

        self.assertEquals(d.one, "B")
        self.assertEquals(d.two.one, "D")
        self.assertEquals(d.two.two, "E")
        self.assertEquals(d.three.one.one, "F")
        self.assertEquals(d.three.one.two, "G")

        self.assertEquals(getKeyPath(d, "one"), "B")
        self.assertEquals(getKeyPath(d, "two.one"), "D")
        self.assertEquals(getKeyPath(d, "two.two"), "E")
        self.assertEquals(getKeyPath(d, "three.one.one"), "F")
        self.assertEquals(getKeyPath(d, "three.one.two"), "G")
示例#28
0
def buildTestDirectory(store,
                       dataRoot,
                       accounts=None,
                       resources=None,
                       augments=None,
                       proxies=None,
                       serversDB=None):
    """
    @param store: the store for the directory to use

    @param dataRoot: the directory to copy xml files to

    @param accounts: path to the accounts.xml file
    @type accounts: L{FilePath}

    @param resources: path to the resources.xml file
    @type resources: L{FilePath}

    @param augments: path to the augments.xml file
    @type augments: L{FilePath}

    @param proxies: path to the proxies.xml file
    @type proxies: L{FilePath}

    @return: the directory service
    @rtype: L{IDirectoryService}
    """

    defaultDirectory = FilePath(__file__).sibling("accounts")
    if accounts is None:
        accounts = defaultDirectory.child("accounts.xml")
    if resources is None:
        resources = defaultDirectory.child("resources.xml")
    if augments is None:
        augments = defaultDirectory.child("augments.xml")
    if proxies is None:
        proxies = defaultDirectory.child("proxies.xml")

    if not os.path.exists(dataRoot):
        os.makedirs(dataRoot)

    accountsCopy = FilePath(dataRoot).child("accounts.xml")
    accountsCopy.setContent(accounts.getContent())

    resourcesCopy = FilePath(dataRoot).child("resources.xml")
    resourcesCopy.setContent(resources.getContent())

    augmentsCopy = FilePath(dataRoot).child("augments.xml")
    augmentsCopy.setContent(augments.getContent())

    proxiesCopy = FilePath(dataRoot).child("proxies.xml")
    proxiesCopy.setContent(proxies.getContent())

    servicesInfo = (
        ConfigDict({
            "Enabled": True,
            "type": "xml",
            "params": {
                "xmlFile": "accounts.xml",
                "recordTypes": ("users", "groups"),
            },
        }),
        ConfigDict({
            "Enabled": True,
            "type": "xml",
            "params": {
                "xmlFile": "resources.xml",
                "recordTypes": ("locations", "resources", "addresses"),
            },
        }),
    )
    augmentServiceInfo = ConfigDict({
        "type": "twistedcaldav.directory.augment.AugmentXMLDB",
        "params": {
            "xmlFiles": [
                "augments.xml",
            ],
            "statSeconds": 15,
        },
    })
    wikiServiceInfo = ConfigDict({
        "Enabled": True,
        "CollabHost": "localhost",
        "CollabPort": 4444,
    })
    directory = buildDirectory(store, dataRoot, servicesInfo,
                               augmentServiceInfo, wikiServiceInfo, serversDB)

    store.setDirectoryService(directory)

    return directory
示例#29
0
    def test_directoryFromConfig(self):

        config = ConfigDict({
            "DataRoot": self.dataRoot,
            "Authentication": {
                "Wiki": {
                    "Enabled": True,
                    "CollabHost": "localhost",
                    "CollabPort": 4444,
                },
            },
            "DirectoryService": {
                "Enabled": True,
                "type": "XML",
                "params": {
                    "xmlFile": "accounts.xml",
                    "recordTypes": ["users", "groups"],
                },
            },
            "ResourceService": {
                "Enabled": True,
                "type": "XML",
                "params": {
                    "xmlFile": "resources.xml",
                    "recordTypes": ["locations", "resources", "addresses"],
                },
            },
            "AugmentService": {
                "Enabled": True,
                # FIXME: This still uses an actual class name:
                "type": "twistedcaldav.directory.augment.AugmentXMLDB",
                "params": {
                    "xmlFiles": ["augments.xml"],
                },
            },
        })

        store = StubStore()
        service = directoryFromConfig(config, store=store)

        # Make sure XML files were created
        dataRoot = FilePath(self.dataRoot)
        self.assertTrue(dataRoot.child("accounts.xml").exists())
        self.assertTrue(dataRoot.child("resources.xml").exists())
        self.assertTrue(dataRoot.child("augments.xml").exists())

        # Inspect the directory service structure
        self.assertTrue(isinstance(service, AugmentedDirectoryService))
        self.assertTrue(
            isinstance(service._directory, AggregateDirectoryService))
        self.assertEquals(len(service._directory.services), 4)
        self.assertTrue(
            isinstance(service._directory.services[0], XMLDirectoryService))
        self.assertEquals(set(service._directory.services[0].recordTypes()),
                          set([RecordType.user, RecordType.group]))
        self.assertTrue(
            isinstance(service._directory.services[1], XMLDirectoryService))
        self.assertEquals(
            set(service._directory.services[1].recordTypes()),
            set([
                CalRecordType.location, CalRecordType.resource,
                CalRecordType.address
            ]))
        self.assertTrue(
            isinstance(service._directory.services[2],
                       DelegateDirectoryService))
        self.assertEquals(
            set(service._directory.services[2].recordTypes()),
            set([
                DelegateRecordType.readDelegateGroup,
                DelegateRecordType.writeDelegateGroup,
                DelegateRecordType.readDelegatorGroup,
                DelegateRecordType.writeDelegatorGroup,
            ]))
        self.assertTrue(
            isinstance(service._directory.services[3], WikiDirectoryService))
        self.assertEquals(set(service._directory.services[3].recordTypes()),
                          set([WikiRecordType.macOSXServerWiki]))

        # And make sure it's functional:
        record = yield service.recordWithUID("group07")
        self.assertEquals(record.fullNames, [u'Group 07'])
示例#30
0
    def test_ApplePushNotifierService(self):

        settings = ConfigDict({
            "Enabled": True,
            "SubscriptionURL": "apn",
            "SubscriptionPurgeSeconds": 24 * 60 * 60,
            "SubscriptionPurgeIntervalSeconds": 24 * 60 * 60,
            "ProviderHost": "gateway.push.apple.com",
            "ProviderPort": 2195,
            "FeedbackHost": "feedback.push.apple.com",
            "FeedbackPort": 2196,
            "FeedbackUpdateSeconds": 300,
            "EnableStaggering": True,
            "StaggerSeconds": 3,
            "CalDAV": {
                "Enabled": True,
                "CertificatePath": "caldav.cer",
                "PrivateKeyPath": "caldav.pem",
                "AuthorityChainPath": "chain.pem",
                "Passphrase": "",
                "KeychainIdentity": "org.calendarserver.test",
                "Topic": "caldav_topic",
            },
            "CardDAV": {
                "Enabled": True,
                "CertificatePath": "carddav.cer",
                "PrivateKeyPath": "carddav.pem",
                "AuthorityChainPath": "chain.pem",
                "Passphrase": "",
                "KeychainIdentity": "org.calendarserver.test",
                "Topic": "carddav_topic",
            },
        })

        # Add subscriptions
        txn = self._sqlCalendarStore.newTransaction()

        # Ensure empty values don't get through
        try:
            yield txn.addAPNSubscription("", "", "", "", "", "")
        except InvalidSubscriptionValues:
            pass
        try:
            yield txn.addAPNSubscription("", "1", "2", "3", "", "")
        except InvalidSubscriptionValues:
            pass

        token = "2d0d55cd7f98bcb81c6e24abcdc35168254c7846a43e2828b1ba5a8f82e219df"
        token2 = "3d0d55cd7f98bcb81c6e24abcdc35168254c7846a43e2828b1ba5a8f82e219df"
        key1 = "/CalDAV/calendars.example.com/user01/calendar/"
        timestamp1 = 1000
        uid = "D2256BCC-48E2-42D1-BD89-CBA1E4CCDFFB"
        userAgent = "test agent"
        ipAddr = "127.0.0.1"
        yield txn.addAPNSubscription(token, key1, timestamp1, uid, userAgent,
                                     ipAddr)
        yield txn.addAPNSubscription(token2, key1, timestamp1, uid, userAgent,
                                     ipAddr)

        key2 = "/CalDAV/calendars.example.com/user02/calendar/"
        timestamp2 = 3000
        yield txn.addAPNSubscription(token, key2, timestamp2, uid, userAgent,
                                     ipAddr)

        subscriptions = (yield txn.apnSubscriptionsBySubscriber(uid))
        subscriptions = [[
            record.token, record.resourceKey, record.modified,
            record.userAgent, record.ipAddr
        ] for record in subscriptions]
        self.assertTrue(
            [token, key1, timestamp1, userAgent, ipAddr] in subscriptions)
        self.assertTrue(
            [token, key2, timestamp2, userAgent, ipAddr] in subscriptions)
        self.assertTrue(
            [token2, key1, timestamp1, userAgent, ipAddr] in subscriptions)

        # Verify an update to a subscription with a different uid takes on
        # the new uid
        timestamp3 = 5000
        uid2 = "D8FFB335-9D36-4CE8-A3B9-D1859E38C0DA"
        yield txn.addAPNSubscription(token, key2, timestamp3, uid2, userAgent,
                                     ipAddr)
        subscriptions = (yield txn.apnSubscriptionsBySubscriber(uid))
        subscriptions = [[
            record.token, record.resourceKey, record.modified,
            record.userAgent, record.ipAddr
        ] for record in subscriptions]
        self.assertTrue(
            [token, key1, timestamp1, userAgent, ipAddr] in subscriptions)
        self.assertFalse(
            [token, key2, timestamp3, userAgent, ipAddr] in subscriptions)
        subscriptions = (yield txn.apnSubscriptionsBySubscriber(uid2))
        subscriptions = [[
            record.token, record.resourceKey, record.modified,
            record.userAgent, record.ipAddr
        ] for record in subscriptions]
        self.assertTrue(
            [token, key2, timestamp3, userAgent, ipAddr] in subscriptions)
        # Change it back
        yield txn.addAPNSubscription(token, key2, timestamp2, uid, userAgent,
                                     ipAddr)

        yield txn.commit()

        # Set up the service (note since Clock has no 'callWhenRunning' we add our own)
        def callWhenRunning(callable, *args):
            callable(*args)

        clock = Clock()
        clock.callWhenRunning = callWhenRunning

        service = (yield ApplePushNotifierService.makeService(
            settings,
            self._sqlCalendarStore,
            testConnectorClass=TestConnector,
            reactor=clock))
        self.assertEquals(set(service.providers.keys()),
                          set(["CalDAV", "CardDAV"]))
        self.assertEquals(set(service.feedbacks.keys()),
                          set(["CalDAV", "CardDAV"]))

        # First, enqueue a notification while we have no connection, in this
        # case by doing it prior to startService()

        # Notification arrives from calendar server
        dataChangedTimestamp = 1354815999
        txn = self._sqlCalendarStore.newTransaction()
        yield service.enqueue(txn,
                              "/CalDAV/calendars.example.com/user01/calendar/",
                              dataChangedTimestamp=dataChangedTimestamp,
                              priority=PushPriority.high)
        yield txn.commit()

        # The notifications should be in the queue
        self.assertTrue(
            ((token, key1), dataChangedTimestamp,
             PushPriority.high) in service.providers["CalDAV"].queue)
        self.assertTrue(
            ((token2, key1), dataChangedTimestamp,
             PushPriority.high) in service.providers["CalDAV"].queue)

        # Start the service, making the connection which should service the
        # queue
        service.startService()

        # The queue should be empty
        self.assertEquals(service.providers["CalDAV"].queue, [])

        # Verify data sent to APN
        providerConnector = service.providers["CalDAV"].testConnector
        rawData = providerConnector.transport.data
        self.assertEquals(len(rawData), 199)
        data = struct.unpack("!BI", rawData[:5])
        self.assertEquals(data[0], 2)  # command
        self.assertEquals(data[1], 194)  # frame length
        # Item 1 (device token)
        data = struct.unpack("!BH32s", rawData[5:40])
        self.assertEquals(data[0], 1)
        self.assertEquals(data[1], 32)
        self.assertEquals(data[2].encode("hex"), token.replace(" ",
                                                               ""))  # token
        # Item 2 (payload)
        data = struct.unpack("!BH", rawData[40:43])
        self.assertEquals(data[0], 2)
        payloadLength = data[1]
        self.assertEquals(payloadLength, 138)
        payload = struct.unpack("!%ds" % (payloadLength, ), rawData[43:181])
        payload = json.loads(payload[0])
        self.assertEquals(payload["key"],
                          u"/CalDAV/calendars.example.com/user01/calendar/")
        self.assertEquals(payload["dataChangedTimestamp"],
                          dataChangedTimestamp)
        self.assertTrue("pushRequestSubmittedTimestamp" in payload)
        # Item 3 (notification id)
        data = struct.unpack("!BHI", rawData[181:188])
        self.assertEquals(data[0], 3)
        self.assertEquals(data[1], 4)
        self.assertEquals(data[2], 2)
        # Item 4 (expiration)
        data = struct.unpack("!BHI", rawData[188:195])
        self.assertEquals(data[0], 4)
        self.assertEquals(data[1], 4)
        # Item 5 (priority)
        data = struct.unpack("!BHB", rawData[195:199])
        self.assertEquals(data[0], 5)
        self.assertEquals(data[1], 1)
        self.assertEquals(data[2], ApplePushPriority.high.value)

        # Verify token history is updated
        self.assertTrue(token in [
            t for (_ignore_i,
                   t) in providerConnector.service.protocol.history.history
        ])
        self.assertTrue(token2 in [
            t for (_ignore_i,
                   t) in providerConnector.service.protocol.history.history
        ])

        #
        # Verify staggering behavior
        #

        # Reset sent data
        providerConnector.transport.data = None
        # Send notification while service is connected
        txn = self._sqlCalendarStore.newTransaction()
        yield service.enqueue(txn,
                              "/CalDAV/calendars.example.com/user01/calendar/",
                              priority=PushPriority.low)
        yield txn.commit()
        clock.advance(1)  # so that first push is sent
        self.assertEquals(len(providerConnector.transport.data), 199)
        # Ensure that the priority is "low"
        data = struct.unpack("!BHB", providerConnector.transport.data[195:199])
        self.assertEquals(data[0], 5)
        self.assertEquals(data[1], 1)
        self.assertEquals(data[2], ApplePushPriority.low.value)

        # Reset sent data
        providerConnector.transport.data = None
        clock.advance(3)  # so that second push is sent
        self.assertEquals(len(providerConnector.transport.data), 199)

        history = []

        def errorTestFunction(status, identifier):
            history.append((status, identifier))
            return succeed(None)

        # Simulate an error
        errorData = struct.pack("!BBI", APNProviderProtocol.COMMAND_ERROR, 1,
                                2)
        yield providerConnector.receiveData(errorData, fn=errorTestFunction)
        clock.advance(301)

        # Simulate multiple errors and dataReceived called
        # with amounts of data not fitting message boundaries
        # Send 1st 4 bytes
        history = []
        errorData = struct.pack(
            "!BBIBBI",
            APNProviderProtocol.COMMAND_ERROR,
            3,
            4,
            APNProviderProtocol.COMMAND_ERROR,
            5,
            6,
        )
        yield providerConnector.receiveData(errorData[:4],
                                            fn=errorTestFunction)
        # Send remaining bytes
        yield providerConnector.receiveData(errorData[4:],
                                            fn=errorTestFunction)
        self.assertEquals(history, [(3, 4), (5, 6)])
        # Buffer is empty
        self.assertEquals(len(providerConnector.service.protocol.buffer), 0)

        # Sending 7 bytes
        yield providerConnector.receiveData("!" * 7, fn=errorTestFunction)
        # Buffer has 1 byte remaining
        self.assertEquals(len(providerConnector.service.protocol.buffer), 1)

        # Prior to feedback, there are 2 subscriptions
        txn = self._sqlCalendarStore.newTransaction()
        subscriptions = (yield txn.apnSubscriptionsByToken(token))
        yield txn.commit()
        self.assertEquals(len(subscriptions), 2)

        # Simulate feedback with a single token
        feedbackConnector = service.feedbacks["CalDAV"].testConnector
        timestamp = 2000
        binaryToken = token.decode("hex")
        feedbackData = struct.pack("!IH32s", timestamp, len(binaryToken),
                                   binaryToken)
        yield feedbackConnector.receiveData(feedbackData)

        # Simulate feedback with multiple tokens, and dataReceived called
        # with amounts of data not fitting message boundaries
        history = []

        def feedbackTestFunction(timestamp, token):
            history.append((timestamp, token))
            return succeed(None)

        timestamp = 2000
        binaryToken = token.decode("hex")
        feedbackData = struct.pack(
            "!IH32sIH32s",
            timestamp,
            len(binaryToken),
            binaryToken,
            timestamp,
            len(binaryToken),
            binaryToken,
        )
        # Send 1st 10 bytes
        yield feedbackConnector.receiveData(feedbackData[:10],
                                            fn=feedbackTestFunction)
        # Send remaining bytes
        yield feedbackConnector.receiveData(feedbackData[10:],
                                            fn=feedbackTestFunction)
        self.assertEquals(history, [(timestamp, token), (timestamp, token)])
        # Buffer is empty
        self.assertEquals(len(feedbackConnector.service.protocol.buffer), 0)

        # Sending 39 bytes
        yield feedbackConnector.receiveData("!" * 39, fn=feedbackTestFunction)
        # Buffer has 1 byte remaining
        self.assertEquals(len(feedbackConnector.service.protocol.buffer), 1)

        # The second subscription should now be gone
        txn = self._sqlCalendarStore.newTransaction()
        subscriptions = (yield txn.apnSubscriptionsByToken(token))
        yield txn.commit()
        self.assertEquals(len(subscriptions), 1)
        self.assertEqual(subscriptions[0].resourceKey,
                         "/CalDAV/calendars.example.com/user02/calendar/")
        self.assertEqual(subscriptions[0].modified, 3000)
        self.assertEqual(subscriptions[0].subscriberGUID,
                         "D2256BCC-48E2-42D1-BD89-CBA1E4CCDFFB")

        # Verify processError removes associated subscriptions and history
        # First find the id corresponding to token2
        for (id, t) in providerConnector.service.protocol.history.history:
            if t == token2:
                break

        yield providerConnector.service.protocol.processError(8, id)
        # The token for this identifier is gone
        self.assertTrue(
            (id,
             token2) not in providerConnector.service.protocol.history.history)

        # All subscriptions for this token should now be gone
        txn = self._sqlCalendarStore.newTransaction()
        subscriptions = (yield txn.apnSubscriptionsByToken(token2))
        yield txn.commit()
        self.assertEquals(subscriptions, [])

        #
        # Verify purgeOldAPNSubscriptions
        #

        # Create two subscriptions, one old and one new
        txn = self._sqlCalendarStore.newTransaction()
        now = int(time.time())
        yield txn.addAPNSubscription(token2, key1, now - 2 * 24 * 60 * 60, uid,
                                     userAgent, ipAddr)  # old
        yield txn.addAPNSubscription(token2, key2, now, uid, userAgent,
                                     ipAddr)  # recent
        yield txn.commit()

        # Purge old subscriptions
        txn = self._sqlCalendarStore.newTransaction()
        yield txn.purgeOldAPNSubscriptions(now - 60 * 60)
        yield txn.commit()

        # Check that only the recent subscription remains
        txn = self._sqlCalendarStore.newTransaction()
        subscriptions = (yield txn.apnSubscriptionsByToken(token2))
        yield txn.commit()
        self.assertEquals(len(subscriptions), 1)
        self.assertEquals(subscriptions[0].resourceKey, key2)

        service.stopService()
class BaseServiceMakerTests(TestCase):
    """
    Utility class for ServiceMaker tests.
    """
    configOptions = None

    def setUp(self):
        TestCase.setUp(self)
        self.options = TestCalDAVOptions()
        self.options.parent = Options()
        self.options.parent["gid"] = None
        self.options.parent["uid"] = None
        self.options.parent["nodaemon"] = None

        self.config = ConfigDict(DEFAULT_CONFIG)

        accountsFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/accounts.xml")
        resourcesFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/resources.xml")
        augmentsFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/augments.xml")
        pemFile = os.path.join(sourceRoot, "twistedcaldav/test/data/server.pem")

        self.config["DirectoryService"] = {
            "params": {"xmlFile": accountsFile},
            "type": "twistedcaldav.directory.xmlfile.XMLDirectoryService"
        }

        self.config["ResourceService"] = {
            "params": {"xmlFile": resourcesFile},
        }

        self.config["AugmentService"] = {
            "params": {"xmlFiles": [augmentsFile]},
            "type": "twistedcaldav.directory.augment.AugmentXMLDB"
        }

        self.config.ServerRoot     = self.mktemp()
        self.config.ConfigRoot     = "config"
        self.config.ProcessType    = "Slave"
        self.config.SSLPrivateKey  = pemFile
        self.config.SSLCertificate = pemFile
        self.config.Memcached.Pools.Default.ClientEnabled = False
        self.config.Memcached.Pools.Default.ServerEnabled = False
        self.config.DirectoryAddressBook.Enabled = False

        self.config.SudoersFile = ""

        if self.configOptions:
            self.config.update(self.configOptions)

        os.mkdir(self.config.ServerRoot)
        os.mkdir(os.path.join(self.config.ServerRoot, self.config.DocumentRoot))
        os.mkdir(os.path.join(self.config.ServerRoot, self.config.DataRoot))
        os.mkdir(os.path.join(self.config.ServerRoot, self.config.ConfigRoot))

        self.configFile = self.mktemp()

        self.writeConfig()

    def tearDown(self):
        config.setDefaults(DEFAULT_CONFIG)
        config.reset()

    def writeConfig(self):
        """
        Flush self.config out to self.configFile
        """
        writePlist(self.config, self.configFile)

    def makeService(self):
        """
        Create a service by calling into CalDAVServiceMaker with
        self.configFile
        """
        self.options.parseOptions(["-f", self.configFile])

        return CalDAVServiceMaker().makeService(self.options)

    def getSite(self):
        """
        Get the server.Site from the service by finding the HTTPFactory
        """
        service = self.makeService()

        return service.services[0].args[1].protocolArgs["requestFactory"]
示例#32
0
    def test_directoryFromConfig(self):

        config = ConfigDict({
            "DataRoot": self.dataRoot,
            "Authentication": {
                "Wiki": {
                    "Enabled": True,
                    "EndpointDescriptor": "tcp:host=localhost:port=4444",
                },
            },
            "DirectoryService": {
                "Enabled": True,
                "type": "xml",
                "params": {
                    "xmlFile": "accounts.xml",
                    "recordTypes": ["users", "groups"],
                },
            },
            "ResourceService": {
                "Enabled": True,
                "type": "xml",
                "params": {
                    "xmlFile": "resources.xml",
                    "recordTypes": ["locations", "resources", "addresses"],
                },
            },
            "AugmentService": {
                "type": "xml",
                "params": {
                    "xmlFiles": ["augments.xml"],
                },
            },
            "Servers": {
                "Enabled": False,
            },
            "DirectoryProxy": {
                "Enabled": False,
                "SocketPath": "directory-proxy.sock",
                "InSidecarCachingSeconds": 120,
            },
            "DirectoryCaching": {
                "CachingSeconds": 60,
                "NegativeCachingEnabled": True,
                "LookupsBetweenPurges": 0,
            },
            "DirectoryFilterStartsWith": False,
        })

        store = StubStore()
        service = directoryFromConfig(config, store)

        # Make sure XML files were created
        dataRoot = FilePath(self.dataRoot)
        self.assertTrue(dataRoot.child("accounts.xml").exists())
        self.assertTrue(dataRoot.child("resources.xml").exists())
        self.assertTrue(dataRoot.child("augments.xml").exists())

        # Inspect the directory service structure
        self.assertTrue(isinstance(service, AugmentedDirectoryService))
        self.assertTrue(
            isinstance(service._directory, AggregateDirectoryService))
        self.assertEquals(len(service._directory.services), 4)
        self.assertTrue(
            isinstance(service._directory.services[0],
                       DelegateDirectoryService))
        self.assertEquals(
            set(service._directory.services[0].recordTypes()),
            set([
                DelegateRecordType.readDelegateGroup,
                DelegateRecordType.writeDelegateGroup,
                DelegateRecordType.readDelegatorGroup,
                DelegateRecordType.writeDelegatorGroup,
            ]))
        self.assertTrue(
            isinstance(service._directory.services[1],
                       CachingDirectoryService))
        self.assertTrue(
            isinstance(service._directory.services[1]._directory,
                       XMLDirectoryService))
        self.assertEquals(
            set(service._directory.services[1]._directory.recordTypes()),
            set([RecordType.user, RecordType.group]))
        self.assertTrue(
            isinstance(service._directory.services[2]._directory,
                       XMLDirectoryService))
        self.assertEquals(
            set(service._directory.services[2]._directory.recordTypes()),
            set([
                CalRecordType.location, CalRecordType.resource,
                CalRecordType.address
            ]))
        self.assertTrue(
            isinstance(service._directory.services[3], WikiDirectoryService))
        self.assertEquals(set(service._directory.services[3].recordTypes()),
                          set([WikiRecordType.macOSXServerWiki]))

        # And make sure it's functional:
        record = yield service.recordWithUID("group07")
        self.assertEquals(record.fullNames, [u'Group 07'])
class BaseServiceMakerTests(StoreTestCase):
    """
    Utility class for ServiceMaker tests.
    """
    configOptions = None

    @inlineCallbacks
    def setUp(self):
        yield super(BaseServiceMakerTests, self).setUp()
        self.options = TestCalDAVOptions()
        self.options.parent = Options()
        self.options.parent["gid"] = None
        self.options.parent["uid"] = None
        self.options.parent["nodaemon"] = None

        self.config = ConfigDict(DEFAULT_CONFIG)

        accountsFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/accounts.xml")
        resourcesFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/resources.xml")
        augmentsFile = os.path.join(sourceRoot, "twistedcaldav/directory/test/augments.xml")
        pemFile = os.path.join(sourceRoot, "twistedcaldav/test/data/server.pem")

        self.config["DirectoryService"] = {
            "params": {"xmlFile": accountsFile},
            "type": "twistedcaldav.directory.xmlfile.XMLDirectoryService"
        }

        self.config["ResourceService"] = {
            "params": {"xmlFile": resourcesFile},
        }

        self.config["AugmentService"] = {
            "params": {"xmlFiles": [augmentsFile]},
            "type": "twistedcaldav.directory.augment.AugmentXMLDB"
        }

        self.config.UseDatabase = False
        self.config.ServerRoot = self.mktemp()
        self.config.ConfigRoot = "config"
        self.config.ProcessType = "Single"
        self.config.SSLPrivateKey = pemFile
        self.config.SSLCertificate = pemFile
        self.config.EnableSSL = True
        self.config.Memcached.Pools.Default.ClientEnabled = False
        self.config.Memcached.Pools.Default.ServerEnabled = False
        self.config.DirectoryAddressBook.Enabled = False
        self.config.UsePackageTimezones = True

        if self.configOptions:
            self.config.update(self.configOptions)

        os.mkdir(self.config.ServerRoot)
        os.mkdir(os.path.join(self.config.ServerRoot, self.config.DocumentRoot))
        os.mkdir(os.path.join(self.config.ServerRoot, self.config.DataRoot))
        os.mkdir(os.path.join(self.config.ServerRoot, self.config.ConfigRoot))

        self.configFile = self.mktemp()

        self.writeConfig()


    def tearDown(self):
        config.setDefaults(DEFAULT_CONFIG)
        config.reset()


    def writeConfig(self):
        """
        Flush self.config out to self.configFile
        """
        writePlist(self.config, self.configFile)


    def makeService(self, patcher=passthru):
        """
        Create a service by calling into CalDAVServiceMaker with
        self.configFile
        """
        self.options.parseOptions(["-f", self.configFile])

        maker = CalDAVServiceMaker()
        maker = patcher(maker)
        return maker.makeService(self.options)


    def getSite(self):
        """
        Get the server.Site from the service by finding the HTTPFactory.
        """
        service = self.makeService()
        for listeningService in inServiceHierarchy(
                service,
                # FIXME: need a better predicate for 'is this really an HTTP
                # factory' but this works for now.
                # NOTE: in a database 'single' configuration, PostgresService
                # will prevent the HTTP services from actually getting added to
                # the hierarchy until the hierarchy has started.
                # 'underlyingSite' assigned in caldav.py
                lambda x: hasattr(x, 'underlyingSite')
            ):
            return listeningService.underlyingSite
        raise RuntimeError("No site found.")
示例#34
0
 def test_readInvalidXML(self):
     self.fp.setContent("invalid")
     config = ConfigDict()
     writable = WritableConfig(config, self.configFile)
     self.assertRaises(ExpatError, writable.read)