Coverage for tests / tests_config / tests_description / test_config_blocks.py: 100%

69 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-09 16:40 +0100

1# SPDX-FileCopyrightText: Copyright INRIA 

2# 

3# SPDX-License-Identifier: LGPL-3.0-only 

4# 

5# Copyright INRIA 

6# 

7# This file is part of PhysioBlocks, a library mostly developed by the 

8# [Ananke project-team](https://team.inria.fr/ananke) at INRIA. 

9# 

10# Authors: 

11# - Colin Drieu 

12# - Dominique Chapelle 

13# - François Kimmig 

14# - Philippe Moireau 

15# 

16# PhysioBlocks is free software: you can redistribute it and/or modify it under the 

17# terms of the GNU Lesser General Public License as published by the Free Software 

18# Foundation, version 3 of the License. 

19# 

20# PhysioBlocks is distributed in the hope that it will be useful, but WITHOUT ANY 

21# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 

22# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 

23# 

24# You should have received a copy of the GNU Lesser General Public License along with 

25# PhysioBlocks. If not, see <https://www.gnu.org/licenses/>. 

26 

27from dataclasses import dataclass 

28from typing import Any 

29from unittest.mock import patch 

30 

31import pytest 

32 

33from physioblocks.computing.models import Block, ModelComponent 

34from physioblocks.computing.quantities import Quantity 

35from physioblocks.configuration import Configuration 

36from physioblocks.configuration.constants import ( 

37 BLOCK_FLUX_TYPE_ITEM_ID, 

38 MODEL_COMPONENT_TYPE_ITEM_ID, 

39 SUBMODEL_ITEM_ID, 

40) 

41from physioblocks.configuration.description.blocks import ( 

42 PARAMETERS_ITEM_ID, 

43 load_block_description_config, 

44 save_block_description_config, 

45) 

46from physioblocks.description.blocks import ( 

47 BLOCK_DESCRIPTION_TYPE_ID, 

48 ID_SEPARATOR, 

49 MODEL_DESCRIPTION_TYPE_ID, 

50 BlockDescription, 

51 ModelComponentDescription, 

52) 

53 

54BLOCK_A_ID = "block_a" 

55BLOCK_A_TYPE_ID = "BlockA" 

56MODEL_B_TYPE_ID = "ModelComponentB" 

57SUBMODEL_KEY = "submodel" 

58PARAM_LOCAL_ID_A = "a" 

59PARAM_LOCAL_ID_B = "b" 

60PARAM_LOCAL_ID_C = "c" 

61PARAM_GLOBAL_ID_A = "param_a" 

62PARAM_GLOBAL_ID_B = "param_b" 

63PARAM_GLOBAL_ID_C = "param_c" 

64TIME_GLOBAL_ID = "time" 

65FLUX_TYPE = "flux" 

66 

67 

68@dataclass 

69class BlockA(Block): 

70 a: Quantity[Any] 

71 b: Quantity[Any] 

72 c: Quantity[Any] 

73 

74 

75@dataclass 

76class ModelComponentB(ModelComponent): 

77 a: Quantity[Any] 

78 b: Quantity[Any] 

79 c: Quantity[Any] 

80 

81 

82@pytest.fixture 

83def ref_block_desc(): 

84 block_desc = BlockDescription( 

85 BLOCK_A_ID, 

86 BlockA, 

87 FLUX_TYPE, 

88 { 

89 PARAM_LOCAL_ID_A: PARAM_GLOBAL_ID_A, 

90 PARAM_LOCAL_ID_B: PARAM_GLOBAL_ID_B, 

91 }, 

92 ) 

93 block_desc.add_submodel( 

94 SUBMODEL_KEY, 

95 ModelComponentDescription( 

96 SUBMODEL_KEY, 

97 ModelComponentB, 

98 { 

99 PARAM_LOCAL_ID_A: PARAM_GLOBAL_ID_C, 

100 PARAM_LOCAL_ID_B: PARAM_GLOBAL_ID_A, 

101 }, 

102 ), 

103 ) 

104 return block_desc 

105 

106 

107@pytest.fixture 

108def ref_config() -> Configuration: 

109 config = Configuration(BLOCK_DESCRIPTION_TYPE_ID) 

