Coverage for tests/test_server.py: 30%
78 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-10-02 07:59 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-10-02 07:59 +0000
1# This file is part of daf_butler.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
28import os.path
29import unittest
31try:
32 # Failing to import any of these should disable the tests.
33 import lsst.daf.butler.server
34 from fastapi.testclient import TestClient
35 from lsst.daf.butler.server import app
36except ImportError:
37 TestClient = None
38 app = None
40from lsst.daf.butler import Butler, CollectionType, Config, DataCoordinate, DatasetRef
41from lsst.daf.butler.tests import addDatasetType
42from lsst.daf.butler.tests.utils import MetricTestRepo, makeTestTempDir, removeTestTempDir
44TESTDIR = os.path.abspath(os.path.dirname(__file__))
47@unittest.skipIf(TestClient is None or app is None, "FastAPI not installed.")
48class ButlerClientServerTestCase(unittest.TestCase):
49 """Test for Butler client/server."""
51 @classmethod
52 def setUpClass(cls):
53 # First create a butler and populate it.
54 cls.root = makeTestTempDir(TESTDIR)
55 cls.repo = MetricTestRepo(root=cls.root, configFile=os.path.join(TESTDIR, "config/basic/butler.yaml"))
57 # Add a collection chain.
58 cls.repo.butler.registry.registerCollection("chain", CollectionType.CHAINED)
59 cls.repo.butler.registry.setCollectionChain("chain", ["ingest"])
61 # Globally change where the server thinks its butler repository
62 # is located. This will prevent any other server tests and is
63 # not a long term fix.
64 lsst.daf.butler.server.BUTLER_ROOT = cls.root
65 cls.client = TestClient(app)
67 # Create a client butler. We need to modify the contents of the
68 # server configuration to reflect the use of the test client.
69 response = cls.client.get("/butler/butler.json")
70 config = Config(response.json())
71 config["registry", "db"] = cls.client
73 # Since there is no client datastore we also need to specify
74 # the datastore root.
75 config["datastore", "root"] = cls.root
76 cls.butler = Butler(config)
78 @classmethod
79 def tearDownClass(cls):
80 removeTestTempDir(cls.root)
82 def test_simple(self):
83 response = self.client.get("/butler/")
84 self.assertEqual(response.status_code, 200)
85 self.assertIn("Butler Server", response.json())
87 response = self.client.get("/butler/butler.json")
88 self.assertEqual(response.status_code, 200)
89 self.assertIn("registry", response.json())
91 response = self.client.get("/butler/v1/universe")
92 self.assertEqual(response.status_code, 200)
93 self.assertIn("namespace", response.json())
95 def test_registry(self):
96 universe = self.butler.dimensions
97 self.assertEqual(universe.namespace, "daf_butler")
99 dataset_type = self.butler.registry.getDatasetType("test_metric_comp")
100 self.assertEqual(dataset_type.name, "test_metric_comp")
102 dataset_types = list(self.butler.registry.queryDatasetTypes(...))
103 self.assertIn("test_metric_comp", [ds.name for ds in dataset_types])
104 dataset_types = list(self.butler.registry.queryDatasetTypes("test_*"))
105 self.assertEqual(len(dataset_types), 1)
107 collections = self.butler.registry.queryCollections(
108 ..., collectionTypes={CollectionType.RUN, CollectionType.TAGGED}
109 )
110 self.assertEqual(len(collections), 2, collections)
112 collection_type = self.butler.registry.getCollectionType("ingest")
113 self.assertEqual(collection_type.name, "TAGGED")
115 chain = self.butler.registry.getCollectionChain("chain")
116 self.assertEqual(list(chain), ["ingest"])
118 datasets = list(self.butler.registry.queryDatasets("test_metric_comp", collections=...))
119 self.assertEqual(len(datasets), 2)
121 ref = self.butler.registry.getDataset(datasets[0].id)
122 self.assertEqual(ref, datasets[0])
124 locations = self.butler.registry.getDatasetLocations(ref)
125 self.assertEqual(locations[0], "FileDatastore@<butlerRoot>")
127 fake_ref = DatasetRef(
128 dataset_type,
129 dataId={"instrument": "DummyCamComp", "physical_filter": "d-r", "visit": 424},
130 run="missing",
131 )
132 locations = self.butler.registry.getDatasetLocations(fake_ref)
133 self.assertEqual(locations, [])
135 dataIds = list(self.butler.registry.queryDataIds("visit", dataId={"instrument": "DummyCamComp"}))
136 self.assertEqual(len(dataIds), 2)
138 # Create a DataCoordinate to test the alternate path for specifying
139 # a data ID.
140 data_id = DataCoordinate.standardize({"instrument": "DummyCamComp"}, universe=self.butler.dimensions)
141 records = list(self.butler.registry.queryDimensionRecords("physical_filter", dataId=data_id))
142 self.assertEqual(len(records), 1)
144 def test_experimental(self):
145 """Experimental interfaces."""
146 # Got URI testing we can not yet support disassembly so must
147 # add a dataset with a different dataset type.
148 datasetType = addDatasetType(
149 self.repo.butler, "metric", {"instrument", "visit"}, "StructuredCompositeReadCompNoDisassembly"
150 )
152 self.repo.addDataset({"instrument": "DummyCamComp", "visit": 424}, datasetType=datasetType)
153 self.butler.registry.refresh()
155 # Need a DatasetRef.
156 datasets = list(self.butler.registry.queryDatasets("metric", collections=...))
158 response = self.client.get(f"/butler/v1/uri/{datasets[0].id}")
159 self.assertEqual(response.status_code, 200)
160 self.assertIn("file://", response.json())
163if __name__ == "__main__":
164 unittest.main()