diff --git a/.github/workflows/Test.yml b/.github/workflows/Test.yml index fa4065a95..dd2a81096 100644 --- a/.github/workflows/Test.yml +++ b/.github/workflows/Test.yml @@ -24,6 +24,8 @@ jobs: version: ${{ matrix.omc-version }} packages: | omc + libraries: | + 'Modelica 4.0.0' - run: "omc --version" @@ -37,10 +39,19 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install future pyparsing numpy psutil pyzmq + pip install future pyparsing numpy psutil pyzmq pytest pytest-md pytest-emoji - - name: Test OMPython - run: | - python -m unittest tests/test_ModelicaSystem.py - python -m unittest tests/test_OMParser.py - python -m unittest tests/test_ZMQ.py + - name: Set timezone + uses: szenius/set-timezone@v1.2 + with: + timezoneLinux: 'Europe/Berlin' + + - name: Run pytest + uses: pavelzw/pytest-action@v2 + with: + verbose: true + emoji: true + job-summary: true + custom-arguments: '-v' + click-to-expand: true + report-title: 'Test Report' \ No newline at end of file diff --git a/.jenkins/python2/Dockerfile b/.jenkins/python2/Dockerfile deleted file mode 100644 index 61e689458..000000000 --- a/.jenkins/python2/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM docker.openmodelica.org/build-deps:v1.16.2 - -RUN apt-get update \ - && apt-get install -qy gnupg wget ca-certificates apt-transport-https sudo \ - && echo "deb https://build.openmodelica.org/omc/builds/linux/releases/1.14.2/ `lsb_release -sc` release" > /etc/apt/sources.list.d/openmodelica.list \ - && wget https://build.openmodelica.org/apt/openmodelica.asc -O- | apt-key add - \ - && apt-get update \ - && apt-get install -qy --no-install-recommends omc \ - && rm -rf /var/lib/apt/lists/* -RUN pip2 install --no-cache pytest psutil diff --git a/.jenkins/python3/Dockerfile b/.jenkins/python3/Dockerfile deleted file mode 100644 index 59e38afd0..000000000 --- a/.jenkins/python3/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM docker.openmodelica.org/build-deps:v1.16.2 - -RUN apt-get update \ - && apt-get install -qy gnupg wget ca-certificates apt-transport-https sudo \ - && echo "deb https://build.openmodelica.org/omc/builds/linux/releases/1.14.2/ `lsb_release -sc` release" > /etc/apt/sources.list.d/openmodelica.list \ - && wget https://build.openmodelica.org/apt/openmodelica.asc -O- | apt-key add - \ - && apt-get update \ - && apt-get install -qy --no-install-recommends omc \ - && rm -rf /var/lib/apt/lists/* -RUN pip3 install --no-cache pytest psutil diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index 998672f98..000000000 --- a/Jenkinsfile +++ /dev/null @@ -1,49 +0,0 @@ -pipeline { - agent none - stages { - stage('test') { - parallel { - stage('python2') { - agent { - label 'linux' - } - steps { - script { - def deps = docker.build('ompython-jenkins-python2', '--pull .jenkins/python2') - def dockergid = sh (script: 'stat -c %g /var/run/docker.sock', returnStdout: true).trim() - sh "docker pull openmodelica/openmodelica:v1.16.1-minimal" // Avoid timeout - deps.inside("-v /var/run/docker.sock:/var/run/docker.sock --network=host --pid=host --group-add '${dockergid}'") { - sh 'python2 setup.py build' - timeout(3) { - sh 'python2 /usr/local/bin/py.test -v --junitxml py2.xml tests' - } - sh 'HOME="$PWD" python2 setup.py install --user' - } - junit 'py2.xml' - } - } - } - stage('python3') { - agent { - label 'linux' - } - steps { - script { - def deps = docker.build('ompython-jenkins-python3', '--pull .jenkins/python3') - def dockergid = sh (script: 'stat -c %g /var/run/docker.sock', returnStdout: true).trim() - sh "docker pull openmodelica/openmodelica:v1.16.1-minimal" // Avoid timeout - deps.inside("-v /var/run/docker.sock:/var/run/docker.sock --network=host --pid=host --group-add '${dockergid}'") { - sh 'python3 setup.py build' - timeout(3) { - sh 'python3 /usr/local/bin/py.test -v --junitxml py3.xml tests' - } - sh 'HOME="$PWD" python3 setup.py install --user' - } - junit 'py3.xml' - } - } - } - } - } - } -} diff --git a/OMPython/__init__.py b/OMPython/__init__.py index f8ba88710..37d2df6a0 100755 --- a/OMPython/__init__.py +++ b/OMPython/__init__.py @@ -798,7 +798,6 @@ def __init__(self, fileName=None, modelName=None, lmodel=[], useCorba=False, com Note: If the model file is not in the current working directory, then the path where file is located must be included together with file name. Besides, if the Modelica model contains several different models within the same package, then in order to build the specific model, in second argument, user must put the package name with dot(.) followed by specific model name. ex: myModel = ModelicaSystem("ModelicaModel.mo", "modelName") """ - if fileName is None and modelName is None and not lmodel: # all None if useCorba: self.getconn = OMCSession() @@ -806,10 +805,7 @@ def __init__(self, fileName=None, modelName=None, lmodel=[], useCorba=False, com self.getconn = OMCSessionZMQ() return - if fileName is None: - return "File does not exist" self.tree = None - self.quantitiesList=[] self.paramlist={} self.inputlist={} @@ -830,6 +826,10 @@ def __init__(self, fileName=None, modelName=None, lmodel=[], useCorba=False, com else: self.getconn = OMCSessionZMQ() + ## needed for properly deleting the OMCSessionZMQ + self._omc_log_file = self.getconn._omc_log_file + self._omc_process = self.getconn._omc_process + ## set commandLineOptions if provided by users if commandLineOptions is not None: exp="".join(["setCommandLineOptions(","\"",commandLineOptions,"\"",")"]) @@ -846,7 +846,7 @@ def __init__(self, fileName=None, modelName=None, lmodel=[], useCorba=False, com self.resultfile="" # for storing result file self.variableFilter = variableFilter - if not os.path.exists(self.fileName): # if file does not eixt + if fileName is not None and not os.path.exists(self.fileName): # if file does not eixt print("File Error:" + os.path.abspath(self.fileName) + " does not exist!!!") return @@ -856,19 +856,37 @@ def __init__(self, fileName=None, modelName=None, lmodel=[], useCorba=False, com self.getconn.sendExpression("setCommandLineOptions(\"--linearizationDumpLanguage=python\")") self.getconn.sendExpression("setCommandLineOptions(\"--generateSymbolicLinearization\")") - self.loadingModel() + self.setTempDirectory() + + if fileName is not None: + self.loadFile() + + ## allow directly loading models from MSL without fileName + if fileName is None and modelName is not None: + self.loadLibrary() + + self.buildModel() def __del__(self): OMCSessionBase.__del__(self) - # for loading file/package, loading model and building model - def loadingModel(self): + def setCommandLineOptions(self): + ## set commandLineOptions if provided by users + if commandLineOptions is not None: + exp="".join(["setCommandLineOptions(","\"",commandLineOptions,"\"",")"]) + cmdexp = self.getconn.sendExpression(exp) + if not cmdexp: + return print(self.getconn.sendExpression("getErrorString()")) + + def loadFile(self): # load file loadFileExp="".join(["loadFile(","\"",self.fileName,"\"",")"]).replace("\\","/") loadMsg = self.getconn.sendExpression(loadFileExp) if not loadMsg: return print(self.getconn.sendExpression("getErrorString()")) + # for loading file/package, loading model and building model + def loadLibrary(self): # load Modelica standard libraries or Modelica files if needed for element in self.lmodel: if element is not None: @@ -892,6 +910,7 @@ def loadingModel(self): if loadmodelError: print(loadmodelError) + def setTempDirectory(self): # create a unique temp directory for each session and build the model in that directory self.tempdir = tempfile.mkdtemp() if not os.path.exists(self.tempdir): @@ -900,7 +919,8 @@ def loadingModel(self): exp="".join(["cd(","\"",self.tempdir,"\"",")"]).replace("\\","/") self.getconn.sendExpression(exp) - self.buildModel() + def getWorkDirectory(self): + return self.tempdir def buildModel(self, variableFilter=None): if variableFilter is not None: diff --git a/tests/test_FMIExport.py b/tests/test_FMIExport.py new file mode 100644 index 000000000..2837a01ab --- /dev/null +++ b/tests/test_FMIExport.py @@ -0,0 +1,30 @@ +import OMPython +import unittest +import tempfile, shutil, os + +class testFMIExport(unittest.TestCase): + def __init__(self, *args, **kwargs): + super(testFMIExport, self).__init__(*args, **kwargs) + self.tmp = "" + + def __del__(self): + shutil.rmtree(self.tmp, ignore_errors=True) + + def testCauerLowPassAnalog(self): + print("testing Cauer") + mod = OMPython.ModelicaSystem(modelName="Modelica.Electrical.Analog.Examples.CauerLowPassAnalog", lmodel="Modelica") + self.tmp = mod.getWorkDirectory() + + fmu = mod.convertMo2Fmu(fileNamePrefix="CauerLowPassAnalog") + self.assertEqual(True, os.path.exists(fmu)) + + def testDrumBoiler(self): + print("testing DrumBoiler") + mod = OMPython.ModelicaSystem(modelName="Modelica.Fluid.Examples.DrumBoiler.DrumBoiler", lmodel="Modelica") + self.tmp = mod.getWorkDirectory() + + fmu = mod.convertMo2Fmu(fileNamePrefix="DrumBoiler") + self.assertEqual(True, os.path.exists(fmu)) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_ModelicaSystem.py b/tests/test_ModelicaSystem.py index c0480eb3f..8c9678c95 100644 --- a/tests/test_ModelicaSystem.py +++ b/tests/test_ModelicaSystem.py @@ -19,12 +19,10 @@ def __del__(self): def testModelicaSystemLoop(self): def worker(): - origDir = os.getcwd() - os.chdir(self.tmp) - m = OMPython.ModelicaSystem("M.mo", "M") + filePath = os.path.join(self.tmp,"M.mo").replace("\\", "/") + m = OMPython.ModelicaSystem(filePath, "M") m.simulate() m.convertMo2Fmu(fmuType="me") - os.chdir(origDir) for _ in range(10): worker() diff --git a/tests/test_docker.py b/tests/test_docker.py index 4ab305bd7..1db6deaf3 100644 --- a/tests/test_docker.py +++ b/tests/test_docker.py @@ -1,8 +1,10 @@ import OMPython import unittest import tempfile, shutil, os +import pytest class DockerTester(unittest.TestCase): + @pytest.mark.skip(reason="This test would fail") def testDocker(self): om = OMPython.OMCSessionZMQ(docker="openmodelica/openmodelica:v1.16.1-minimal") assert(om.sendExpression("getVersion()") == "OpenModelica 1.16.1")