Skip to content

Commit f1d2eaf

Browse files
committed
Improve test suite by including CLI tests
1 parent cb9f4f9 commit f1d2eaf

File tree

11 files changed

+137
-18
lines changed

11 files changed

+137
-18
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,10 @@ tests/fmi3/passthrough/results-container-passthrough.csv
7272
tests/remoting/bouncing_ball-win64.fmu
7373
tests/remoting/results-bouncing_ball-win32.csv
7474
tests/remoting/results-bouncing_ball-win64.csv
75+
/tests/containers/bouncing_ball/cli-bouncing/
76+
/tests/containers/ssp/bouncing.dir/
77+
tests/cli-bouncing_ball.csv
78+
tests/containers/bouncing_ball/cli-bouncing.fmu
79+
tests/containers/arch/cli-flat-dump.json
80+
tests/containers/arch/cli-flat.fmu
81+

fmu_manipulation_toolbox/cli/fmucontainer.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import argparse
22
import logging
3+
import sys
34

5+
from typing import *
46
from pathlib import Path
57

68
from .utils import setup_logger, make_wide
@@ -9,7 +11,7 @@
911
from ..version import __version__ as version
1012

1113

12-
def fmucontainer():
14+
def fmucontainer(command_options: Sequence[str]):
1315
logger = setup_logger()
1416

1517
logger.info(f"FMUContainer version {version}")
@@ -63,7 +65,7 @@ def fmucontainer():
6365
parser.add_argument("-dump-json", action="store_true", dest="dump", default=False,
6466
help="Dump a JSON file for each container.")
6567

66-
config = parser.parse_args()
68+
config = parser.parse_args(command_options)
6769

6870
if config.debug:
6971
logger.setLevel(logging.DEBUG)
@@ -88,16 +90,16 @@ def fmucontainer():
8890
auto_parameter=config.auto_parameter)
8991
except FileNotFoundError as e:
9092
logger.fatal(f"Cannot read file: {e}")
91-
continue
93+
sys.exit(-1)
9294
except (FMUContainerError, AssemblyError) as e:
9395
logger.fatal(f"{filename}: {e}")
94-
continue
96+
sys.exit(-2)
9597

9698
try:
9799
assembly.make_fmu(dump_json=config.dump, fmi_version=int(config.fmi_version))
98100
except FMUContainerError as e:
99101
logger.fatal(f"{filename}: {e}")
100-
continue
102+
sys.exit(-3)
101103

102104
if __name__ == "__main__":
103-
fmucontainer()
105+
fmucontainer(sys.argv[1:])

fmu_manipulation_toolbox/cli/fmusplit.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import argparse
22
import logging
3+
import sys
4+
5+
from typing import *
36

47
from .utils import setup_logger, make_wide
58
from ..split import FMUSplitter, FMUSplitterError
69
from ..version import __version__ as version
710

811

9-
def fmusplit():
12+
def fmusplit(command_options: Sequence[str]):
1013
logger = setup_logger()
1114

1215
logger.info(f"FMUSplit version {version}")
@@ -24,7 +27,7 @@ def fmusplit():
2427
metavar="filename.fmu", required=True,
2528
help="Description of the FMU container to split.")
2629

27-
config = parser.parse_args()
30+
config = parser.parse_args(command_options)
2831

2932
if config.debug:
3033
logger.setLevel(logging.DEBUG)
@@ -35,11 +38,11 @@ def fmusplit():
3538
splitter.split_fmu()
3639
except FMUSplitterError as e:
3740
logger.fatal(f"{fmu_filename}: {e}")
38-
continue
41+
sys.exit(-1)
3942
except FileNotFoundError as e:
4043
logger.fatal(f"Cannot read file: {e}")
41-
continue
44+
sys.exit(-2)
4245

4346

4447
if __name__ == "__main__":
45-
fmusplit()
48+
fmusplit(sys.argv[1:])

fmu_manipulation_toolbox/cli/fmutool.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import argparse
22
import sys
33

