source: trunk/Python/src/tests_jmodelica/general/test_extfunctions.py @ 13719

Last change on this file since 13719 was 13719, checked in by Christian Andersson, 2 months ago

Recommitted changeset:13700 to trunk with two bug fixes. Related to ticket:5837

File size: 36.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (C) 2010-2017 Modelon AB
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, version 3 of the License.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17"""
18Module for testing external function support.
19"""
20import os, subprocess, shutil
21from os.path import join as path
22
23import nose
24import fnmatch
25
26from pymodelica import compile_fmu
27from pymodelica.common.core import get_platform_dir, create_temp_dir
28from pyfmi import load_fmu, FMUModelME2
29from pyfmi.fmi import FMUException
30from tests_jmodelica import testattr, get_files_path
31from tests_jmodelica.general.base_simul import *
32from assimulo.solvers.sundials import CVodeError
33
34path_to_mofiles = os.path.join(get_files_path(), 'Modelica')
35
36class TestEvaluator:
37    @classmethod
38    def setUpClass(cls):
39        """
40        Sets up the test class.
41        """
42        cls.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
43   
44    @testattr(stddist_base = True)
45    def test_builtin_substring(self):
46        cpath = "ExtFunctionTests.Evaluator_Substring"
47        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log.txt")
48       
49        nbr_of_evaluator_calls = 0
50        with open("log.txt") as f:
51            res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
52            nbr_of_evaluator_calls = len(res)
53       
54        assert nbr_of_evaluator_calls == 4, "Wrong number of external function calls, check log."
55       
56        model = load_fmu(fmu_name)
57       
58        assert model.get("sub")[0] == "Y", model.get("sub")
59        assert model.get("string2")[0] == "line", model.get("string2")
60        assert model.get("len") == 16, model.get("len")
61        assert model.get("start") == 4, model.get("start")
62        assert not model.get("not_equal"), model.get("not_equal")
63        assert model.get("equal"), model.get("equal")
64   
65    @testattr(stddist_base = True)
66    def test_add(self):
67        cpath = "ExtFunctionTests.Evaluator_Add"
68        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, version=2.0, compiler_log_level="d:log.txt")
69       
70        nbr_of_evaluator_calls = 0
71        with open("log.txt") as f:
72            res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
73            nbr_of_evaluator_calls = len(res)
74       
75        assert nbr_of_evaluator_calls == 2, "Wrong number of external function calls, check log."
76       
77        model = FMUModelME2(fmu_name, _connect_dll=False)
78       
79        assert model.get_variable_start("c") == 3, model.get_variable_start("c")
80        assert model.get_variable_start("d") == 3, model.get_variable_start("d")
81   
82    @testattr(stddist_base = True)
83    def test_unsupported_signature(self):
84        cpath = "ExtFunctionTests.Evaluator_Multiple_Add"
85        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log.txt")
86       
87        matches = 0
88        with open("log.txt") as f:
89            res = fnmatch.filter(f, "*is not supported. Disabling use of the evaluator*")
90            matches = len(res)
91       
92        assert matches == 1, "Does not seem to disabling the evaluator"
93
94    @testattr(stddist_base = True)
95    def test_unknown_shared_library(self):
96        cpath = "ExtFunctionTests.Evaluator_Unknown_Shared"
97        try:
98            fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, compiler_log_level="d:log_unknown_shared.txt")
99        except: #The compilation will fail, the interesting parts will though still be contained in the log file
100            pass
101       
102        matches = 0
103        with open("log_unknown_shared.txt") as f:
104            res = fnmatch.filter(f, "Could not find a shared library containing*")
105            matches = len(res)
106       
107        assert matches == 1, "Seems to have found an unknown shared library"
108   
109    @testattr(stddist_base = True)
110    def test_double_return(self):
111        cpath = "ExtFunctionTests.Evaluator_Double"
112        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, version=2.0, compiler_log_level="d:log.txt")
113       
114        nbr_of_evaluator_calls = 0
115        with open("log.txt") as f:
116            res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
117            nbr_of_evaluator_calls = len(res)
118       
119        assert nbr_of_evaluator_calls == 2, "Wrong number of external function calls, check log."
120       
121        model = FMUModelME2(fmu_name, _connect_dll=False)
122       
123        assert model.get_variable_start("c") == 3.0, model.get_variable_start("c")
124        assert model.get_variable_start("d") == 9.0, model.get_variable_start("d")
125   
126    @testattr(stddist_base = True)
127    def test_integer_return(self):
128        cpath = "ExtFunctionTests.Evaluator_Integer"
129        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, version=2.0, compiler_log_level="d:log.txt")
130       
131        nbr_of_evaluator_calls = 0
132        with open("log.txt") as f:
133            res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
134            nbr_of_evaluator_calls = len(res)
135       
136        assert nbr_of_evaluator_calls == 1, "Wrong number of external function calls, check log."
137       
138        model = FMUModelME2(fmu_name, _connect_dll=False)
139       
140        assert model.get_variable_start("c") == 3.0, model.get_variable_start("c")
141   
142    @testattr(stddist_base = True)
143    def test_record(self):
144        cpath = "ExtFunctionTests.Evaluator_Record"
145        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"external_constant_evaluation_dynamic":True}, version=2.0, compiler_log_level="d:log.txt")
146       
147        nbr_of_evaluator_calls = 0
148        with open("log.txt") as f:
149            res = fnmatch.filter(f, "Succesfully connected external function '*' to the evaluator*")
150            nbr_of_evaluator_calls = len(res)
151       
152        assert nbr_of_evaluator_calls == 1, "Wrong number of external function calls, check log."
153       
154        model = FMUModelME2(fmu_name, _connect_dll=False)
155       
156        assert model.get_variable_start("c.x0") == 1.0, model.get_variable_start("c.x0")
157        assert model.get_variable_start("c.x1") == 2.0, model.get_variable_start("c.x1")
158        assert model.get_variable_start("c.x2") == 3.0, model.get_variable_start("c.x2")
159        assert model.get_variable_start("c.x3") == 3.0, model.get_variable_start("c.x3")
160        assert model.get_variable_start("c.x4") == 4.0, model.get_variable_start("c.x4")
161        assert model.get_variable_start("c.x5") == 5.0, model.get_variable_start("c.x5")
162        assert model.get_variable_start("c.x6") == 6.0, model.get_variable_start("c.x6")
163        assert model.get_variable_start("c.x7") == 7.0, model.get_variable_start("c.x7")
164        assert model.get_variable_start("c.x8") == 8.0, model.get_variable_start("c.x8")
165        assert model.get_variable_start("c.x9") == 9.0, model.get_variable_start("c.x9")
166        assert model.get_variable_start("c.x10") == 10.0, model.get_variable_start("c.x10")
167   
168class TestExternalStatic:
169
170    @classmethod
171    def setUpClass(cls):
172        """
173        Sets up the test class.
174        """
175        cls.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
176   
177    @testattr(stddist_base = True)
178    def test_ExtFuncStatic(self):
179        """
180        Test compiling a model with external functions in a static library.
181        """
182        cpath = "ExtFunctionTests.ExtFunctionTest1"
183        fmu_name = compile_fmu(cpath, TestExternalStatic.fpath)
184        model = load_fmu(fmu_name)
185   
186    @testattr(stddist_base = True)
187    def test_IntegerArrays(self):
188        """
189        Test a model with external functions containing integer array and literal inputs.
190        """
191        cpath = "ExtFunctionTests.ExtFunctionTest4"
192        fmu_name = compile_fmu(cpath, TestExternalStatic.fpath, compiler_options={'variability_propagation':False})
193        model = load_fmu(fmu_name)
194        res = model.simulate()
195       
196        nose.tools.assert_equals(res.final('myResult[1]'), 2) 
197        nose.tools.assert_equals(res.final('myResult[2]'), 4)
198        nose.tools.assert_equals(res.final('myResult[3]'), 6)
199       
200class TestUtilities:
201   
202    @testattr(stddist_base = True)
203    def test_ModelicaUtilities(self):
204        """
205        Test compiling a model with external functions using the functions in ModelicaUtilities.
206        """
207        fpath = path(get_files_path(), 'Modelica', "ExtFunctionTests.mo")
208        cpath = "ExtFunctionTests.ExtFunctionTest3"
209        fmu_name = compile_fmu(cpath, fpath, compiler_options={'variability_propagation':False})
210        model = load_fmu(fmu_name)
211        #model.simulate()
212
213class TestExternalShared:
214   
215    @classmethod
216    def setUpClass(self):
217        """
218        Sets up the test class.
219        """
220        self.cpath = "ExtFunctionTests.ExtFunctionTest1"
221        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
222       
223    @testattr(stddist_base = True)
224    def test_ExtFuncShared(self):
225        """
226        Test compiling a model with external functions in a shared library. Simple.
227        """
228        fmu_name = compile_fmu(self.cpath, self.fpath, compiler_options={'variability_propagation':False})
229        model = load_fmu(fmu_name)
230        res = model.simulate()
231        nose.tools.assert_equals(res.final('c'), 3) 
232       
233    @testattr(stddist_base = True)
234    def test_ExtFuncSharedCeval(self):
235        """
236        Test compiling a model with external functions in a shared library. Constant evaluation during compilation.
237        """
238        fmu_name = compile_fmu(self.cpath, self.fpath, compiler_options={'variability_propagation':True})
239        model = load_fmu(fmu_name)
240        nose.tools.assert_equals(model.get('c'), 3)
241       
242    @testattr(stddist_full = True)
243    def test_ExtFuncSharedCevalDisabled(self):
244        """
245        Test compiling a model with external functions in a shared library. Disabling external evaluation during
246        variability propagation.
247        """
248        fmu_name = compile_fmu(self.cpath, self.fpath, compiler_options={'variability_propagation':True,
249            'variability_propagation_external':False})
250        model = load_fmu(fmu_name)
251        nose.tools.assert_equals(model.get_variable_variability('c'), 1)
252
253class TestExternalBool:
254   
255    @classmethod
256    def setUpClass(self):
257        """
258        Sets up the test class.
259        """
260        self.cpath = "ExtFunctionTests.ExtFunctionBool"
261        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
262       
263    @testattr(stddist_full = True)
264    def test_ExtFuncBool(self):
265        """
266        Test compiling a model with external functions in a shared library. Boolean arrays.
267        """
268        fmu_name = compile_fmu(self.cpath, self.fpath, compiler_options={'variability_propagation':False})
269        model = load_fmu(fmu_name)
270        model.simulate()
271        trueInd  = {1,2,3,5,8}
272        falseInd = {4,6,7}
273        for i in trueInd:
274            assert(model.get('res[' + str(i) + ']'))
275        for i in falseInd:
276            assert(not model.get('res[' + str(i) + ']'))
277
278class TestExternalRecord(SimulationTest):
279    @classmethod
280    def setUpClass(cls):
281        SimulationTest.setup_class_base('ExtFunctionTests.mo', 
282            'ExtFunctionTests.ExtFunctionRecord')
283
284    @testattr(stddist_full = True)
285    def setUp(self):
286        self.setup_base(start_time=0.0, final_time=0.1, time_step=0.01)
287        self.run()
288
289    @testattr(stddist_full = True)
290    def test_result(self):
291        self.assert_end_value('y.x', 0.1)
292
293class TestExternalRecordCeval(SimulationTest):
294    @classmethod
295    def setUpClass(cls):
296        SimulationTest.setup_class_base('ExtFunctionTests.mo', 
297            'ExtFunctionTests.ExtFunctionRecordCeval')
298
299    @testattr(stddist_full = True)
300    def setUp(self):
301        self.setup_base(start_time=0.0, final_time=0.1, time_step=0.01)
302        self.run()
303
304    @testattr(stddist_full = True)
305    def test_result(self):
306        self.assert_end_value('y1.x', 3)
307        self.assert_end_value('y2.x', 3)
308
309
310class TestExternalRecordObj(SimulationTest):
311    @classmethod
312    def setUpClass(cls):
313        SimulationTest.setup_class_base('ExtFunctionTests.mo', 
314            'ExtFunctionTests.ExtFunctionRecordObj')
315
316    @testattr(stddist_full = True)
317    def setUp(self):
318        self.setup_base(start_time=0.0, final_time=0.1, time_step=0.01)
319        self.run()
320
321    @testattr(stddist_full = True)
322    def test_result(self):
323        self.assert_end_value('y', 3)
324
325class TestExternalRecordObjCeval(SimulationTest):
326    @classmethod
327    def setUpClass(cls):
328        SimulationTest.setup_class_base('ExtFunctionTests.mo', 
329            'ExtFunctionTests.ExtFunctionRecordObjCeval')
330
331    @testattr(stddist_full = True)
332    def setUp(self):
333        self.setup_base(start_time=0.0, final_time=0.1, time_step=0.01)
334        self.run()
335
336    @testattr(stddist_full = True)
337    def test_result(self):
338        self.assert_end_value('y', 3)
339
340
341class TestExternalShared2:
342   
343    @classmethod
344    def setUpClass(self):
345        """
346        Sets up the test class.
347        """
348        self.cpath = "ExtFunctionTests.ExtFunctionTest2"
349        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
350       
351    @testattr(stddist_base = True)
352    def test_ExtFuncShared(self):
353        """
354        Test compiling a model with external functions in a shared library. Real, Integer, and Boolean arrays.
355        Compare results between constant evaluation and simulation.
356        """
357        fmu_name = compile_fmu(self.cpath, self.fpath, compiler_options={'variability_propagation':True})
358        model = load_fmu(fmu_name)
359        s_ceval = model.get('s')
360        res = model.simulate()
361        s_sim1 = res.final('s')
362       
363        fmu_name = compile_fmu(self.cpath, self.fpath, compiler_options={'variability_propagation':False})
364        model = load_fmu(fmu_name)
365        res = model.simulate()
366        s_sim2 = res.final('s')
367        nose.tools.assert_equals(s_sim1, s_sim2)
368       
369class TestExternalInf:
370   
371    @classmethod
372    def setUpClass(self):
373        """
374        Sets up the test class. Check timeout of infinite loop during constant evaluation.
375        """
376        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
377       
378    @testattr(stddist_full = True)
379    def test_InfiniteLoopExternalEvaluation(self):
380        """
381        Test compiling a model with external functions in a shared library. Infinite loop.
382        """
383        fmu_name = compile_fmu("ExtFunctionTests.ExternalInfinityTest", self.fpath)
384       
385    @testattr(stddist_full = True)
386    def test_InfiniteLoopExternalEvaluationError(self):
387        """
388        Test compiling a model with external functions in a shared library. Infinite loop.
389        """
390        try:
391            fmu_name = compile_fmu("ExtFunctionTests.ExternalInfinityTestCeval", self.fpath, compiler_options={"external_constant_evaluation":100}, compiler_log_level="e:e.txt")
392        except:
393            pass
394        file=open("e.txt")
395        i = 0
396        for line in file.readlines():
397            if "timed out" in line:
398                i = i+1
399        assert i == 1, 'Wrong error message'
400       
401class TestExternalObject:
402   
403    @classmethod
404    def setUpClass(cls):
405        """
406        Sets up the test class.
407        """
408        cls.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
409       
410    @testattr(stddist_base = True)
411    def test_ExtObjectDestructor(self):
412        """
413        Test compiling a model with external object functions in a static library.
414        """
415        cpath = 'ExtFunctionTests.ExternalObjectTests1'
416        fmu_name = compile_fmu(cpath, TestExternalObject.fpath)
417        model = load_fmu(fmu_name)
418        model.simulate()
419        model.terminate()
420        if (os.path.exists('test_ext_object.marker')):
421             os.remove('test_ext_object.marker')
422        else:
423            assert False, 'External object destructor not called.'
424           
425class TestExternalObject2:
426   
427    @classmethod
428    def setUpClass(cls):
429        """
430        Sets up the test class.
431        """
432        cls.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
433       
434    @testattr(stddist_full = True)
435    def test_ExtObjectDestructor(self):
436        """
437        Test compiling a model with external object functions in a static library.
438        """
439        cpath = 'ExtFunctionTests.ExternalObjectTests2'
440        fmu_name = compile_fmu(cpath, TestExternalObject2.fpath)
441        model = load_fmu(fmu_name)
442        model.simulate()
443        model.terminate()
444        if (os.path.exists('test_ext_object_array1.marker') and os.path.exists('test_ext_object_array2.marker')):
445             os.remove('test_ext_object_array1.marker')
446             os.remove('test_ext_object_array2.marker')
447        else:
448            assert False, 'External object destructor not called.'
449           
450class TestExternalObject3:
451   
452    @classmethod
453    def setUpClass(cls):
454        """
455        Sets up the test class.
456        """
457        cls.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
458       
459    @testattr(stddist_full = True)
460    def test_ExtObjectDestructor(self):
461        cpath = 'ExtFunctionTests.ExternalObjectTests3'
462        fmu_name = compile_fmu(cpath, TestExternalObject2.fpath)
463        model = load_fmu(fmu_name, log_level=6)
464        model.set("_log_level", 6)
465        model.simulate()
466        model.terminate() #Test that we do not segfault at this point
467        log = model.get_log()[-1]
468        assert "This should not lead to a segfault" in log
469           
470class TestExternalObjectConstructorSingleCall:
471   
472    @classmethod
473    def setUpClass(cls):
474        """
475        Sets up the test class.
476        """
477        cls.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
478       
479    @testattr(stddist_full = True)
480    def test_ExtObjectConstructor(self):
481        """
482        Test independent external object constructor is called once
483        """
484        cpath = 'ExtFunctionTests.ConstructorSingleCallTest'
485        fmu_name = compile_fmu(cpath, TestExternalObjectConstructorSingleCall.fpath)
486        model = load_fmu(fmu_name)
487        model.simulate()
488        model.terminate()
489
490    @testattr(stddist_full = True)
491    def test_ExtObjectConstructorDependent(self):
492        """
493        Test external object constructor dependent on parameter is called once
494        """
495        cpath = 'ExtFunctionTests.ConstructorSingleCallDepTest'
496        fmu_name = compile_fmu(cpath, TestExternalObjectConstructorSingleCall.fpath)
497        model = load_fmu(fmu_name)
498        model.simulate()
499        model.terminate()
500
501    @testattr(stddist_full = True)
502    def test_ExtObjectConstructorDependentSetParam(self):
503        """
504        Test external object constructor dependent on parameter is not called when setting parameters
505        """
506        cpath = 'ExtFunctionTests.ConstructorSingleCallDepTest'
507        fmu_name = compile_fmu(cpath, TestExternalObjectConstructorSingleCall.fpath)
508        model = load_fmu(fmu_name)
509        model.set('s', 'test')
510        model.set('s', 'test2')
511        model.simulate()
512        model.terminate()
513
514class TestAssertEqu3(SimulationTest):
515    '''Test structural verification assert'''
516    @classmethod
517    def setUpClass(cls):
518        SimulationTest.setup_class_base(
519            "ExtFunctionTests.mo",
520            'ExtFunctionTests.StructuralAsserts')
521           
522    @testattr(stddist_base = True)
523    def test_simulate(self):
524        try:
525            self.setup_base()
526            self.run()
527            assert False, 'Simulation not stopped by failed assertions'
528        except FMUException, e:
529            pass
530   
531class TestModelicaError:
532   
533    @classmethod
534    def setUpClass(cls):
535        """
536        Sets up the test class.
537        """
538        cls.fpath = path(path_to_mofiles, 'Asserts.mo')
539       
540    @testattr(stddist_full = True)
541    def test_simulate(self):
542        cpath = 'Asserts.ModelicaError'
543        fmu_name = compile_fmu(cpath, TestModelicaError.fpath)
544        model = load_fmu(fmu_name)
545        try:
546            model.simulate(final_time = 3, options={"CVode_options":{"minh":1e-15}})
547            assert False, 'Simulation not stopped by calls to ModelicaError()'
548        except CVodeError, e:
549            assert abs(e.t - 2.0) < 0.01, 'Simulation stopped at wrong time'
550       
551
552class TestStrings:
553    @classmethod
554    def setUpClass(self):
555        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
556       
557    @testattr(stddist_full = True)
558    def testTmpString(self):
559        '''
560        Test that strings are propagated correctly
561        '''
562        cpath = "ExtFunctionTests.TestString"
563        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={"variability_propagation":False, "inline_functions":"none"})
564        model = load_fmu(fmu_name)
565        res = model.simulate() #No asserts should be raised (in the model)
566
567       
568class TestCBasic:
569    '''
570    Test basic external C functions.
571    '''
572    @classmethod
573    def setUpClass(self):
574        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
575   
576    @testattr(stddist_full = True)
577    def testCEvalReal(self):
578        '''
579        Constant evaluation of basic external C function with Reals.
580        '''
581        cpath = "ExtFunctionTests.CEval.C.RealTest"
582        fmu_name = compile_fmu(cpath, self.fpath)
583        model = load_fmu(fmu_name)
584        res = model.simulate()
585        nose.tools.assert_equals(res.final('xScalar'), 3*3.14)
586        nose.tools.assert_equals(res.final('xArray[2]'), 4)
587        nose.tools.assert_equals(res.final('xArrayUnknown[2]'), 6)
588       
589    @testattr(stddist_full = True)
590    def testCEvalInteger(self):
591        '''
592        Constant evaluation of basic external C function with Integers.
593        '''
594        cpath = "ExtFunctionTests.CEval.C.IntegerTest"
595        fmu_name = compile_fmu(cpath, self.fpath)
596        model = load_fmu(fmu_name)
597        res = model.simulate()
598        nose.tools.assert_equals(res.final('xScalar'), 9)
599        nose.tools.assert_equals(res.final('xArray[2]'), 4)
600        nose.tools.assert_equals(res.final('xArrayUnknown[2]'), 6)
601   
602    @testattr(stddist_full = True)
603    def testCEvalBoolean(self):
604        '''
605        Constant evaluation of basic external C function with Booleans.
606        '''
607        cpath = "ExtFunctionTests.CEval.C.BooleanTest"
608        fmu_name = compile_fmu(cpath, self.fpath)
609        model = load_fmu(fmu_name)
610        res = model.simulate()
611        nose.tools.assert_equals(res.final('xScalar'), False)
612        nose.tools.assert_equals(res.final('xArray[2]'), True)
613        nose.tools.assert_equals(res.final('xArrayUnknown[2]'), False)
614
615    @testattr(stddist_full = True)
616    def test_ExtFuncString(self):
617        cpath = "ExtFunctionTests.CEval.C.StringTest"
618        fmu_name = compile_fmu(cpath, self.fpath)
619        model = load_fmu(fmu_name)
620        res = model.simulate()
621        nose.tools.assert_equals(model.get('len'), 5)
622        #TODO: enable when model.get_string implemented
623        #nose.tools.assert_equals(model.get('xScalar'), 'dcb')
624        #nose.tools.assert_equals(model.get('xScalarLit'), 'dcb')
625        #nose.tools.assert_equals(model.get('xArray[2]'), 'dbf')
626        #nose.tools.assert_equals(model.get('xArrayUnknown[2]'), 'dbf')
627   
628    @testattr(stddist_full = True)
629    def testCEvalEnum(self):
630        '''
631        Constant evaluation of basic external C function with Enums.
632        '''
633        cpath = "ExtFunctionTests.CEval.C.EnumTest"
634        fmu_name = compile_fmu(cpath, self.fpath)
635        model = load_fmu(fmu_name)
636        res = model.simulate()
637        nose.tools.assert_equals(model.get('xScalar'), 2)
638        nose.tools.assert_equals(model.get('xArray[2]'), 2)
639        nose.tools.assert_equals(model.get('xArrayUnknown[2]'), 1)
640       
641    @testattr(stddist_full = True)
642    def testCEvalShortClass(self):
643        '''
644        Constant evaluation of function modified by short class decl
645        '''
646        cpath = "ExtFunctionTests.CEval.C.ShortClass"
647        fmu_name = compile_fmu(cpath, self.fpath)
648        model = load_fmu(fmu_name)
649        resConst = model.simulate()
650        nose.tools.assert_almost_equal(resConst.final('a1'), 10*3.14)
651
652    @testattr(stddist_full = True)
653    def testCEvalPackageConstant(self):
654        cpath = "ExtFunctionTests.CEval.C.PackageConstantTest"
655        fmu_name = compile_fmu(cpath, self.fpath)
656        model = load_fmu(fmu_name)
657        res = model.simulate()
658        nose.tools.assert_equals(res.final('x[2]'), 4)
659
660class TestFortranBasic:
661    '''
662    Test basic external fortran functions.
663    '''
664    @classmethod
665    def setUpClass(self):
666        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
667   
668    @testattr(stddist_base = True)
669    def testCEvalReal(self):
670        '''
671        Constant evaluation of basic external fortran function with Reals.
672        '''
673        cpath = "ExtFunctionTests.CEval.Fortran.RealTest"
674        fmu_name = compile_fmu(cpath, self.fpath)
675        model = load_fmu(fmu_name)
676        res = model.simulate()
677        nose.tools.assert_equals(res.final('xScalar'), 3*3.14)
678        nose.tools.assert_equals(res.final('xArray[2]'), 4)
679        nose.tools.assert_equals(res.final('xArrayUnknown[2]'), 6)
680       
681    @testattr(stddist_base = True)
682    def testCEvalMatrixReal(self):
683        '''
684        Constant evaluation of basic external fortran function with Reals.
685        '''
686        cpath = "ExtFunctionTests.CEval.Fortran.RealTestMatrix"
687        fmu_name = compile_fmu(cpath, self.fpath)
688        model = load_fmu(fmu_name)
689        res = model.simulate()
690        nose.tools.assert_equals(res.final('y1[1,1]'), 1)
691        nose.tools.assert_equals(res.final('y2[1,1]'), 9)
692       
693    @testattr(stddist_base = True)
694    def testCEvalInteger(self):
695        '''
696        Constant evaluation of basic external fortran function with Integers.
697        '''
698        cpath = "ExtFunctionTests.CEval.Fortran.IntegerTest"
699        fmu_name = compile_fmu(cpath, self.fpath)
700        model = load_fmu(fmu_name)
701        res = model.simulate()
702        nose.tools.assert_equals(res.final('xScalar'), 9)
703        nose.tools.assert_equals(res.final('xArray[2]'), 4)
704        nose.tools.assert_equals(res.final('xArrayUnknown[2]'), 6)
705   
706    @testattr(stddist_full = True)
707    def testCEvalBoolean(self):
708        '''
709        Constant evaluation of basic external fortran function with Booleans.
710        '''
711        cpath = "ExtFunctionTests.CEval.Fortran.BooleanTest"
712        fmu_name = compile_fmu(cpath, self.fpath)
713        model = load_fmu(fmu_name)
714        res = model.simulate()
715        nose.tools.assert_equals(res.final('xScalar'), False)
716        nose.tools.assert_equals(res.final('xArray[2]'), True)
717        nose.tools.assert_equals(res.final('xArrayUnknown[2]'), False)
718   
719    @testattr(stddist_full = True)
720    def testCEvalEnum(self):
721        '''
722        Constant evaluation of basic external fortran function with Enums.
723        '''
724        cpath = "ExtFunctionTests.CEval.Fortran.EnumTest"
725        fmu_name = compile_fmu(cpath, self.fpath)
726        model = load_fmu(fmu_name)
727        res = model.simulate()
728        nose.tools.assert_equals(model.get('xScalar'), 2)
729        nose.tools.assert_equals(model.get('xArray[2]'), 2)
730        nose.tools.assert_equals(model.get('xArrayUnknown[2]'), 1)
731       
732class TestAdvanced:
733    '''
734    Test advanced external fortran functions.
735    '''
736    @classmethod
737    def setUpClass(self):
738        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
739   
740    @testattr(stddist_base = True)
741    def testDGELSX(self):
742        '''
743        A test using the external fortran function dgelsx from lapack.
744        Compares simulation results with constant evaluation results.
745        '''
746        cpath = "ExtFunctionTests.CEval.Advanced.DgelsxTest"
747        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={'variability_propagation':False})
748        model = load_fmu(fmu_name)
749        resSim = model.simulate()
750        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={'variability_propagation':True})
751        model = load_fmu(fmu_name)
752        resConst = model.simulate()
753        for i in range(1,4):
754          for j in range(1,4):
755            x = 'out[{0},{1}]'.format(i,j)
756            nose.tools.assert_almost_equals(resSim.final(x), resConst.final(x), places=13)
757        nose.tools.assert_equals(resSim.final('a'), resConst.final('a'))
758        nose.tools.assert_equals(resSim.final('b'), resConst.final('b'))
759       
760    @testattr(stddist_base = True)
761    def testExtObjScalar(self):
762        '''
763        Test constant evaluation of a simple external object.
764        '''
765        cpath = "ExtFunctionTests.CEval.Advanced.ExtObjTest1"
766        fmu_name = compile_fmu(cpath, self.fpath)
767        model = load_fmu(fmu_name)
768        resConst = model.simulate()
769        nose.tools.assert_equals(resConst.final('x'), 6.13)
770       
771    @testattr(stddist_base = True)
772    def testExtObjArrays(self):
773        '''
774        Test constant evaluation of arrays of external objects.
775        '''
776        cpath = "ExtFunctionTests.CEval.Advanced.ExtObjTest2"
777        fmu_name = compile_fmu(cpath, self.fpath)
778        model = load_fmu(fmu_name)
779        resConst = model.simulate()
780        nose.tools.assert_equals(resConst.final('x'), 13.27)
781       
782    @testattr(stddist_full = True)
783    def testExtObjRecursive(self):
784        '''
785        Test constant evaluation of external object encapsulating
786        external objects.
787        '''
788        cpath = "ExtFunctionTests.CEval.Advanced.ExtObjTest3"
789        fmu_name = compile_fmu(cpath, self.fpath)
790        model = load_fmu(fmu_name)
791        resConst = model.simulate()
792        nose.tools.assert_equals(resConst.final('x'), 32.67)
793   
794    @testattr(stddist_full = True)
795    def testPartialEvalFail(self):
796        '''
797        Test failing of partial constant evaluation on external function
798        '''
799        cpath = "ExtFunctionTests.CEval.Advanced.UnknownInput"
800        fmu_name = compile_fmu(cpath, self.fpath, version=1.0) 
801        model = load_fmu(fmu_name)
802        assert model.get_variable_variability("y") == 3, 'y should be continuous'
803       
804        fmu_name = compile_fmu(cpath, self.fpath, version=2.0) #Continuous variability is == 4 with FMI2
805        model = load_fmu(fmu_name)
806        assert model.get_variable_variability("y") == 4, 'y should be continuous'
807       
808       
809   
810class TestUtilitiesCEval:
811    '''
812    Test utility functions in external C functions.
813    '''
814    @classmethod
815    def setUpClass(self):
816        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
817   
818    @testattr(stddist_base = True)
819    def testCEvalLog(self):
820        '''
821        Constant evaluation of external C logging function.
822        '''
823        cpath = "ExtFunctionTests.CEval.Utility.LogTest"
824        fmu_name = compile_fmu(cpath, self.fpath, compiler_log_level="w:tmp.log")
825        logfile = open('tmp.log')
826        count = 0
827        for line in logfile:
828            if line == "ModelicaMessage: <msg:X is a bit high: 1.100000.>\n" or line == "ModelicaError: <msg:X is too high: 2.100000.>\n":
829                count = count + 1
830        logfile.close()
831        os.remove(logfile.name);
832        assert(count >= 2)
833
834class TestCevalCaching:
835    '''
836    Test caching of external objects during constant evaluation
837    '''
838    @classmethod
839    def setUpClass(self):
840        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
841   
842    @testattr(stddist_full = True)
843    def testCaching1(self):
844        '''
845        Test caching of external objects during constant evaluation
846        '''
847        cpath = "ExtFunctionTests.CEval.Caching.CacheExtObj"
848        fmu_name = compile_fmu(cpath, self.fpath)
849        model = load_fmu(fmu_name)
850        res = model.simulate()
851        nose.tools.assert_equals(res.final('n3'), 5)
852       
853    @testattr(stddist_full = True)
854    def testCaching2(self):
855        '''
856        Test caching process limit of external objects during constant evaluation
857        '''
858        cpath = "ExtFunctionTests.CEval.Caching.CacheExtObjLimit"
859        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={'external_constant_evaluation_max_proc':2})
860        model = load_fmu(fmu_name)
861        res = model.simulate()
862        nose.tools.assert_equals(res.final('n3'), 20)
863       
864    @testattr(stddist_full = True)
865    def testCaching3(self):
866        '''
867        Test disabling process caching
868        '''
869        cpath = "ExtFunctionTests.CEval.Caching.CacheExtObj"
870        fmu_name = compile_fmu(cpath, self.fpath, compiler_options={'external_constant_evaluation_max_proc':0})
871        model = load_fmu(fmu_name)
872        res = model.simulate()
873        nose.tools.assert_equals(res.final('n3'), 4)
874       
875    @testattr(stddist_full = True)
876    def testConError(self):
877        '''
878        Test caching of external objects during constant evaluation, ModelicaError in constructor.
879        '''
880        cpath = "ExtFunctionTests.CEval.Caching.ConError"
881        fmu_name = compile_fmu(cpath, self.fpath)
882       
883    @testattr(stddist_full = True)
884    def testDeconError(self):
885        '''
886        Test caching of external objects during constant evaluation, ModelicaError in deconstructor.
887        '''
888        cpath = "ExtFunctionTests.CEval.Caching.DeconError"
889        fmu_name = compile_fmu(cpath, self.fpath)
890       
891    @testattr(stddist_full = True)
892    def testUseError(self):
893        '''
894        Test caching of external objects during constant evaluation, ModelicaError in use.
895        '''
896        cpath = "ExtFunctionTests.CEval.Caching.UseError"
897        fmu_name = compile_fmu(cpath, self.fpath)
898       
899       
900    @testattr(stddist_full = True)
901    def testConCrash(self):
902        '''
903        Test caching of external objects during constant evaluation, Crash in constructor.
904        '''
905        cpath = "ExtFunctionTests.CEval.Caching.ConCrash"
906        fmu_name = compile_fmu(cpath, self.fpath)
907       
908    @testattr(stddist_full = True)
909    def testDeconCrash(self):
910        '''
911        Test caching of external objects during constant evaluation, Crash in deconstructor.
912        '''
913        cpath = "ExtFunctionTests.CEval.Caching.DeconCrash"
914        fmu_name = compile_fmu(cpath, self.fpath)
915       
916    @testattr(stddist_full = True)
917    def testUseCrash(self):
918        '''
919        Test caching of external objects during constant evaluation, Crash in use.
920        '''
921        cpath = "ExtFunctionTests.CEval.Caching.UseCrash"
922        fmu_name = compile_fmu(cpath, self.fpath)
923       
924class TestMultiUse:
925    @classmethod
926    def setUpClass(self):
927        self.fpath = path(path_to_mofiles, "ExtFunctionTests.mo")
928   
929    @testattr(stddist_full = True)
930    def testMultiUse1(self):
931        cpath = "ExtFunctionTests.MultiUse1"
932        fmu_name = compile_fmu(cpath, self.fpath)
933        model = load_fmu(fmu_name)
934        res = model.simulate()
935        nose.tools.assert_equals(res.final('y'), 5.0)
Note: See TracBrowser for help on using the repository browser.