110 config[MODEL_COMPONENT_TYPE_ITEM_ID] = BLOCK_A_TYPE_ID 

111 config[BLOCK_FLUX_TYPE_ITEM_ID] = FLUX_TYPE 

112 config[PARAMETERS_ITEM_ID] = {} 

113 config[PARAMETERS_ITEM_ID][PARAM_LOCAL_ID_A] = PARAM_GLOBAL_ID_A 

114 config[PARAMETERS_ITEM_ID][PARAM_LOCAL_ID_B] = PARAM_GLOBAL_ID_B 

115 submodel_config = Configuration(MODEL_DESCRIPTION_TYPE_ID) 

116 submodel_config[MODEL_COMPONENT_TYPE_ITEM_ID] = MODEL_B_TYPE_ID 

117 submodel_config[PARAMETERS_ITEM_ID] = {} 

118 submodel_config[PARAMETERS_ITEM_ID][PARAM_LOCAL_ID_A] = PARAM_GLOBAL_ID_C 

119 submodel_config[PARAMETERS_ITEM_ID][PARAM_LOCAL_ID_B] = PARAM_GLOBAL_ID_A 

120 config[SUBMODEL_ITEM_ID] = {SUBMODEL_KEY: submodel_config} 

121 return config 

122 

123 

124@pytest.fixture 

125def saved_config_ref(ref_config: Configuration) -> Configuration: 

126 config = ref_config 

127 config[MODEL_COMPONENT_TYPE_ITEM_ID] = BLOCK_A_TYPE_ID 

128 config[PARAMETERS_ITEM_ID][PARAM_LOCAL_ID_C] = ID_SEPARATOR.join( 

129 [BLOCK_A_ID, PARAM_LOCAL_ID_C] 

130 ) 

131 config[SUBMODEL_ITEM_ID][SUBMODEL_KEY][PARAMETERS_ITEM_ID][PARAM_LOCAL_ID_C] = ( 

132 ID_SEPARATOR.join([BLOCK_A_ID, SUBMODEL_KEY, PARAM_LOCAL_ID_C]) 

133 ) 

134 return config 

135 

136 

137@patch( 

138 "physioblocks.registers.type_register.__type_register", 

139 new={ 

140 BLOCK_DESCRIPTION_TYPE_ID: BlockDescription, 

141 BlockDescription: BLOCK_DESCRIPTION_TYPE_ID, 

142 MODEL_DESCRIPTION_TYPE_ID: ModelComponentDescription, 

143 ModelComponentDescription: MODEL_DESCRIPTION_TYPE_ID, 

144 BLOCK_A_TYPE_ID: BlockA, 

145 BlockA: BLOCK_A_TYPE_ID, 

146 MODEL_B_TYPE_ID: ModelComponentB, 

147 ModelComponentB: MODEL_B_TYPE_ID, 

148 }, 

149) 

150def test_get_block_config( 

151 saved_config_ref: Configuration, ref_block_desc: BlockDescription 

152): 

153 configuration = save_block_description_config(ref_block_desc) 

154 assert saved_config_ref == configuration 

155 

156 

157@patch( 

158 "physioblocks.registers.type_register.__type_register", 

159 new={ 

160 BLOCK_DESCRIPTION_TYPE_ID: BlockDescription, 

161 BlockDescription: BLOCK_DESCRIPTION_TYPE_ID, 

162 MODEL_DESCRIPTION_TYPE_ID: ModelComponentDescription, 

163 ModelComponentDescription: MODEL_DESCRIPTION_TYPE_ID, 

164 BLOCK_A_TYPE_ID: BlockA, 

165 BlockA: BLOCK_A_TYPE_ID, 

166 MODEL_B_TYPE_ID: ModelComponentB, 

167 ModelComponentB: MODEL_B_TYPE_ID, 

168 }, 

169) 

170def test_configure_block(ref_config: Configuration, ref_block_desc: BlockDescription): 

171 block_desc = load_block_description_config(ref_config, BLOCK_A_ID, BlockDescription) 

172 assert isinstance(block_desc, BlockDescription) 

173 assert block_desc.global_ids == ref_block_desc.global_ids 

174 assert ( 

175 block_desc.submodels[SUBMODEL_KEY].global_ids 

176 == ref_block_desc.submodels[SUBMODEL_KEY].global_ids 

177 )