4+
from typing import *
5+
46
from .utils import setup_logger, make_wide
57
from ..operations import (OperationSummary, OperationError, OperationRemoveRegexp,
68
OperationRemoveSources, OperationTrimUntil, OperationKeepOnlyRegexp, OperationMergeTopLevel,
@@ -12,7 +14,7 @@
1214
from ..help import Help
1315

1416

15-
def fmutool():
17+
def fmutool(command_options: Sequence[str]):
1618
logger = setup_logger()
1719

1820
logger.info(f"FMU Manipulation Toolbox version {version}")
@@ -68,7 +70,7 @@ def add_option(option, *args, **kwargs):
6870
add_option('-summary', action='append_const', dest='operations_list', const=OperationSummary())
6971
add_option('-check', action='append_const', dest='operations_list', const=[checker() for checker in checker_list])
7072

71-
cli_options = parser.parse_args()
73+
cli_options = parser.parse_args(command_options)
7274
# handle the "no operation" use case
7375
if not cli_options.operations_list:
7476
cli_options.operations_list = []
@@ -121,4 +123,4 @@ def operation_iterator():
121123
logger.info(f"INFO Modified FMU is not saved. If necessary use '-output' option.")
122124

123125
if __name__ == "__main__":
124-
fmutool()
126+
fmutool(sys.argv[1:])

fmu_manipulation_toolbox/split.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from typing import *
77
from pathlib import Path
88

9+
from .container import EmbeddedFMUPort
10+
911
logger = logging.getLogger("fmu_manipulation_toolbox")
1012

1113

@@ -66,7 +68,7 @@ def __del__(self):
6668
def split_fmu(self):
6769
logger.info(f"Splitting...")
6870
config = self._split_fmu(fmu_filename=str(self.fmu_filename), relative_path="")
69-
config_filename = self.directory / self.fmu_filename.with_suffix(".json")
71+
config_filename = self.directory / self.fmu_filename.with_suffix(".json").name
7072
with open(config_filename, "w") as file:
7173
json.dump(config, file, indent=2)
7274
logger.info(f"Container definition saved to '{config_filename}'")
@@ -77,7 +79,7 @@ def _split_fmu(self, fmu_filename: str, relative_path: str) -> Dict[str, Any]:
7779
if txt_filename in self.filenames_list:
7880
description = FMUSplitterDescription(self.zip)
7981
config = description.parse_txt_file(txt_filename)
80-
config["name"] = fmu_filename
82+
config["name"] = Path(fmu_filename).name
8183
for i, fmu_filename in enumerate(config["candidate_fmu"]):
8284
directory = f"{relative_path}resources/{i:02x}/"
8385
if directory not in self.dir_set:
@@ -134,6 +136,7 @@ def __init__(self, zip):
134136
self.current_vr = None
135137
self.current_name = None
136138
self.current_causality = None
139+
self.supported_fmi_types: Tuple[str] = ()
137140

138141
@staticmethod
139142
def get_line(file):
@@ -182,10 +185,12 @@ def parse_model_description(self, directory: str, fmu_filename: str):
182185
def parse_txt_file_header(self, file, txt_filename):
183186
flags = self.get_line(file).split(" ")
184187
if len(flags) == 1:
188+
self.supported_fmi_types = ("Real", "Integer", "Boolean", "String")
185189
self.config["mt"] = flags[0] == "1"
186190
self.config["profiling"] = self.get_line(file) == "1"
187191
self.config["sequential"] = False
188192
elif len(flags) == 3:
193+
self.supported_fmi_types = EmbeddedFMUPort.ALL_TYPES
189194
self.config["mt"] = flags[0] == "1"
190195
self.config["profiling"] = flags[1] == "1"
191196
self.config["sequential"] = flags[2] == "1"
@@ -242,7 +247,7 @@ def add_port(self, fmi_type: str, fmu_id: int, fmu_vr: int, container_vr: int):
242247
logger.debug(f"Adding container port {causality}: {definition}")
243248

244249
def parse_txt_file_ports(self, file):
245-
for fmi_type in ("Real", "Integer", "Boolean", "String"):
250+
for fmi_type in self.supported_fmi_types:
246251
nb_port_variables = self.get_line(file).split(" ")[0]
247252
for i in range(int(nb_port_variables)):
248253
tokens = self.get_line(file).split(" ")
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "cli-flat.fmu",
3+
"mt": false,
4+
"profiling": false,
5+
"sequential": false,
6+
"auto_link": true,
7+
"auto_input": true,
8+
"auto_output": true,
9+
"auto_parameter": false,
10+
"auto_local": false,
11+
"step_size": 0.5,
12+
"fmu": [
13+
"gain.fmu",
14+
"integrate.fmu",
15+
"sine.fmu"
16+
],
17+
"output": [
18+
[
19+
"gain.fmu",
20+
"final",
21+
"final"
22+
]
23+
],
24+
"link": [
25+
[
26+
"sine.fmu",
27+
"sine",
28+
"integrate.fmu",
29+
"sine"
30+
],
31+
[
32+
"integrate.fmu",
33+
"integrate",
34+
"gain.fmu",
35+
"integrate"
36+
]
37+
]
38+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"fmu": [
3+
"sine.fmu",
4+
"integrate.fmu",
5+
"gain.fmu"
6+
],
7+
"step_size": 0.5
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
rule;from_fmu;from_port;to_fmu;to_port
2+
FMU;bb_position.fmu;;;
3+
FMU;bb_velocity.fmu;;;
4+
OUTPUT;bb_position.fmu;position1;;position
5+
LINK;bb_position.fmu;is_ground;bb_velocity.fmu;reset
6+
LINK;bb_velocity.fmu;velocity;bb_position.fmu;velocity
7+
OUTPUT;bb_velocity.fmu;velocity;;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"auto_input": false,
3+
"auto_output": false,
4+
"auto_parameter": false,
5+
"auto_local": false,
6+
"auto_link": false,
7+
"mt": false,
8+
"profiling": false,
9+
"sequential": false,
10+
"step_size": 0.001,
11+
"name": "bouncing.fmu",
12+
"fmu": [
13+
"bb_velocity.fmu",
14+
"bb_position.fmu"
15+
]
16+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name;newName;valueReference;causality;variability;scalarType;startValue
2+
h;h;0;local;continuous;Real;1
3+
der(h);der(h);1;local;continuous;Real;
4+
v;v;2;local;continuous;Real;0
5+
der(v);der(v);3;local;continuous;Real;
6+
g;g;4;parameter;fixed;Real;9.81
7+
e;e;5;parameter;tunable;Real;0.7

0 commit comments

Comments
 (0)