Coverage for tests/test_dotTools.py: 36%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of ctrl_mpexec.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://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 <https://www.gnu.org/licenses/>.
22"""Simple unit test for Pipeline.
23"""
25import io
26import re
27import unittest
29from lsst.pipe.base import (PipelineTask, PipelineTaskConfig,
30 Pipeline, PipelineTaskConnections)
31import lsst.pipe.base.connectionTypes as cT
32from lsst.ctrl.mpexec.dotTools import pipeline2dot
33import lsst.utils.tests
36class ExamplePipelineTaskConnections(PipelineTaskConnections, dimensions=()):
37 input1 = cT.Input(name="",
38 dimensions=["visit", "detector"],
39 storageClass="example",
40 doc="Input for this task")
41 input2 = cT.Input(name="",
42 dimensions=["visit", "detector"],
43 storageClass="example",
44 doc="Input for this task")
45 output1 = cT.Output(name="",
46 dimensions=["visit", "detector"],
47 storageClass="example",
48 doc="Output for this task")
49 output2 = cT.Output(name="",
50 dimensions=["visit", "detector"],
51 storageClass="example",
52 doc="Output for this task")
54 def __init__(self, *, config=None):
55 super().__init__(config=config)
56 if not config.connections.input2:
57 self.inputs.remove("input2")
58 if not config.connections.output2:
59 self.outputs.remove("output2")
62class ExamplePipelineTaskConfig(PipelineTaskConfig, pipelineConnections=ExamplePipelineTaskConnections):
63 pass
66def _makeConfig(inputName, outputName, pipeline, label):
67 """Factory method for config instances
69 inputName and outputName can be either string or tuple of strings
70 with two items max.
71 """
72 if isinstance(inputName, tuple):
73 pipeline.addConfigOverride(label, "connections.input1", inputName[0])
74 pipeline.addConfigOverride(label, "connections.input2", inputName[1] if len(inputName) > 1 else "")
75 else:
76 pipeline.addConfigOverride(label, "connections.input1", inputName)
78 if isinstance(outputName, tuple):
79 pipeline.addConfigOverride(label, "connections.output1", outputName[0])
80 pipeline.addConfigOverride(label, "connections.output2", outputName[1] if len(outputName) > 1 else "")
81 else:
82 pipeline.addConfigOverride(label, "connections.output1", outputName)
85class ExamplePipelineTask(PipelineTask):
86 ConfigClass = ExamplePipelineTaskConfig
89def _makePipeline(tasks):
90 """Generate Pipeline instance.
92 Parameters
93 ----------
94 tasks : list of tuples
95 Each tuple in the list has 3 or 4 items:
96 - input DatasetType name(s), string or tuple of strings
97 - output DatasetType name(s), string or tuple of strings
98 - task label, string
99 - optional task class object, can be None
101 Returns
102 -------
103 Pipeline instance
104 """
105 pipe = Pipeline("test pipeline")
106 for task in tasks:
107 inputs = task[0]
108 outputs = task[1]
109 label = task[2]
110 klass = task[3] if len(task) > 3 else ExamplePipelineTask
111 pipe.addTask(klass, label)
112 _makeConfig(inputs, outputs, pipe, label)
113 return list(pipe.toExpandedPipeline())
116class DotToolsTestCase(unittest.TestCase):
117 """A test case for dotTools
118 """
120 def testPipeline2dot(self):
121 """Tests for dotTools.pipeline2dot method
122 """
123 pipeline = _makePipeline([("A", ("B", "C"), "task1"),
124 ("C", "E", "task2"),
125 ("B", "D", "task3"),
126 (("D", "E"), "F", "task4")])
127 file = io.StringIO()
128 pipeline2dot(pipeline, file)
130 # It's hard to validate complete output, just checking few basic
131 # things, even that is not terribly stable.
132 lines = file.getvalue().strip().split('\n')
133 ndatasets = 6
134 ntasks = 4
135 nedges = 10
136 nextra = 2 # graph header and closing
137 self.assertEqual(len(lines), ndatasets + ntasks + nedges + nextra)
139 # make sure that all node names are quoted
140 nodeRe = re.compile(r"^([^ ]+) \[.+\];$")
141 edgeRe = re.compile(r"^([^ ]+) *-> *([^ ]+);$")
142 for line in lines:
143 match = nodeRe.match(line)
144 if match:
145 node = match.group(1)
146 self.assertEqual(node[0] + node[-1], '""')
147 continue
148 match = edgeRe.match(line)
149 if match:
150 for group in (1, 2):
151 node = match.group(group)
152 self.assertEqual(node[0] + node[-1], '""')
153 continue
156class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase):
157 pass
160def setup_module(module):
161 lsst.utils.tests.init()
164if __name__ == "__main__": 164 ↛ 165line 164 didn't jump to line 165, because the condition on line 164 was never true
165 lsst.utils.tests.init()
166 unittest.main()