Coverage for tests/test_server.py: 26%
78 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-06 02:33 -0700
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-06 02:33 -0700
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 program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
22import os.path
23import unittest
25try:
26 # Failing to import any of these should disable the tests.
27 import lsst.daf.butler.server
28 from fastapi.testclient import TestClient
29 from lsst.daf.butler.server import app
30except ImportError:
31 TestClient = None
32 app = None
34from lsst.daf.butler import Butler, CollectionType, Config, DataCoordinate, DatasetRef
35from lsst.daf.butler.tests import addDatasetType
36from lsst.daf.butler.tests.utils import MetricTestRepo, makeTestTempDir, removeTestTempDir
38TESTDIR = os.path.abspath(os.path.dirname(__file__))
41@unittest.skipIf(TestClient is None or app is None, "FastAPI not installed.")
42class ButlerClientServerTestCase(unittest.TestCase):
43 """Test for Butler client/server."""
45 @classmethod
46 def setUpClass(cls):
47 # First create a butler and populate it.
48 cls.root = makeTestTempDir(TESTDIR)
49 cls.repo = MetricTestRepo(root=cls.root, configFile=os.path.join(TESTDIR, "config/basic/butler.yaml"))
51 # Add a collection chain.
52 cls.repo.butler.registry.registerCollection("chain", CollectionType.CHAINED)
53 cls.repo.butler.registry.setCollectionChain("chain", ["ingest"])
55 # Globally change where the server thinks its butler repository
56 # is located. This will prevent any other server tests and is
57 # not a long term fix.
58 lsst.daf.butler.server.BUTLER_ROOT = cls.root
59 cls.client = TestClient(app)
61 # Create a client butler. We need to modify the contents of the
62 # server configuration to reflect the use of the test client.
63 response = cls.client.get("/butler/butler.json")
64 config = Config(response.json())
65 config["registry", "db"] = cls.client
67 # Since there is no client datastore we also need to specify
68 # the datastore root.
69 config["datastore", "root"] = cls.root
70 cls.butler = Butler(config)
72 @classmethod
73 def tearDownClass(cls):
74 removeTestTempDir(cls.root)
76 def test_simple(self):
77 response = self.client.get("/butler/")
78 self.assertEqual(response.status_code, 200)
79 self.assertIn("Butler Server", response.json())
81 response = self.client.get("/butler/butler.json")
82 self.assertEqual(response.status_code, 200)
83 self.assertIn("registry", response.json())
85 response = self.client.get("/butler/v1/universe")
86 self.assertEqual(response.status_code, 200)
87 self.assertIn("namespace", response.json())
89 def test_registry(self):
90 universe = self.butler.registry.dimensions
91 self.assertEqual(universe.namespace, "daf_butler")
93 dataset_type = self.butler.registry.getDatasetType("test_metric_comp")
94 self.assertEqual(dataset_type.name, "test_metric_comp")
96 dataset_types = list(self.butler.registry.queryDatasetTypes(...))
97 self.assertIn("test_metric_comp", [ds.name for ds in dataset_types])
98 dataset_types = list(self.butler.registry.queryDatasetTypes("test_*"))
99 self.assertEqual(len(dataset_types), 1)
101 collections = self.butler.registry.queryCollections(
102 ..., collectionTypes={CollectionType.RUN, CollectionType.TAGGED}
103 )
104 self.assertEqual(len(collections), 2, collections)
106 collection_type = self.butler.registry.getCollectionType("ingest")
107 self.assertEqual(collection_type.name, "TAGGED")
109 chain = self.butler.registry.getCollectionChain("chain")
110 self.assertEqual([coll for coll in chain], ["ingest"])
112 datasets = list(self.butler.registry.queryDatasets("test_metric_comp", collections=...))
113 self.assertEqual(len(datasets), 2)
115 ref = self.butler.registry.getDataset(datasets[0].id)
116 self.assertEqual(ref, datasets[0])
118 locations = self.butler.registry.getDatasetLocations(ref)
119 self.assertEqual(locations[0], "FileDatastore@<butlerRoot>")
121 fake_ref = DatasetRef(
122 dataset_type,
123 dataId={"instrument": "DummyCamComp", "physical_filter": "d-r", "visit": 424},
124 run="missing",
125 )
126 locations = self.butler.registry.getDatasetLocations(fake_ref)
127 self.assertEqual(locations, [])
129 dataIds = list(self.butler.registry.queryDataIds("visit", dataId={"instrument": "DummyCamComp"}))
130 self.assertEqual(len(dataIds), 2)
132 # Create a DataCoordinate to test the alternate path for specifying
133 # a data ID.
134 data_id = DataCoordinate.standardize(
135 {"instrument": "DummyCamComp"}, universe=self.butler.registry.dimensions
136 )
137 records = list(self.butler.registry.queryDimensionRecords("physical_filter", dataId=data_id))
138 self.assertEqual(len(records), 1)
140 def test_experimental(self):
141 """Experimental interfaces."""
142 # Got URI testing we can not yet support disassembly so must
143 # add a dataset with a different dataset type.
144 datasetType = addDatasetType(
145 self.repo.butler, "metric", {"instrument", "visit"}, "StructuredCompositeReadCompNoDisassembly"
146 )
148 self.repo.addDataset({"instrument": "DummyCamComp", "visit": 424}, datasetType=datasetType)
149 self.butler.registry.refresh()
151 # Need a DatasetRef.
152 datasets = list(self.butler.registry.queryDatasets("metric", collections=...))
154 response = self.client.get(f"/butler/v1/uri/{datasets[0].id}")
155 self.assertEqual(response.status_code, 200)
156 self.assertIn("file://", response.json())
159if __name__ == "__main__":
160 unittest.main()