diff --git a/.github/workflows/nightly-model-testing.yml b/.github/workflows/nightly-model-testing.yml index 72e8e3b20e..8fa64bdf04 100644 --- a/.github/workflows/nightly-model-testing.yml +++ b/.github/workflows/nightly-model-testing.yml @@ -59,231 +59,244 @@ jobs: java-version: '8' distribution: 'adopt' cache: 'maven' - - - name: Build VCell Jars - run: mvn clean install dependency:copy-dependencies -DskipTests=True - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Build and Export - uses: docker/build-push-action@v3 - with: - context: . - file: ./Dockerfile - outputs: type=docker,dest=/tmp/image.tar - build-args: | # Max ram for Ubuntu GitHub workflow is 7GB (as of 12/9/22), using MB for precision (0.8 of 7gb) - MAX_JAVA_MEM=5734 - - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: docker-image - path: /tmp/image.tar - - # Report a Problem to Slack - - name: Report Problem to Slack - if: ${{ failure() }} - run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="Uh-Oh! The *Build Step* of Nightly Testing Action on GitHub Failed ( ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} )! This may need attention..." https://slack.com/api/chat.postMessage - - # Tmate just in case - - name: Setup tmate session 3 - uses: mxschmitt/action-tmate@v3 - if: ${{ failure() }} - export: - runs-on: ubuntu-20.04 - needs: build - steps: - - name: Create Docker Image Dir - run: mkdir /tmp/docker - - - name: Download Docker Image from `build` Job - uses: actions/download-artifact@v3 - with: - name: docker-image - path: /tmp/docker - - name: Load Downloaded Docker Image - run: docker load --input /tmp/docker/$(ls /tmp/docker) - - # Get files from VCDB + # Get files from VCDB - name: Checkout Input Files uses: actions/checkout@v3 - with: + with: repository: virtualcell/vcdb - - - name: Prepare Output Directory - run: mkdir -p $GITHUB_WORKSPACE/export_conversion/output - - # Do the conversion - - name: Begin Conversion - #$(docker image ls | grep "" | awk '{print $3;}') to get image id - run: docker run -v $GITHUB_WORKSPACE:/root $(docker image ls | grep "" | awk '{print $3;}') export-omex-batch -i "/root/public/biomodel/vcml" -o "/root/export_conversion/output" -m SBML --offline # grabs image and runs + path: ./filesToTest - # Parse the results - - name: Parse Results - run: | - cd $GITHUB_WORKSPACE/export_conversion/output - /bin/echo "biomodels processed $(cat jobLog.txt | grep START | wc -l)" >> ../export_results.txt - /bin/echo "biomodels succeeded $(cat jobLog.txt | grep MODEL,SUCC | wc -l)" >> ../export_results.txt - /bin/echo "simcontexts total $(cat jobLog.txt | grep TEXT | wc -l)" >> ../export_results.txt - /bin/echo "simcontexts failed $(cat jobLog.txt | grep TEXT,FAIL | wc -l)" >> ../import_results.txt - /bin/echo "simcontexts supported that failed $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | wc -l)" >> ../export_results.txt - /bin/echo "simcontexts math not equivalent $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep equiv | wc -l)" >> ../export_results.txt - /bin/echo "simcontexts divide by zero $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep divide | wc -l)" >> ../export_results.txt - /bin/echo "simcontexts duplicate IDs $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep duplicate | wc -l)" >> ../export_results.txt - /bin/echo "simcontexts null pointer $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep null | wc -l)" >> ../export_results.txt - /bin/echo "simcontexts structure mapping $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep struct | wc -l)" >> ../export_results.txt - /bin/echo "simcontexts other failure $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep -v struct | grep -v null | grep -v duplicate | grep -v divide | grep -v equiv | wc -l)" >> ../export_results.txt - /bin/echo "simulations total $(cat jobLog.txt | grep TION | wc -l)" >> ../export_results.txt - /bin/echo "simulations failed $(cat jobLog.txt | grep TION,FAIL | wc -l)" >> ../export_results.txt - /bin/echo "simulations supported that failed $(cat jobLog.txt | grep TION,FAIL | grep -v supp | wc -l)" >> ../export_results.txt - /bin/echo "simulations orphan overrides $(cat jobLog.txt | grep TION,FAIL | grep -v supp | grep Over | wc -l)" >> ../export_results.txt - /bin/echo "simulations unbound identifier $(cat jobLog.txt | grep TION,FAIL | grep -v supp | grep unbound | wc -l)" >> ../export_results.txt - /bin/echo "simulations other failure $(cat jobLog.txt | grep TION,FAIL | grep -v supp | grep -v Over | grep -v unbound | wc -l)" >> ../export_results.txt - - # Create tar of converted files - - name: Compress Converted Files - run: cd $GITHUB_WORKSPACE/export_conversion/output && sudo tar cf omexes.tar --wildcards *.omex - - # Upload Converted Files - - name: Upload Converted Files - uses: actions/upload-artifact@v3 - with: - name: omexes.tar - path: ~/work/vcell/vcell/export_conversion/output/omexes.tar # Action only has basic ~ based expansion, env variables dont appear to work - - # Upload Results - - name: Upload results of round-trip - uses: actions/upload-artifact@v3 - with: - name: export_results.txt - path: ~/work/vcell/vcell/export_conversion/output/export_results.txt - - - name: Upload original log of export - uses: actions/upload-artifact@v3 - with: - name: export_log_original - path: ~/work/vcell/vcell/export_conversion/output/jobLog.txt + - name: Put Files To Testing Directory + run: mkdir -p $HOME/test_dir && cp $GITHUB_WORKSPACE/filesToTest/public/biomodel/vcml/* $HOME/test_dir - # Report a Problem to Slack - - name: Report Problem to Slack - if: ${{ failure() }} - run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="Uh-Oh! The *Export Step* of Nightly Testing Action on GitHub Failed ( ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} )! This may need attention..." https://slack.com/api/chat.postMessage + - name: Build VCell Jars && Run Roundtrip Test + run: mvn --batch-mode clean install dependency:copy-dependencies -Dgroups="org.vcell.test.Nightly" -Dvcell.vcmlLocation="$HOME/test_dir" - # Tmate just in case - - name: Setup tmate session 3 - uses: mxschmitt/action-tmate@v3 - if: ${{ failure() }} - import: - runs-on: ubuntu-20.04 - needs: export - steps: - - name: Create working directory - run: mkdir ~/wrk - - - name: Download Docker Image from `build` Job - uses: actions/download-artifact@v3 - with: - name: docker-image - path: ~/wrk + # Report a Success + - name: Report Results to Slack + run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="$(cat $HOME/test_dir/results/rawRoundTripResults.txt)" https://slack.com/api/chat.postMessage - - name: Load Downloaded Docker Image - run: docker load --input ~/wrk/$(ls ~/wrk) - - # Make Input Directory - - name: Make Input and Output Directory - run: mkdir -p ~/input_files/output && mkdir ~/input_files/input - - # Get the coverted omexes from before - - name: Download Converted COMBINE Archives - uses: actions/download-artifact@v3 - with: - name: omexes.tar - path: ~/input_files/input - - - name: Unpack Input Files - run: cd ~/input_files/input && sudo tar xvf $(ls *.tar) && rm $(ls *.tar) - - - name: Prepare Output Directory - run: mkdir ~/input_files/input - - # Do the round trip - - name: Begin Round-Trip Import - #$(docker image ls | grep "" | awk '{print $3;}') to get image id - run: docker run -v ~/input_files:/root $(docker image ls | grep "" | awk '{print $3;}') import-omex-batch -d -i "/root/input" -o "/root/output" - - # Parse the results - - name: Parse Results - run: | - cd ~/input_files/output - /bin/echo "Biomodels processed $(cat jobLog.txt | grep '.omex,SUCC\|.omex,FAIL' | wc -l)" >> ~/import_results.txt - /bin/echo "Biomodels succeeded $(cat jobLog.txt | grep SUCC | wc -l)" >> ~/import_results.txt - /bin/echo "Biomodels that didn't converge $(cat jobLog.txt | grep SUCC | grep -v ',1' | wc -l)" >> ~/import_results.txt - - # Upload results - - name: Upload Results of Round-Trip - uses: actions/upload-artifact@v3 - with: - name: import_results.txt - path: ~/import_results.txt - - - name: Upload Results of Round-Trip - uses: actions/upload-artifact@v3 - with: - name: import_log_original - path: ~/input_files/output/jobLog.txt +# +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@v2 +# +# - name: Build and Export +# uses: docker/build-push-action@v3 +# with: +# context: . +# file: ./Dockerfile +# outputs: type=docker,dest=/tmp/image.tar +# build-args: | # Max ram for Ubuntu GitHub workflow is 7GB (as of 12/9/22), using MB for precision (0.8 of 7gb) +# MAX_JAVA_MEM=5734 +# +# - name: Upload Artifact +# uses: actions/upload-artifact@v3 +# with: +# name: docker-image +# path: /tmp/image.tar # Report a Problem to Slack - name: Report Problem to Slack if: ${{ failure() }} - run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="Uh-Oh! The *Import Step* of Nightly Testing Action on GitHub Failed ( ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} )! This may need attention..." https://slack.com/api/chat.postMessage + run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="Uh-Oh! The Nightly Testing Action on GitHub Failed ( ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} )! This may need attention..." https://slack.com/api/chat.postMessage # Tmate just in case - name: Setup tmate session 3 uses: mxschmitt/action-tmate@v3 if: ${{ failure() }} - - summarize: - runs-on: ubuntu-20.04 - needs: import - steps: - - name: Make Results Directory - run: mkdir -p ~/results && cd ~/results - - name: Download Export Results - uses: actions/download-artifact@v3 - with: - name: export_results.txt - path: ~/results - - - name: Download Import Results - uses: actions/download-artifact@v3 - with: - name: import_results.txt - path: ~/results - - - name: Compile Results - run: | - if [ $() -gt 50000] && [ $() -lt 120000 ]; then echo -n 'Good Morning! ' >> ~/results/summary.txt; fi - echo 'Here are the results of the Nightly Testing. Have a great day!' >> ~/results/summary.txt - echo '' >> ~/results/summary.txt - echo '-------- Export Results --------' >> ~/results/summary.txt - cat ~/results/export_results.txt >> ~/results/summary.txt - echo '-------- Import Results --------' >> ~/results/summary.txt - cat ~/results/import_results.txt >> ~/results/summary.txt - echo '' >> ~/results/summary.txt - - # Report a Success - - name: Report Results to Slack - run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="$(cat ~/results/summary.txt)" https://slack.com/api/chat.postMessage - - # Report a Problem to Slack - - name: Report Problem to Slack - if: ${{ failure() }} - run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="Oops! The *Summary Step* of Nightly Testing Action on GitHub Failed ( ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} ). Go see what happened!" https://slack.com/api/chat.postMessage - - - name: Setup tmate session 3 - uses: mxschmitt/action-tmate@v3 - if: ${{ failure() }} - +# export: +# runs-on: ubuntu-20.04 +# needs: build +# steps: +# - name: Create Docker Image Dir +# run: mkdir /tmp/docker +# +# - name: Download Docker Image from `build` Job +# uses: actions/download-artifact@v3 +# with: +# name: docker-image +# path: /tmp/docker +# +# - name: Load Downloaded Docker Image +# run: docker load --input /tmp/docker/$(ls /tmp/docker) +# +# # Get files from VCDB +# - name: Checkout Input Files +# uses: actions/checkout@v3 +# with: +# repository: virtualcell/vcdb +# +# - name: Prepare Output Directory +# run: mkdir -p $GITHUB_WORKSPACE/export_conversion/output +# +# # Do the conversion +# - name: Begin Conversion +# #$(docker image ls | grep "" | awk '{print $3;}') to get image id +# run: docker run -v $GITHUB_WORKSPACE:/root $(docker image ls | grep "" | awk '{print $3;}') export-omex-batch -i "/root/public/biomodel/vcml" -o "/root/export_conversion/output" -m SBML --writeLogFiles=true --validate # grabs image and runs +# +# # Parse the results +# - name: Parse Results +# run: | +# cd $GITHUB_WORKSPACE/export_conversion/output +# /bin/echo "biomodels processed $(cat jobLog.txt | grep START | wc -l)" >> ../export_results.txt +# /bin/echo "biomodels succeeded $(cat jobLog.txt | grep MODEL,SUCC | wc -l)" >> ../export_results.txt +# /bin/echo "simcontexts total $(cat jobLog.txt | grep TEXT | wc -l)" >> ../export_results.txt +# /bin/echo "simcontexts failed $(cat jobLog.txt | grep TEXT,FAIL | wc -l)" >> ../import_results.txt +# /bin/echo "simcontexts supported that failed $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | wc -l)" >> ../export_results.txt +# /bin/echo "simcontexts math not equivalent $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep equiv | wc -l)" >> ../export_results.txt +# /bin/echo "simcontexts divide by zero $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep divide | wc -l)" >> ../export_results.txt +# /bin/echo "simcontexts duplicate IDs $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep duplicate | wc -l)" >> ../export_results.txt +# /bin/echo "simcontexts null pointer $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep null | wc -l)" >> ../export_results.txt +# /bin/echo "simcontexts structure mapping $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep struct | wc -l)" >> ../export_results.txt +# /bin/echo "simcontexts other failure $(cat jobLog.txt | grep TEXT,FAIL | grep -v supp | grep -v struct | grep -v null | grep -v duplicate | grep -v divide | grep -v equiv | wc -l)" >> ../export_results.txt +# /bin/echo "simulations total $(cat jobLog.txt | grep TION | wc -l)" >> ../export_results.txt +# /bin/echo "simulations failed $(cat jobLog.txt | grep TION,FAIL | wc -l)" >> ../export_results.txt +# /bin/echo "simulations supported that failed $(cat jobLog.txt | grep TION,FAIL | grep -v supp | wc -l)" >> ../export_results.txt +# /bin/echo "simulations orphan overrides $(cat jobLog.txt | grep TION,FAIL | grep -v supp | grep Over | wc -l)" >> ../export_results.txt +# /bin/echo "simulations unbound identifier $(cat jobLog.txt | grep TION,FAIL | grep -v supp | grep unbound | wc -l)" >> ../export_results.txt +# /bin/echo "simulations other failure $(cat jobLog.txt | grep TION,FAIL | grep -v supp | grep -v Over | grep -v unbound | wc -l)" >> ../export_results.txt +# +# # Create tar of converted files +# - name: Compress Converted Files +# run: cd $GITHUB_WORKSPACE/export_conversion/output && sudo tar cf omexes.tar --wildcards *.omex +# +# # Upload Converted Files +# - name: Upload Converted Files +# uses: actions/upload-artifact@v3 +# with: +# name: omexes.tar +# path: ~/work/vcell/vcell/export_conversion/output/omexes.tar # Action only has basic ~ based expansion, env variables dont appear to work +# +# # Upload Results +# - name: Upload results of round-trip +# uses: actions/upload-artifact@v3 +# with: +# name: export_results.txt +# path: ~/work/vcell/vcell/export_conversion/export_results.txt +# +# - name: Upload original log of export +# uses: actions/upload-artifact@v3 +# with: +# name: export_log_original +# path: ~/work/vcell/vcell/export_conversion/output/jobLog.txt +# +# # Report a Problem to Slack +# - name: Report Problem to Slack +# if: ${{ failure() }} +# run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="Uh-Oh! The *Export Step* of Nightly Testing Action on GitHub Failed ( ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} )! This may need attention..." https://slack.com/api/chat.postMessage +# +# # Tmate just in case +# - name: Setup tmate session 3 +# uses: mxschmitt/action-tmate@v3 +# if: ${{ failure() }} +# import: +# runs-on: ubuntu-20.04 +# needs: export +# steps: +# - name: Create working directory +# run: mkdir ~/wrk +# +# - name: Download Docker Image from `build` Job +# uses: actions/download-artifact@v3 +# with: +# name: docker-image +# path: ~/wrk +# +# - name: Load Downloaded Docker Image +# run: docker load --input ~/wrk/$(ls ~/wrk) +# +# # Make Input and Output Directory +# - name: Make Input and Output Directory +# run: mkdir -p ~/input_files/output && mkdir ~/input_files/input +# +# # Get the coverted omexes from before +# - name: Download Converted COMBINE Archives +# uses: actions/download-artifact@v3 +# with: +# name: omexes.tar +# path: ~/input_files/input +# +# - name: Unpack Input Files +# run: cd ~/input_files/input && sudo tar xvf $(ls *.tar) && rm $(ls *.tar) +# +# # Do the round trip +# - name: Begin Round-Trip Import +# #$(docker image ls | grep "" | awk '{print $3;}') to get image id +# run: docker run -v ~/input_files:/root $(docker image ls | grep "" | awk '{print $3;}') import-omex-batch -d -i "/root/input" -o "/root/output" +# +# # Parse the results +# - name: Parse Results +# run: | +# cd ~/input_files/output +# /bin/echo "Biomodels processed $(cat jobLog.txt | grep '.omex,SUCC\|.omex,FAIL' | wc -l)" >> ~/import_results.txt +# /bin/echo "Biomodels succeeded $(cat jobLog.txt | grep SUCC | wc -l)" >> ~/import_results.txt +# /bin/echo "Biomodels that didn't converge $(cat jobLog.txt | grep SUCC | grep -v ',1' | wc -l)" >> ~/import_results.txt +# +# # Upload results +# - name: Upload Results of Round-Trip +# uses: actions/upload-artifact@v3 +# with: +# name: import_results.txt +# path: ~/import_results.txt +# +# - name: Upload Results of Round-Trip +# uses: actions/upload-artifact@v3 +# with: +# name: import_log_original +# path: ~/input_files/output/jobLog.txt +# +# # Report a Problem to Slack +# - name: Report Problem to Slack +# if: ${{ failure() }} +# run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="Uh-Oh! The *Import Step* of Nightly Testing Action on GitHub Failed ( ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} )! This may need attention..." https://slack.com/api/chat.postMessage +# +# # Tmate just in case +# - name: Setup tmate session 3 +# uses: mxschmitt/action-tmate@v3 +# if: ${{ failure() }} +# +# summarize: +# runs-on: ubuntu-20.04 +# needs: import +# steps: +# - name: Make Results Directory +# run: mkdir -p ~/results && cd ~/results +# +# - name: Download Export Results +# uses: actions/download-artifact@v3 +# with: +# name: export_results.txt +# path: ~/results +# +# - name: Download Import Results +# uses: actions/download-artifact@v3 +# with: +# name: import_results.txt +# path: ~/results +# +# - name: Compile Results +# run: | +# if [ $() -gt 50000] && [ $() -lt 120000 ]; then echo -n 'Good Morning! ' >> ~/results/summary.txt; fi +# echo 'Here are the results of the Nightly Testing. Have a great day!' >> ~/results/summary.txt +# echo '' >> ~/results/summary.txt +# echo '-------- Export Results --------' >> ~/results/summary.txt +# cat ~/results/export_results.txt >> ~/results/summary.txt +# echo '-------- Import Results --------' >> ~/results/summary.txt +# cat ~/results/import_results.txt >> ~/results/summary.txt +# echo '' >> ~/results/summary.txt +# +# # Report a Success +# - name: Report Results to Slack +# run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="$(cat ~/results/summary.txt)" https://slack.com/api/chat.postMessage +# +# # Report a Problem to Slack +# - name: Report Problem to Slack +# if: ${{ failure() }} +# run: curl -X POST -F token="${{ secrets.SLACK_BOT_TOKEN }}" -F channel=${{ secrets.SLACK_CHANNEL_VCELL_DEV_TOKEN }} -F text="Oops! The *Summary Step* of Nightly Testing Action on GitHub Failed ( ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} ). Go see what happened!" https://slack.com/api/chat.postMessage +# +# - name: Setup tmate session 3 +# uses: mxschmitt/action-tmate@v3 +# if: ${{ failure() }} +# diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/Hdf5Writer.java b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/Hdf5Writer.java index 19d2965ed7..86049685d1 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/Hdf5Writer.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/Hdf5Writer.java @@ -72,7 +72,7 @@ public static void writeHdf5(Hdf5DataContainer hdf5DataWrapper, File outDirForCu masterHdf5.insertNumericAttributes(currentDatasetId, "times", Hdf5DataPreparer.getSpatialHdf5Attribute_Times(data)); } masterHdf5.insertFixedStringAttribute(currentDatasetId, "_type", data.datasetMetadata._type); - masterHdf5.insertFixedStringAttributes(currentDatasetId, "scanParameterNames", Arrays.asList(data.dataSource.scanParameterNames)); + //masterHdf5.insertFixedStringAttributes(currentDatasetId, "scanParameterNames", Arrays.asList(data.dataSource.scanParameterNames)); masterHdf5.insertFixedStringAttributes(currentDatasetId, "sedmlDataSetDataTypes", data.datasetMetadata.sedmlDataSetDataTypes); masterHdf5.insertFixedStringAttributes(currentDatasetId, "sedmlDataSetIds", data.datasetMetadata.sedmlDataSetIds); diff --git a/vcell-cli/src/main/java/org/vcell/cli/vcml/ExportOmexBatchCommand.java b/vcell-cli/src/main/java/org/vcell/cli/vcml/ExportOmexBatchCommand.java index 089335647e..9da3778ae3 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/vcml/ExportOmexBatchCommand.java +++ b/vcell-cli/src/main/java/org/vcell/cli/vcml/ExportOmexBatchCommand.java @@ -1,5 +1,6 @@ package org.vcell.cli.vcml; +import org.vcell.cli.vcml.ExportOmexCommand; import cbit.vcell.resource.PropertyLoader; import org.apache.logging.log4j.Level; @@ -10,12 +11,18 @@ import org.vcell.admin.cli.CLIDatabaseService; import org.vcell.cli.CLIRecorder; import org.vcell.sedml.ModelFormat; +import org.vcell.sedml.SEDMLEventLog; +import org.vcell.sedml.SEDMLEventLogFile; import org.vcell.util.DataAccessException; import picocli.CommandLine.Command; import picocli.CommandLine.Option; import java.io.File; import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.sql.SQLException; import java.util.concurrent.Callable; @@ -64,23 +71,88 @@ public class ExportOmexBatchCommand implements Callable { private boolean help; public Integer call() { - Level logLevel = bDebug ? Level.DEBUG : logger.getLevel(); + Level logLevel = this.bDebug ? Level.DEBUG : logger.getLevel(); LoggerContext config = (LoggerContext)(LogManager.getContext(false)); config.getConfiguration().getLoggerConfig(LogManager.getLogger("org.vcell").getName()).setLevel(logLevel); config.getConfiguration().getLoggerConfig(LogManager.getLogger("cbit").getName()).setLevel(logLevel); config.updateLoggers(); - + final SEDMLEventLog sedmlEventLog; try { - logger.debug("Batch export of omex files requested"); PropertyLoader.loadProperties(); - if (inputFilePath == null || !inputFilePath.exists() || !inputFilePath.isDirectory()) - throw new RuntimeException("inputFilePath '" + (inputFilePath == null ? "" : inputFilePath) + "' is not a 'valid directory'"); - - if (outputFilePath.exists() && !outputFilePath.isDirectory()) - throw new RuntimeException("outputFilePath '" + outputFilePath + "' is not a 'valid directory'"); + File parentDir = new File(outputFilePath.getParent()).getCanonicalFile(); + if (this.inputFilePath == null || !this.inputFilePath.exists() || !this.inputFilePath.isDirectory()) + throw new RuntimeException("inputFilePath '" + (this.inputFilePath == null ? "" : this.inputFilePath) + "' is not a valid VCML archive"); + if (this.outputFilePath == null || !this.outputFilePath.isDirectory()) + throw new RuntimeException("outputFilePath '" + (this.outputFilePath == null ? "" : this.outputFilePath) + "' is not a valid target for OMEX archive"); + if (parentDir.exists() && !parentDir.isDirectory()) { + throw new RuntimeException("directory for output '" + parentDir.getCanonicalPath() + "' is not a valid directory for OMEX archive"); + } + if (!parentDir.exists()) + if (!parentDir.mkdirs()) + throw new RuntimeException("Output dir doesn't exist and could not be made!"); + + + if (bWriteLogFiles) { + sedmlEventLog = new SEDMLEventLogFile(new File(outputFilePath, "jobLog.txt")); + } else { + sedmlEventLog = (String entry) -> {}; + } + } catch (IOException e){ + throw new RuntimeException("Error in setting up batch execution:\n\t", e); + } + try { + PropertyLoader.loadProperties(); + + logger.debug("Batch export of omex files requested"); + int numSuccessfulExports = 0, numTotalFiles = 0; + Path inputDirPath = this.inputFilePath.getCanonicalFile().toPath(); + try (DirectoryStream dirStream = Files.newDirectoryStream(inputDirPath)){ + for (Path child : dirStream){ + // Begin Setup + File childFile, targetOutputFile; + try { + childFile = child.toFile(); + if (childFile.isDirectory()){ + continue; + } + if (!child.toString().endsWith(".vcml")){ + continue; + } + numTotalFiles++; + + String childFileFullName = childFile.getName(); + String outputFileName = childFileFullName.substring(0, childFileFullName.length() - 5); + targetOutputFile = Paths.get(this.outputFilePath.getCanonicalPath(), outputFileName).toFile(); + } catch (IOException e){ + logger.error("Error setting up '" + child.getFileName() + "':\n\t", e); + continue; + } + + // Setup Complete, Begin Conversion. + try { + ExportOmexCommand.exportVCMLFile(childFile, targetOutputFile, this.outputModelFormat, sedmlEventLog, + this.bWriteLogFiles, this.bValidateOmex, this.bSkipUnsupportedApps); + logger.info("Conversion from '" + child.getFileName() + + "' to '" + targetOutputFile.getName() + "' succeeded"); + numSuccessfulExports++; + } catch (Exception e){ + logger.error("Conversion for '" + child.getFileName() + "' failed:\n\t", e); + } + logger.error("Continuing to next file to convert.\n\n"); + } + logger.info(String.format("Batch mode complete.\n\t" + + " %d/%d exports were successful.", numSuccessfulExports, numTotalFiles)); + } + + } catch (Exception e){ + logger.error("Unexpected IO Error occurred, ending batch conversion"); + throw new RuntimeException("Unexpected IO error occurred:\n\t", e); + } + return 0; + /* old methodology if (bOffline) this.runInOfflineMode(); else this.run(); @@ -91,6 +163,7 @@ public Integer call() { } finally { logger.debug("Batch export completed"); } + */ } private void runInOfflineMode() throws IOException { diff --git a/vcell-cli/src/main/java/org/vcell/cli/vcml/ExportOmexCommand.java b/vcell-cli/src/main/java/org/vcell/cli/vcml/ExportOmexCommand.java index d9db532930..017c507750 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/vcml/ExportOmexCommand.java +++ b/vcell-cli/src/main/java/org/vcell/cli/vcml/ExportOmexCommand.java @@ -7,6 +7,7 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.LoggerContext; import org.vcell.sedml.ModelFormat; +import org.vcell.sedml.SEDMLEventLog; import org.vcell.util.DataAccessException; import picocli.CommandLine.Command; import picocli.CommandLine.Option; @@ -42,8 +43,8 @@ public class ExportOmexCommand implements Callable { boolean bValidateOmex; public Integer call() { - Level logLevel = bDebug ? Level.DEBUG : logger.getLevel(); - + Level logLevel = bDebug ? Level.DEBUG : logger.getLevel(); + LoggerContext config = (LoggerContext)(LogManager.getContext(false)); config.getConfiguration().getLoggerConfig(LogManager.getLogger("org.vcell").getName()).setLevel(logLevel); config.getConfiguration().getLoggerConfig(LogManager.getLogger("cbit").getName()).setLevel(logLevel); @@ -52,15 +53,35 @@ public Integer call() { try { PropertyLoader.loadProperties(); - logger.debug("Beginning export"); - VcmlOmexConverter.convertOneFile( - inputFilePath, outputFilePath, outputModelFormat, bWriteLogFiles, bValidateOmex, bSkipUnsupportedApps); - return 0; + if (inputFilePath == null || !inputFilePath.exists() || !inputFilePath.isDirectory()) + throw new RuntimeException("inputFilePath '" + (inputFilePath == null ? "" : inputFilePath) + "' is not a valid VCML archive"); + + if (outputFilePath == null || outputFilePath.isDirectory()) + throw new RuntimeException("outputFilePath '" + (outputFilePath == null ? "" : outputFilePath) + "' is not a valid target for OMEX archive"); + + if (outputFilePath.exists()) + this.logger.warn(String.format("File '%s' already exists.")); + + return ExportOmexCommand.exportVCMLFile(this.inputFilePath, this.outputFilePath, + this.outputModelFormat, null, this.bWriteLogFiles, this.bValidateOmex, this.bSkipUnsupportedApps); + } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } finally { - logger.debug("Completed all exports"); + throw new RuntimeException("Export failed with message:\n\t" + e.getMessage(), e); + } + } + + public static int exportVCMLFile(File inputFilePath, File outputFilePath, ModelFormat outputModelFormat, SEDMLEventLog sedmlEventLog, + boolean bWriteLogFiles, boolean bValidateOmex, boolean bSkipUnsupportedApps) + throws Exception { + try { + logger.debug(String.format("Beginning export of '%s'", inputFilePath.getName())); + VcmlOmexConverter.convertOneFile(inputFilePath, outputFilePath, outputModelFormat, sedmlEventLog, + bWriteLogFiles, bValidateOmex, bSkipUnsupportedApps); + logger.debug(String.format("Finished export of '%s'", inputFilePath.getName())); + } catch (Exception e){ + logger.error(String.format("Error while exporting '%s'", inputFilePath.getName())); // We throw, no need to print error here + throw e; } + return 0; } } diff --git a/vcell-cli/src/main/java/org/vcell/cli/vcml/VCMLConversionException.java b/vcell-cli/src/main/java/org/vcell/cli/vcml/VCMLConversionException.java new file mode 100644 index 0000000000..0427621f15 --- /dev/null +++ b/vcell-cli/src/main/java/org/vcell/cli/vcml/VCMLConversionException.java @@ -0,0 +1,19 @@ +package org.vcell.cli.vcml; + +public class VCMLConversionException extends Exception { + public VCMLConversionException(String message){ + super(message); + } + + public VCMLConversionException(String message, Throwable cause){ + super(message, cause); + } + + public VCMLConversionException(Throwable cause){ + super(cause); + } + + public VCMLConversionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace){ + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/vcell-cli/src/main/java/org/vcell/cli/vcml/VcmlOmexConverter.java b/vcell-cli/src/main/java/org/vcell/cli/vcml/VcmlOmexConverter.java index 0cdec9477e..e24f4ab890 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/vcml/VcmlOmexConverter.java +++ b/vcell-cli/src/main/java/org/vcell/cli/vcml/VcmlOmexConverter.java @@ -14,6 +14,7 @@ import org.apache.logging.log4j.Logger; import org.vcell.admin.cli.CLIDatabaseService; import org.vcell.sbml.OmexPythonUtils; +import org.vcell.sbml.UnsupportedSbmlExportException; import org.vcell.sedml.*; import org.vcell.util.DataAccessException; import org.vcell.util.document.BioModelInfo; @@ -42,6 +43,7 @@ public class VcmlOmexConverter { public static void convertOneFile(File input, File outputDir, ModelFormat modelFormat, + SEDMLEventLog passedInSedmlEventLog, boolean bWriteLogFiles, boolean bValidateOmex, boolean bSkipUnsupportedApps) @@ -53,12 +55,15 @@ public static void convertOneFile(File input, logger.debug("Beginning conversion of `" + input + "`"); Predicate simulationExportFilter = simulation -> true; BioModelInfo bioModelInfo = null; - final SEDMLEventLog sedmlEventLog; - if (bWriteLogFiles) { + SEDMLEventLog sedmlEventLog; + if (passedInSedmlEventLog != null){ + sedmlEventLog = passedInSedmlEventLog; + } else if (bWriteLogFiles) { sedmlEventLog = new SEDMLEventLogFile(new File(outputDir, jobLogFileName)); } else { sedmlEventLog = (String entry) -> {}; } + boolean bHasPython = true; List sedmlTaskRecords = SEDMLExporter.writeBioModel( input, @@ -204,19 +209,22 @@ public static void convertFilesNoDatabase(File inputDir, File outputDir, ModelFo bSkipUnsupportedApps, bHasPython, bValidateOmex); - if (!sedmlTaskRecords.stream().anyMatch((SEDMLTaskRecord r) -> r.getTaskResult() == TaskResult.FAILED)) { + if (sedmlTaskRecords.stream().noneMatch((SEDMLTaskRecord r) -> r.getTaskResult() == TaskResult.FAILED)) { logger.info("Combine archive created for `" + inputFileName + "`"); } else { List errorList = sedmlTaskRecords.stream() .filter((SEDMLTaskRecord r) -> r.getTaskResult() == TaskResult.FAILED) - .map((SEDMLTaskRecord r) -> r.getCSV()) + .map(SEDMLTaskRecord::getCSV) .collect(Collectors.toList()); String msg = "Failed converting VCML to OMEX archive for `" + inputFileName + "`, errors: " + errorList; logger.error(msg); - throw new RuntimeException(msg); + throw new VCMLConversionException(msg); } - } catch (SEDMLExporter.SEDMLExportException | OmexPythonUtils.OmexValidationException e) { + } catch (SEDMLExporter.SEDMLExportException | OmexPythonUtils.OmexValidationException | VCMLConversionException e) { logger.error("Failed converting VCML to OMEX archive for `" + inputFileName + "`", e); + } catch (Exception e){ + logger.error("Unexpected Exception occurred while converting VCML:\n\t", e); + throw e; } } logger.debug("Completed conversion of files in `" + inputDir + "`"); diff --git a/vcell-core/src/main/java/cbit/vcell/resource/PropertyLoader.java b/vcell-core/src/main/java/cbit/vcell/resource/PropertyLoader.java index 3c59b9557b..654bb5fd92 100644 --- a/vcell-core/src/main/java/cbit/vcell/resource/PropertyLoader.java +++ b/vcell-core/src/main/java/cbit/vcell/resource/PropertyLoader.java @@ -247,6 +247,8 @@ public class PropertyLoader { public static final String cmdSrvcSshCmdRestoreTimeoutFactor = record("vcell.ssh.cmd.restoretimeout", ValueType.GEN); public static final String cliWorkingDir = record("cli.workingDir", ValueType.DIR); + + public static final String vcellVcmlLocation = record("vcell.vcmlLocation", ValueType.DIR); public static final String enableSpringSaLaD = record("vcell.enableSpringSaLaD", ValueType.BOOL); diff --git a/vcell-core/src/main/java/org/vcell/sbml/OmexPythonUtils.java b/vcell-core/src/main/java/org/vcell/sbml/OmexPythonUtils.java index 315bdb08e9..dca52cde57 100644 --- a/vcell-core/src/main/java/org/vcell/sbml/OmexPythonUtils.java +++ b/vcell-core/src/main/java/org/vcell/sbml/OmexPythonUtils.java @@ -77,8 +77,7 @@ private static List getErrorsFromReport(JsonObject reportRo } private static int callCLIPython(String command, Path omexFile, Path tempDir, Path reportJsonFile) throws InterruptedException, IOException { - File installDir = PropertyLoader.getRequiredDirectory(PropertyLoader.installationRoot); - File cliPythonDir = Paths.get(installDir.getAbsolutePath(), "vcell-cli-utils").toAbsolutePath().toFile(); + File cliPythonDir = PropertyLoader.getRequiredDirectory(PropertyLoader.cliWorkingDir).getCanonicalFile(); ProcessBuilder pb = new ProcessBuilder( "poetry", "run", "python", "-m", "vcell_cli_utils.wrapper", diff --git a/vcell-core/src/main/java/org/vcell/sedml/SEDMLExporter.java b/vcell-core/src/main/java/org/vcell/sedml/SEDMLExporter.java index d8b7b25325..10a18c2a82 100644 --- a/vcell-core/src/main/java/org/vcell/sedml/SEDMLExporter.java +++ b/vcell-core/src/main/java/org/vcell/sedml/SEDMLExporter.java @@ -116,7 +116,8 @@ public SEDMLExporter(String argJobId, BioModel argBiomodel, int argLevel, int ar } public SEDMLDocument getSEDMLDocument(String sPath, String sBaseFileName, ModelFormat modelFormat, - boolean bRoundTripSBMLValidation, Predicate simContextExportFilter) { + boolean bRoundTripSBMLValidation, Predicate simContextExportFilter) throws + SEDMLExportException { double start = System.currentTimeMillis(); @@ -151,8 +152,14 @@ public SEDMLDocument getSEDMLDocument(String sPath, String sBaseFileName, ModelF sedmlModel = sedmlDocument.getSedMLModel(); sedmlModel.setAdditionalNamespaces(nsList); - this.translateBioModelToSedML(sPath, sBaseFileName, modelFormat, bRoundTripSBMLValidation, simContextExportFilter); - + try { + this.translateBioModelToSedML(sPath, sBaseFileName, modelFormat, bRoundTripSBMLValidation, simContextExportFilter); + } catch (UnsupportedSbmlExportException | SEDMLExportException | + MappingException | XmlParseException | NumberFormatException e){ + String message = "Unable to export to SED-ML:\n\t" + e.getMessage().replace("\n", "\n\t"); + throw new SEDMLExporter.SEDMLExportException(message, e); + } + double stop = System.currentTimeMillis(); Exception timer = new Exception(Double.toString((stop-start)/1000)+" seconds"); // update overall status @@ -171,7 +178,9 @@ public SEDMLDocument getSEDMLDocument(String sPath, String sBaseFileName, ModelF } private void translateBioModelToSedML(String savePath, String sBaseFileName, ModelFormat modelFormat, - boolean bRoundTripSBMLValidation, Predicate simContextExportFilter) { + boolean bRoundTripSBMLValidation, Predicate simContextExportFilter) + throws UnsupportedSbmlExportException, SEDMLExportException, MappingException, + XmlParseException, NumberFormatException { modelFilePathStrAbsoluteList.clear(); try { @@ -221,11 +230,11 @@ private void translateBioModelToSedML(String savePath, String sBaseFileName, Mod // Export the application itself to SBML, with default values (overrides will become model changes or repeated tasks) String sbmlString = null; Map, String> l2gMap = null; // local to global translation map - boolean sbmlExportFailed = false; + boolean noContextExportFailures = true; Exception simContextException = null; try { SBMLExporter.validateSimulationContextSupport(simContext); - boolean isSpatial = simContext.getGeometry().getDimension() > 0 ? true : false; + boolean isSpatial = simContext.getGeometry().getDimension() > 0; Pair , String>> pair = XmlHelper.exportSBMLwithMap(vcBioModel, 3, 2, 0, isSpatial, simContext, bRoundTripSBMLValidation); sbmlString = pair.one; l2gMap = pair.two; @@ -234,17 +243,21 @@ private void translateBioModelToSedML(String savePath, String sBaseFileName, Mod } catch (Exception e) { String msg = "SBML export failed for simContext '"+simContext.getName()+"': " + e.getMessage(); logger.error(msg, e); - sbmlExportFailed = true; + noContextExportFailures = false; simContextException = e; sedmlRecorder.addTaskRecord(simContext.getName(), TaskType.SIMCONTEXT, TaskResult.FAILED, e); } - if (!sbmlExportFailed) { - // simContext was exported succesfully, now we try to export its simulations + if (noContextExportFailures) { + // simContext was exported successfully, now we try to export its simulations exportSimulations(simContextCnt, simContext, sbmlString, l2gMap, sbmlLanguageURN); } else { System.err.println(sedmlRecorder.getRecordsAsCSV()); - throw new Exception ("SimContext '"+simContext.getName()+"' could not be exported to SBML :" +simContextException.getMessage(), simContextException); + String message = "SimContext '"+simContext.getName()+"' could not be exported to SBML :" +simContextException.getMessage(); + if (simContextException instanceof UnsupportedSbmlExportException){ + throw new UnsupportedSbmlExportException(message, simContextException); + } + throw new Exception (message, simContextException); } simContextCnt++; } @@ -260,6 +273,12 @@ private void translateBioModelToSedML(String savePath, String sBaseFileName, Mod } } catch (Exception e) { // this only happens if not from CLI, we need to pass this down the calling thread + String message = "Error adding model to SEDML document : " + e.getMessage(); + if (e instanceof UnsupportedSbmlExportException) throw new UnsupportedSbmlExportException(message, e); + if (e instanceof SEDMLExportException) throw new SEDMLExportException(message, e); + if (e instanceof MappingException) throw new MappingException(message, e); + if (e instanceof cbit.vcell.xml.XmlParseException) throw new XmlParseException(message, e); + if (e instanceof NumberFormatException) throw (NumberFormatException)e; throw new RuntimeException("Error adding model to SEDML document : " + e.getMessage(), e); } } @@ -293,7 +312,7 @@ private void exportSimulations(int simContextCnt, SimulationContext simContext, long numOfTrials = simTaskDesc.getStochOpt().getNumOfTrials(); if (numOfTrials > 1) { String msg = simContextName + " ( " + vcSimulation.getName() + " ) : export of non-spatial stochastic simulation with histogram option to SEDML not supported at this time."; - throw new Exception(msg); + throw new SEDMLExportException(msg); } } @@ -656,7 +675,7 @@ private UniformTimeCourse createSEDMLsim(SolverTaskDescription simTaskDesc) { private void createSEDMLtasks(int simContextCnt, Map, String> l2gMap, String simContextName, String simContextId, Simulation vcSimulation, UniformTimeCourse utcSim, Set dataGeneratorTasksSet, MathOverrides mathOverrides, String languageURN) - throws ExpressionBindingException, ExpressionException, DivideByZeroException, MappingException { + throws ExpressionBindingException, ExpressionException, DivideByZeroException, MappingException, UnsupportedSbmlExportException { if(mathOverrides != null && mathOverrides.hasOverrides()) { String[] overridenConstantNames = mathOverrides.getOverridenConstantNames(); String[] scannedConstantsNames = mathOverrides.getScannedConstantNames(); @@ -927,7 +946,7 @@ private Expression adjustIfRateParam(Simulation vcSimulation, SymbolTableEntry s private RepeatedTask createSEDMLreptask(String rangeId, Map, String> l2gMap, SimulationContext simContext, Set dataGeneratorTasksSet, MathOverrides mathOverrides, String ownerTaskId, String scannedConstName, String repeatedTaskId, String modelReferenceId) - throws ExpressionException, DivideByZeroException, MappingException { + throws ExpressionException, DivideByZeroException, MappingException, UnsupportedSbmlExportException { RepeatedTask rt = new RepeatedTask(repeatedTaskId, mathOverrides.getSimulation().getName(), true, rangeId); dataGeneratorTasksSet.add(rt.getId()); SubTask subTask = new SubTask("0", ownerTaskId); @@ -949,7 +968,7 @@ private RepeatedTask createSEDMLreptask(String rangeId, Map } private Range createSEDMLrange(String rangeId, RepeatedTask rt, ConstantArraySpec constantArraySpec, String scannedConstantName, SimulationContext simContext, Map, String> l2gMap, String modelReferenceId, Simulation vcSim) - throws ExpressionException, DivideByZeroException, MappingException { + throws ExpressionException, DivideByZeroException, MappingException, UnsupportedSbmlExportException { Range r = null; SimulationContext sc = (SimulationContext)vcSim.getSimulationOwner(); SymbolReplacement sr = sc.getMathOverridesResolver().getSymbolReplacement(scannedConstantName, true); @@ -1012,7 +1031,7 @@ private Range createSEDMLrange(String rangeId, RepeatedTask rt, ConstantArraySpe } private void createFunctionalRangeElements(FunctionalRange fr, Expression func, SimulationContext simContext, - Map, String> l2gMap, String modelReferenceId) throws ExpressionException, MappingException { + Map, String> l2gMap, String modelReferenceId) throws ExpressionException, MappingException, UnsupportedSbmlExportException { String[] symbols = func.getSymbols(); MathSymbolMapping msm = (MathSymbolMapping)simContext.getMathDescription().getSourceSymbolMapping(); for(String symbol : symbols) { @@ -1098,7 +1117,7 @@ public static SymbolTableEntry getSymbolTableEntryForModelEntity(MathSymbolMappi } } - private XPathTarget getTargetAttributeXPath(SymbolTableEntry ste, Map, String> l2gMap, SimulationContext simContext) { + private XPathTarget getTargetAttributeXPath(SymbolTableEntry ste, Map, String> l2gMap, SimulationContext simContext) throws UnsupportedSbmlExportException { // VCML model format if (l2gMap == null) return getVCMLTargetXPath(ste, simContext); // SBML model format @@ -1131,7 +1150,7 @@ private XPathTarget getTargetAttributeXPath(SymbolTableEntry ste, Map key = new Pair(reactionID, parameterID); + Pair key = new Pair<>(reactionID, parameterID); String value = l2gMap.get(key); if(value == null) { // stays as local parameter @@ -1187,7 +1206,7 @@ private XPathTarget getTargetAttributeXPath(SymbolTableEntry ste, Map writeBioModel(BioModel bioModel, // export the entire biomodel to a SEDML file (all supported applications) int sedmlLevel = 1; int sedmlVersion = 2; - String sOutputDirPath = FileUtils.getFullPathNoEndSeparator(exportFileOrDirectory.getAbsolutePath()); - String sBaseFileName = FileUtils.getBaseName(exportFileOrDirectory.getAbsolutePath()); + String sOutputDirPath; + String sBaseFileName; + /* if (exportFileOrDirectory.isDirectory()){ + String strPath = exportFileOrDirectory.toPath().toString(); + sOutputDirPath = Paths.get(FileUtils.getFullPath(strPath), exportFileOrDirectory.getName()).toString(); + sBaseFileName = bioModel.getName(); + } else { + sOutputDirPath = FileUtils.getFullPathNoEndSeparator(exportFileOrDirectory.getAbsolutePath()); + sBaseFileName = FileUtils.getBaseName(exportFileOrDirectory.getAbsolutePath()); + }*/ + + sOutputDirPath = FileUtils.getFullPathNoEndSeparator(exportFileOrDirectory.getAbsolutePath()); + sBaseFileName = FileUtils.getBaseName(exportFileOrDirectory.getAbsolutePath()); List simsToExport = Arrays.stream(bioModel.getSimulations()).filter(simulationExportFilter).collect(Collectors.toList()); @@ -1470,14 +1500,14 @@ private static List writeBioModel(BioModel bioModel, // try to replace with the fully supported equivalent (do we need to reset solver parameters?) simulation.getSolverTaskDescription().setSolverDescription(SolverDescription.SundialsPDE); } catch (PropertyVetoException e) { - String msg1 = "Failed to replace obsolete PDE solver '"+SolverDescription.FiniteVolume.name()+"' " + - "with fully supported equivalent PDE solver '"+SolverDescription.SundialsPDE.name()+"'"; - logger.error(msg1,e); + String msg1 = "Failed to replace obsolete PDE solver '" + SolverDescription.FiniteVolume.name() + "' " + + "with fully supported equivalent PDE solver '" + SolverDescription.SundialsPDE.name() + "'"; + logger.error(msg1, e); try { simulation.getSolverTaskDescription().setSolverDescription(SolverDescription.FiniteVolumeStandalone); } catch (PropertyVetoException e1) { - String msg2 = "Failed to replace obsolete PDE solver '"+SolverDescription.FiniteVolume.name()+"' " + - "with equivalent PDE solver '"+SolverDescription.FiniteVolumeStandalone.name()+"'"; + String msg2 = "Failed to replace obsolete PDE solver '" + SolverDescription.FiniteVolume.name() + "' " + + "with equivalent PDE solver '" + SolverDescription.FiniteVolumeStandalone.name() + "'"; logger.error(msg2, e1); throw new RuntimeException(msg2, e1); } @@ -1492,14 +1522,13 @@ private static List writeBioModel(BioModel bioModel, XmlUtil.writeXMLStringToFile(vcmlString, vcmlFile.getAbsolutePath(), true); String jsonReportPath = null; - if (jsonReportFile.isPresent()){ + if (jsonReportFile.isPresent()) { jsonReportPath = jsonReportFile.get().getAbsolutePath(); } SEDMLExporter sedmlExporter = new SEDMLExporter(sBaseFileName, bioModel, sedmlLevel, sedmlVersion, simsToExport, jsonReportPath); String sedmlString = sedmlExporter.getSEDMLDocument(sOutputDirPath, sBaseFileName, modelFormat, bValidate, simContextExportFilter).writeDocumentToString(); if (bCreateOmexArchive) { - String sedmlFileName = Paths.get(sOutputDirPath, sBaseFileName + ".sedml").toString(); XmlUtil.writeXMLStringToFile(sedmlString, sedmlFileName, true); sedmlExporter.addSedmlFileToList(sBaseFileName + ".sedml"); diff --git a/vcell-core/src/test/java/cbit/vcell/biomodel/MathOverrideRoundTipTest.java b/vcell-core/src/test/java/cbit/vcell/biomodel/MathOverrideRoundTipTest.java index 2ec1e5ddd9..5cd5cf41d1 100644 --- a/vcell-core/src/test/java/cbit/vcell/biomodel/MathOverrideRoundTipTest.java +++ b/vcell-core/src/test/java/cbit/vcell/biomodel/MathOverrideRoundTipTest.java @@ -42,6 +42,7 @@ public class MathOverrideRoundTipTest { // save state for zero side-effect // private String previousInstalldirPropertyValue; + private String previousCliWorkDirPropertyValue; private boolean previousWriteDebugFiles; public MathOverrideRoundTipTest(String filename) { @@ -64,7 +65,9 @@ public static List filenames() { @Before public void setup() { previousInstalldirPropertyValue = System.getProperty("vcell.installDir"); + previousCliWorkDirPropertyValue = System.getProperty("cli.workingDir"); System.setProperty("vcell.installDir", ".."); + System.setProperty("cli.workingDir", System.getProperty("vcell.installDir") + "/vcell-cli-utils"); NativeLib.combinej.load(); this.previousWriteDebugFiles = SBMLExporter.bWriteDebugFiles; SBMLExporter.bWriteDebugFiles = bDebug; @@ -72,9 +75,12 @@ public void setup() { @After public void teardown() { - if (previousInstalldirPropertyValue!=null) { + if (previousInstalldirPropertyValue != null) { System.setProperty("vcell.installDir", previousInstalldirPropertyValue); } + if (previousCliWorkDirPropertyValue != null) { + System.setProperty("cli.workingDir", previousCliWorkDirPropertyValue); + } SBMLExporter.bWriteDebugFiles = previousWriteDebugFiles; } diff --git a/vcell-core/src/test/java/org/vcell/sbml/NightlyRoundTripVCMLFilenameFilter.java b/vcell-core/src/test/java/org/vcell/sbml/NightlyRoundTripVCMLFilenameFilter.java new file mode 100644 index 0000000000..7b0bc8d27d --- /dev/null +++ b/vcell-core/src/test/java/org/vcell/sbml/NightlyRoundTripVCMLFilenameFilter.java @@ -0,0 +1,63 @@ +package org.vcell.sbml; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.HashSet; +import java.util.Set; + +public class NightlyRoundTripVCMLFilenameFilter implements FilenameFilter { + + private static Set exemptTests; + + // Static Initializer, equivalent to a static "contractor" + static { + Set superSet = new HashSet<>(); + superSet.addAll(NightlyRoundTripVCMLFilenameFilter.slowTestSet()); + superSet.addAll(NightlyRoundTripVCMLFilenameFilter.outOfMemorySet()); + superSet.addAll(NightlyRoundTripVCMLFilenameFilter.largeFileSet()); + NightlyRoundTripVCMLFilenameFilter.exemptTests = superSet; + } + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".vcml") && !NightlyRoundTripVCMLFilenameFilter.exemptTests.contains(name); + } + + static Set slowTestSet() { + Set slowModels = new HashSet<>(); + slowModels.add("biomodel_101981216.vcml"); // 29s + slowModels.add("biomodel_147699816.vcml"); // 23s + slowModels.add("biomodel_17326658.vcml"); // 24s + slowModels.add("biomodel_188880263.vcml"); // 89s + slowModels.add("biomodel_200301029.vcml"); // 124s (and fails with java.lang.OutOfMemoryError: GC overhead limit exceeded) + slowModels.add("biomodel_200301683.vcml"); // 37s + slowModels.add("biomodel_28625786.vcml"); // 57s + slowModels.add("biomodel_34826524.vcml"); // 129s + slowModels.add("biomodel_47429473.vcml"); // 194s + slowModels.add("biomodel_59361239.vcml"); // 116s + slowModels.add("biomodel_60799209.vcml"); // 41s + slowModels.add("biomodel_61699798.vcml"); // 69s + slowModels.add("biomodel_62467093.vcml"); // 23s + slowModels.add("biomodel_62477836.vcml"); // 30s + slowModels.add("biomodel_62585003.vcml"); // 24s + slowModels.add("biomodel_66264206.vcml"); // 45s + slowModels.add("biomodel_93313420.vcml"); // 137s + slowModels.add("biomodel_9590643.vcml"); // 40s + return slowModels; + } + + static Set outOfMemorySet() { + Set outOfMemoryModels = new HashSet<>(); + outOfMemoryModels.add("biomodel_101963252.vcml"); // FAULT.JAVA_HEAP_SPACE + outOfMemoryModels.add("biomodel_200301029.vcml"); // FAULT.OUT_OF_MEMORY - GC Overhead Limit Exceeded (and 124s) + outOfMemoryModels.add("biomodel_26455186.vcml"); // FAULT.OUT_OF_MEMORY - GC Overhead Limit Exceeded + outOfMemoryModels.add("biomodel_27192647.vcml"); // FAULT.OUT_OF_MEMORY - GC Overhead Limit Exceeded + outOfMemoryModels.add("biomodel_27192717.vcml"); // FAULT.OUT_OF_MEMORY) - Java heap space: failed reallocation of scalar replaced objects + return outOfMemoryModels; + } + + public static Set largeFileSet() { + Set largeFiles = new HashSet<>(); + largeFiles.add("biomodel_101963252.vcml"); + return largeFiles; + } +} diff --git a/vcell-core/src/test/java/org/vcell/sbml/RoundTripException.java b/vcell-core/src/test/java/org/vcell/sbml/RoundTripException.java new file mode 100644 index 0000000000..a84d570ab6 --- /dev/null +++ b/vcell-core/src/test/java/org/vcell/sbml/RoundTripException.java @@ -0,0 +1,41 @@ +package org.vcell.sbml; + + +public class RoundTripException extends Exception { + + protected boolean wasTheExpectedResult; + protected SEDMLExporterNightlyRoundTrip.SEDML_FAULT faultType; + public RoundTripException(boolean wasTheExpectedResult, SEDMLExporterNightlyRoundTrip.SEDML_FAULT faultType){ + super(); + this._localConstructor(wasTheExpectedResult, faultType); + } + + public RoundTripException(String message, boolean wasTheExpectedResult, + SEDMLExporterNightlyRoundTrip.SEDML_FAULT faultType){ + super(message); + this._localConstructor(wasTheExpectedResult, faultType); + } + + public RoundTripException(String message, Throwable cause, boolean wasTheExpectedResult, + SEDMLExporterNightlyRoundTrip.SEDML_FAULT faultType){ + super(message, cause); + this._localConstructor(wasTheExpectedResult, faultType); + } + + public RoundTripException(Throwable cause, boolean wasTheExpectedResult, + SEDMLExporterNightlyRoundTrip.SEDML_FAULT faultType){ + super(cause); + this._localConstructor(wasTheExpectedResult, faultType); + } + + protected RoundTripException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, + boolean wasTheExpectedResult, SEDMLExporterNightlyRoundTrip.SEDML_FAULT faultType ){ + super(message, cause, enableSuppression, writableStackTrace); + this._localConstructor(wasTheExpectedResult, faultType); + } + + private void _localConstructor(boolean wasTheExpectedResult, SEDMLExporterNightlyRoundTrip.SEDML_FAULT faultType){ + this.wasTheExpectedResult = wasTheExpectedResult; + this.faultType = faultType; + } +} diff --git a/vcell-core/src/test/java/org/vcell/sbml/RoundTripStatistics.java b/vcell-core/src/test/java/org/vcell/sbml/RoundTripStatistics.java new file mode 100644 index 0000000000..46e1dff54d --- /dev/null +++ b/vcell-core/src/test/java/org/vcell/sbml/RoundTripStatistics.java @@ -0,0 +1,46 @@ +package org.vcell.sbml; +import java.io.BufferedWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class RoundTripStatistics { + private int numBioModelsProcessed; + private int numBioModelsSucceeded; + private Map failureTypeToNumMap; + + public RoundTripStatistics(){ + this.numBioModelsProcessed = 0; + this.numBioModelsSucceeded = 0; + this.failureTypeToNumMap = new HashMap<>(); + } + + public void recordFailureResult(RoundTripException e){ + this.numBioModelsProcessed += 1; + if (!this.failureTypeToNumMap.containsKey(e.faultType)) + this.failureTypeToNumMap.put(e.faultType, 0); + this.failureTypeToNumMap.put(e.faultType, this.failureTypeToNumMap.get(e.faultType) + 1); + } + + public void recordSuccessResult(){ + this.numBioModelsProcessed += 1; + this.numBioModelsSucceeded += 1; + } + + public void exportResultsToWriter(BufferedWriter writer) throws IOException { + writer.write(this.getResults()); + writer.flush(); + } + + public String getResults(){ + String str = ""; + str += String.format("Results of Round Trip:\n"); + str += String.format(" BioModels Processed:\t%d\n", this.numBioModelsProcessed); + str += String.format(" BioModels Succeeded:\t%d\n", this.numBioModelsSucceeded); + for (SEDMLExporterNightlyRoundTrip.SEDML_FAULT fault : this.failureTypeToNumMap.keySet()){ + str += String.format(" - BioModels failed with: '%s' fault: %d", fault.name(), + this.failureTypeToNumMap.get(fault)); + } + return str; + } +} diff --git a/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterCommon.java b/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterCommon.java index ec85d1174a..93a9a22efa 100644 --- a/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterCommon.java +++ b/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterCommon.java @@ -1,345 +1,351 @@ -package org.vcell.sbml; - -import cbit.util.xml.XmlUtil; -import cbit.vcell.biomodel.BioModel; -import cbit.vcell.biomodel.ModelUnitConverter; -import cbit.vcell.mapping.SimulationContext; -import cbit.vcell.math.MathCompareResults; -import cbit.vcell.math.MathDescription; -import cbit.vcell.resource.NativeLib; -import cbit.vcell.solver.Simulation; -import cbit.vcell.solver.SimulationSymbolTable; -import cbit.vcell.solver.SolverDescription; -import cbit.vcell.xml.XMLSource; -import cbit.vcell.xml.XmlHelper; -import com.google.common.io.Files; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.vcell.sbml.vcell.SBMLExporter; -import org.vcell.sedml.*; - -import java.io.*; -import java.util.*; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -public abstract class SEDMLExporterCommon { - - static class TestCase { - public final String filename; - public final ModelFormat modelFormat; - - public TestCase(String filename, ModelFormat modelFormat){ - this.filename = filename; - this.modelFormat = modelFormat; - } - } - - - final TestCase testCase; - - private static boolean bDebug = false; - - // - // save state for zero side-effect - // - private static String previousInstalldirPropertyValue; - private static boolean previousWriteDebugFiles; - - public SEDMLExporterCommon(TestCase testCase){ - this.testCase = testCase; - } - - public enum FAULT { - EXPRESSIONS_DIFFERENT, - EQUATION_REMOVED, - EXPRESSION_BINDING, - MATH_GENERATION_FAILURE, - MATHOVERRIDES_INVALID, - MATHOVERRIDES_SurfToVol, - MATHOVERRIDES_A_FUNCTION, - UNITS_EXCEPTION, - TOO_SLOW, - GEOMETRYSPEC_DIFFERENT, - NULL_POINTER_EXCEPTION, - UNKNOWN_IDENTIFIER, - SBML_IMPORT_FAILURE, - DIVIDE_BY_ZERO, - UNSUPPORTED_NONSPATIAL_STOCH_HISTOGRAM, - SEDML_UNSUPPORTED_ENTITY - }; - - public enum SEDML_FAULT { - DIFF_NUMBER_OF_BIOMODELS, - OMEX_PARSER_ERRORS, - OMEX_VALIDATION_ERRORS, - NO_MODELS_IN_OMEX, - ERROR_CONSTRUCTING_SIMCONTEXT, - NONSPATIAL_STOCH_HISTOGRAM, - MATH_OVERRIDE_NOT_EQUIVALENT, - MATH_OVERRIDE_NAMES_DIFFERENT, - SIMCONTEXT_NOT_FOUND_BY_NAME, - SIMULATION_NOT_FOUND_BY_NAME - }; - - @BeforeClass - public static void setup(){ - previousInstalldirPropertyValue = System.getProperty("vcell.installDir"); - System.setProperty("vcell.installDir", ".."); - NativeLib.combinej.load(); - previousWriteDebugFiles = SBMLExporter.bWriteDebugFiles; - SBMLExporter.bWriteDebugFiles = bDebug; - } - - @AfterClass - public static void teardown() throws IOException { - if (previousInstalldirPropertyValue!=null) { - System.setProperty("vcell.installDir", previousInstalldirPropertyValue); - } - SBMLExporter.bWriteDebugFiles = previousWriteDebugFiles; - } - - /** - * each file in largeFileSet is > 500K on disk and is not included in the test suite. - * @return - */ - public static Set largeFileSet() { - Set largeFiles = new HashSet<>(); - largeFiles.add("biomodel_101963252.vcml"); - return largeFiles; - } - - /** - * each file in the knownFaultsMap hold known problems in the current software - */ - abstract Map knownFaults(); - - - abstract Map knownSEDMLFaults(); - - - void sedml_roundtrip_common() throws Exception { - String test_case_name = testCase.modelFormat+"."+testCase.filename; - InputStream testFileInputStream = VcmlTestSuiteFiles.getVcmlTestCase(testCase.filename); - String vcmlStr = new BufferedReader(new InputStreamReader(testFileInputStream)) - .lines().collect(Collectors.joining("\n")); - - BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(vcmlStr)); - - bioModel.updateAll(false); - - Predicate simulationExportFilter = sim -> true; - List simsToExport = Arrays.stream(bioModel.getSimulations()).filter(simulationExportFilter).collect(Collectors.toList()); - - // we replace the obsolete solver with the fully supported equivalent - for (Simulation simulation : simsToExport) { - if (simulation.getSolverTaskDescription().getSolverDescription().equals(SolverDescription.FiniteVolume)) { - simulation.getSolverTaskDescription().setSolverDescription(SolverDescription.SundialsPDE); - } - } - File outputDir = Files.createTempDir(); - String jsonFullyQualifiedName = new File(outputDir, test_case_name + ".json").getAbsolutePath(); - System.out.println(jsonFullyQualifiedName); - - boolean bHasPython = true; - boolean bRoundTripSBMLValidation = true; - boolean bWriteOmexArchive = true; - File omexFile = new File(outputDir, test_case_name + ".omex"); - Optional publicationMetadata = Optional.empty(); - Map unsupportedApplications = SEDMLExporter.getUnsupportedApplicationMap(bioModel, testCase.modelFormat); - Predicate simContextFilter = (SimulationContext sc) -> !unsupportedApplications.containsKey(sc.getName()); - try { - List sedmlTaskRecords = SEDMLExporter.writeBioModel( - bioModel, publicationMetadata, omexFile, testCase.modelFormat, simContextFilter, bHasPython, bRoundTripSBMLValidation, bWriteOmexArchive); - - boolean bAnyFailures = false; - for (SEDMLTaskRecord sedmlTaskRecord : sedmlTaskRecords) { - boolean bFailed = false; - switch (sedmlTaskRecord.getTaskType()) { - case BIOMODEL: { - break; - } - case SIMCONTEXT: { - bFailed = sedmlTaskRecord.getTaskResult() == TaskResult.FAILED && - (sedmlTaskRecord.getException() == null || !sedmlTaskRecord.getException().getClass().equals(UnsupportedSbmlExportException.class)); - break; - } - case UNITS: - case SIMULATION: { - bFailed = sedmlTaskRecord.getTaskResult() == TaskResult.FAILED; - break; - } - } - bAnyFailures |= bFailed; - if (!knownFaults().containsKey(testCase.filename)) { - // skip assert if the model is known to have a problem - Assert.assertFalse(sedmlTaskRecord.getCSV(), bFailed); - } - } - FAULT knownFault = knownFaults().get(testCase.filename); - if (knownFault != null){ - // if in the knownFaults list, the model should fail - // this is how we can keep track of our list of known problems - // if we fix a model without removing it from the knownFaults map, then this test will fail - Assert.assertTrue( - "expecting fault "+knownFault.name()+" in "+test_case_name+" but it passed, Please remove from SEDMLExporterTest.knownFaults()", - bAnyFailures); - } - - if (testCase.modelFormat == ModelFormat.VCML){ - System.err.println("skipping re-importing SEDML for this test case, not yet supported for VCML"); - return; - } - SBMLExporter.MemoryVCLogger memoryVCLogger = new SBMLExporter.MemoryVCLogger(); - List bioModels = XmlHelper.readOmex(omexFile, memoryVCLogger); - Assert.assertTrue(memoryVCLogger.highPriority.size() == 0); - - File tempDir = Files.createTempDir(); - String origVcmlPath = new File(tempDir, "orig.vcml").getAbsolutePath(); - XmlUtil.writeXMLStringToFile(XmlHelper.bioModelToXML(bioModel), origVcmlPath, true); - - if (bDebug) { - SBMLExporter.bWriteDebugFiles=true; - for (int i = 0; i < bioModels.size(); i++) { - String rereadVcmlPath = new File(tempDir, "reread_" + i + ".vcml").getAbsolutePath(); - XmlUtil.writeXMLStringToFile(XmlHelper.bioModelToXML(bioModels.get(i)), rereadVcmlPath, true); - } - System.err.println("wrote original and final BioModel VCML files to " + tempDir.getAbsolutePath()); - } - - Assert.assertEquals("expecting 1 biomodel in round trip", 1, bioModels.size()); - BioModel importedBioModel = bioModels.get(0); - - boolean hasAnyOverrides = Arrays.stream(bioModel.getSimulations()).anyMatch(s -> s.getMathOverrides().getSize() > 0); - if (testCase.modelFormat == ModelFormat.SBML && hasAnyOverrides){ - importedBioModel = ModelUnitConverter.createBioModelWithNewUnitSystem(importedBioModel, bioModel.getModel().getUnitSystem()); - } - - // - // compare Math Overrides for each simulation - // - for (Simulation simToExport : simsToExport){ - SimulationContext simContextToExport = bioModel.getSimulationContext(simToExport); - String simContextName = simContextToExport.getName(); - String simName = simToExport.getName(); - SimulationContext simContextRoundTripped = importedBioModel.getSimulationContext(simContextName); - Assert.assertNotNull("roundtripped simulationContext not found with name '"+simContextName+"'", simContextRoundTripped); - Simulation simRoundTripped = simContextRoundTripped.getSimulation(simName); - Assert.assertNotNull("roundtripped simulation not found with name '"+simName+"'", simRoundTripped); - boolean mathOverrideEquiv = simToExport.getMathOverrides().compareEquivalent(simRoundTripped.getMathOverrides()); - if (!mathOverrideEquiv){ - // - // math overrides didn't compare as equivalent, if overridden names are different, try substituting into math and comparing math - // - List oldOverrideNames = Arrays.stream(simToExport.getMathOverrides().getOverridenConstantNames()).sorted().collect(Collectors.toList()); - List newOverrideNames = Arrays.stream(simRoundTripped.getMathOverrides().getOverridenConstantNames()).sorted().collect(Collectors.toList()); - if (!oldOverrideNames.equals(newOverrideNames) && (simToExport.getScanCount() == simRoundTripped.getScanCount())){ - // simulation scan counts are the same, but overridden constants have different names, try substituting them into the math and compare the maths. - System.out.println("old names: "+oldOverrideNames+", new names: "+newOverrideNames); - for (int simJobIndex=0; simJobIndex < simToExport.getScanCount(); simJobIndex++){ - MathDescription oldMathDescription = new SimulationSymbolTable(simToExport, simJobIndex).getMathDescription(); - MathDescription newMathDescription = new SimulationSymbolTable(simRoundTripped, simJobIndex).getMathDescription(); - MathCompareResults subCompareResults = MathDescription.testEquivalency( - SimulationSymbolTable.createMathSymbolTableFactory(), oldMathDescription, newMathDescription); - Assert.assertTrue("math overrides names not equivalent for simulation '"+simName+"' " + - "in simContext '"+simContextName+"'", subCompareResults.isEquivalent()); - mathOverrideEquiv = true; - } - } - } - Assert.assertTrue("math overrides not equivalent for simulation '"+simName+"' in simContext '"+simContextName+"'", mathOverrideEquiv); - } - - Assert.assertNull("file "+test_case_name+" passed SEDML Round trip, but knownSEDMLFault was set", knownSEDMLFaults().get(testCase.filename)); - }catch (Exception | AssertionError e){ - if (e instanceof OmexPythonUtils.OmexValidationException){ - OmexPythonUtils.OmexValidationException validationException = (OmexPythonUtils.OmexValidationException) e; - if (validationException.errors.stream() - .anyMatch(err -> err.type == OmexPythonUtils.OmexValidationErrorType.OMEX_PARSE_ERROR)){ - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.OMEX_PARSER_ERRORS) { - System.err.println("Expected error: "+e.getMessage()); - return; - }else{ - System.err.println("add SEDML_FAULT.OMEX_PARSER_ERRORS to "+test_case_name+": "+e.getMessage()); - } - } - if (validationException.errors.stream() - .anyMatch(err -> err.type == OmexPythonUtils.OmexValidationErrorType.OMEX_VALIDATION_ERROR)){ - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.OMEX_VALIDATION_ERRORS) { - System.err.println("Expected error: "+e.getMessage()); - return; - }else{ - System.err.println("add SEDML_FAULT.OMEX_VALIDATION_ERRORS to "+test_case_name+": "+e.getMessage()); - } - } - } - if (e.getMessage()!=null && e.getMessage().contains("There are no models in ")){ - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.NO_MODELS_IN_OMEX) { - System.err.println("Expected error: "+e.getMessage()); - return; - }else{ - System.err.println("add SEDML_FAULT.NO_MODELS_IN_OMEX to "+test_case_name); - } - } - if (e.getMessage()!=null && e.getMessage().contains("expecting 1 biomodel in round trip")){ - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS) { - System.err.println("Expected error: "+e.getMessage()); - return; - }else{ - System.err.println("add SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS to "+test_case_name); - } - } - if (e.getMessage()!=null && e.getMessage().contains("Error constructing a new simulation context")) { - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.ERROR_CONSTRUCTING_SIMCONTEXT) { - System.err.println("Expected error: "+e.getMessage()); - return; - } else { - System.err.println("add SEDML_FAULT.ERROR_CONSTRUCTING_SIMCONTEXT to " + test_case_name); - } - } - if (e.getMessage()!=null && e.getMessage().contains("non-spatial stochastic simulation with histogram option to SEDML not supported")) { - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.NONSPATIAL_STOCH_HISTOGRAM) { - System.err.println("Expected error: "+e.getMessage()); - return; - } else { - System.err.println("add SEDML_FAULT.NONSPATIAL_STOCH_HISTOGRAM to " + test_case_name); - } - } - if (e.getMessage()!=null && e.getMessage().contains("math overrides not equivalent for simulation")) { - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT) { - System.err.println("Expected error: "+e.getMessage()); - return; - } else { - System.err.println("add SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT to " + test_case_name); - } - } - if (e.getMessage()!=null && e.getMessage().contains("math overrides names not equivalent for simulation")) { - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT) { - System.err.println("Expected error: "+e.getMessage()); - return; - } else { - System.err.println("add SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT to " + test_case_name); - } - } - if (e.getMessage()!=null && e.getMessage().contains("roundtripped simulationContext not found with name")) { - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME) { - System.err.println("Expected error: "+e.getMessage()); - return; - } else { - System.err.println("add SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME to " + test_case_name); - } - } - if (e.getMessage()!=null && e.getMessage().contains("roundtripped simulation not found with name")) { - if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME) { - System.err.println("Expected error: "+e.getMessage()); - return; - } else { - System.err.println("add SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME to " + test_case_name); - } - } - throw e; - } - } - -} +package org.vcell.sbml; + +import cbit.util.xml.XmlUtil; +import cbit.vcell.biomodel.BioModel; +import cbit.vcell.biomodel.ModelUnitConverter; +import cbit.vcell.mapping.SimulationContext; +import cbit.vcell.math.MathCompareResults; +import cbit.vcell.math.MathDescription; +import cbit.vcell.resource.NativeLib; +import cbit.vcell.solver.Simulation; +import cbit.vcell.solver.SimulationSymbolTable; +import cbit.vcell.solver.SolverDescription; +import cbit.vcell.xml.XMLSource; +import cbit.vcell.xml.XmlHelper; +import com.google.common.io.Files; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.vcell.sbml.vcell.SBMLExporter; +import org.vcell.sedml.*; + +import java.io.*; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public abstract class SEDMLExporterCommon { + + static class TestCase { + public final String filename; + public final ModelFormat modelFormat; + + public TestCase(String filename, ModelFormat modelFormat){ + this.filename = filename; + this.modelFormat = modelFormat; + } + } + + + final TestCase testCase; + + private static boolean bDebug = false; + + // + // save state for zero side-effect + // + private static String previousInstallDirPropertyValue; + private static String previousCliWorkDirPropertyValue; + private static boolean previousWriteDebugFiles; + + public SEDMLExporterCommon(TestCase testCase){ + this.testCase = testCase; + } + + public enum FAULT { + EXPRESSIONS_DIFFERENT, + EQUATION_REMOVED, + EXPRESSION_BINDING, + MATH_GENERATION_FAILURE, + MATHOVERRIDES_INVALID, + MATHOVERRIDES_SurfToVol, + MATHOVERRIDES_A_FUNCTION, + UNITS_EXCEPTION, + TOO_SLOW, + GEOMETRYSPEC_DIFFERENT, + NULL_POINTER_EXCEPTION, + UNKNOWN_IDENTIFIER, + SBML_IMPORT_FAILURE, + DIVIDE_BY_ZERO, + UNSUPPORTED_NONSPATIAL_STOCH_HISTOGRAM, + SEDML_UNSUPPORTED_ENTITY + }; + + public enum SEDML_FAULT { + DIFF_NUMBER_OF_BIOMODELS, + OMEX_PARSER_ERRORS, + OMEX_VALIDATION_ERRORS, + NO_MODELS_IN_OMEX, + ERROR_CONSTRUCTING_SIMCONTEXT, + NONSPATIAL_STOCH_HISTOGRAM, + MATH_OVERRIDE_NOT_EQUIVALENT, + MATH_OVERRIDE_NAMES_DIFFERENT, + SIMCONTEXT_NOT_FOUND_BY_NAME, + SIMULATION_NOT_FOUND_BY_NAME + }; + + @BeforeClass + public static void setup(){ + previousInstallDirPropertyValue = System.getProperty("vcell.installDir"); + previousCliWorkDirPropertyValue = System.getProperty("cli.workingDir"); + System.setProperty("vcell.installDir", ".."); + System.setProperty("cli.workingDir", System.getProperty("vcell.installDir") + "/vcell-cli-utils"); + NativeLib.combinej.load(); + previousWriteDebugFiles = SBMLExporter.bWriteDebugFiles; + SBMLExporter.bWriteDebugFiles = bDebug; + } + + @AfterClass + public static void teardown() throws IOException { + if (previousInstallDirPropertyValue !=null) { + System.setProperty("vcell.installDir", previousInstallDirPropertyValue); + } + if (previousCliWorkDirPropertyValue != null){ + System.setProperty("cli.workingDir", previousCliWorkDirPropertyValue); + } + SBMLExporter.bWriteDebugFiles = previousWriteDebugFiles; + } + + /** + * each file in largeFileSet is > 500K on disk and is not included in the test suite. + * @return + */ + public static Set largeFileSet() { + Set largeFiles = new HashSet<>(); + largeFiles.add("biomodel_101963252.vcml"); + return largeFiles; + } + + /** + * each file in the knownFaultsMap hold known problems in the current software + */ + abstract Map knownFaults(); + + + abstract Map knownSEDMLFaults(); + + + void sedml_roundtrip_common() throws Exception { + String test_case_name = testCase.modelFormat+"."+testCase.filename; + InputStream testFileInputStream = VcmlTestSuiteFiles.getVcmlTestCase(testCase.filename); + String vcmlStr = new BufferedReader(new InputStreamReader(testFileInputStream)) + .lines().collect(Collectors.joining("\n")); + + BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(vcmlStr)); + + bioModel.updateAll(false); + + Predicate simulationExportFilter = sim -> true; + List simsToExport = Arrays.stream(bioModel.getSimulations()).filter(simulationExportFilter).collect(Collectors.toList()); + + // we replace the obsolete solver with the fully supported equivalent + for (Simulation simulation : simsToExport) { + if (simulation.getSolverTaskDescription().getSolverDescription().equals(SolverDescription.FiniteVolume)) { + simulation.getSolverTaskDescription().setSolverDescription(SolverDescription.SundialsPDE); + } + } + File outputDir = Files.createTempDir(); + String jsonFullyQualifiedName = new File(outputDir, test_case_name + ".json").getAbsolutePath(); + System.out.println(jsonFullyQualifiedName); + + boolean bHasPython = true; + boolean bRoundTripSBMLValidation = true; + boolean bWriteOmexArchive = true; + File omexFile = new File(outputDir, test_case_name + ".omex"); + Optional publicationMetadata = Optional.empty(); + Map unsupportedApplications = SEDMLExporter.getUnsupportedApplicationMap(bioModel, testCase.modelFormat); + Predicate simContextFilter = (SimulationContext sc) -> !unsupportedApplications.containsKey(sc.getName()); + try { + List sedmlTaskRecords = SEDMLExporter.writeBioModel( + bioModel, publicationMetadata, omexFile, testCase.modelFormat, simContextFilter, bHasPython, bRoundTripSBMLValidation, bWriteOmexArchive); + + boolean bAnyFailures = false; + for (SEDMLTaskRecord sedmlTaskRecord : sedmlTaskRecords) { + boolean bFailed = false; + switch (sedmlTaskRecord.getTaskType()) { + case BIOMODEL: { + break; + } + case SIMCONTEXT: { + bFailed = sedmlTaskRecord.getTaskResult() == TaskResult.FAILED && + (sedmlTaskRecord.getException() == null || !sedmlTaskRecord.getException().getClass().equals(UnsupportedSbmlExportException.class)); + break; + } + case UNITS: + case SIMULATION: { + bFailed = sedmlTaskRecord.getTaskResult() == TaskResult.FAILED; + break; + } + } + bAnyFailures |= bFailed; + if (!knownFaults().containsKey(testCase.filename)) { + // skip assert if the model is known to have a problem + Assert.assertFalse(sedmlTaskRecord.getCSV(), bFailed); + } + } + FAULT knownFault = knownFaults().get(testCase.filename); + if (knownFault != null){ + // if in the knownFaults list, the model should fail + // this is how we can keep track of our list of known problems + // if we fix a model without removing it from the knownFaults map, then this test will fail + Assert.assertTrue( + "expecting fault "+knownFault.name()+" in "+test_case_name+" but it passed, Please remove from SEDMLExporterTest.knownFaults()", + bAnyFailures); + } + + if (testCase.modelFormat == ModelFormat.VCML){ + System.err.println("skipping re-importing SEDML for this test case, not yet supported for VCML"); + return; + } + SBMLExporter.MemoryVCLogger memoryVCLogger = new SBMLExporter.MemoryVCLogger(); + List bioModels = XmlHelper.readOmex(omexFile, memoryVCLogger); + Assert.assertTrue(memoryVCLogger.highPriority.size() == 0); + + File tempDir = Files.createTempDir(); + String origVcmlPath = new File(tempDir, "orig.vcml").getAbsolutePath(); + XmlUtil.writeXMLStringToFile(XmlHelper.bioModelToXML(bioModel), origVcmlPath, true); + + if (bDebug) { + SBMLExporter.bWriteDebugFiles=true; + for (int i = 0; i < bioModels.size(); i++) { + String rereadVcmlPath = new File(tempDir, "reread_" + i + ".vcml").getAbsolutePath(); + XmlUtil.writeXMLStringToFile(XmlHelper.bioModelToXML(bioModels.get(i)), rereadVcmlPath, true); + } + System.err.println("wrote original and final BioModel VCML files to " + tempDir.getAbsolutePath()); + } + + Assert.assertEquals("expecting 1 biomodel in round trip", 1, bioModels.size()); + BioModel importedBioModel = bioModels.get(0); + + boolean hasAnyOverrides = Arrays.stream(bioModel.getSimulations()).anyMatch(s -> s.getMathOverrides().getSize() > 0); + if (testCase.modelFormat == ModelFormat.SBML && hasAnyOverrides){ + importedBioModel = ModelUnitConverter.createBioModelWithNewUnitSystem(importedBioModel, bioModel.getModel().getUnitSystem()); + } + + // + // compare Math Overrides for each simulation + // + for (Simulation simToExport : simsToExport){ + SimulationContext simContextToExport = bioModel.getSimulationContext(simToExport); + String simContextName = simContextToExport.getName(); + String simName = simToExport.getName(); + SimulationContext simContextRoundTripped = importedBioModel.getSimulationContext(simContextName); + Assert.assertNotNull("roundtripped simulationContext not found with name '"+simContextName+"'", simContextRoundTripped); + Simulation simRoundTripped = simContextRoundTripped.getSimulation(simName); + Assert.assertNotNull("roundtripped simulation not found with name '"+simName+"'", simRoundTripped); + boolean mathOverrideEquiv = simToExport.getMathOverrides().compareEquivalent(simRoundTripped.getMathOverrides()); + if (!mathOverrideEquiv){ + // + // math overrides didn't compare as equivalent, if overridden names are different, try substituting into math and comparing math + // + List oldOverrideNames = Arrays.stream(simToExport.getMathOverrides().getOverridenConstantNames()).sorted().collect(Collectors.toList()); + List newOverrideNames = Arrays.stream(simRoundTripped.getMathOverrides().getOverridenConstantNames()).sorted().collect(Collectors.toList()); + if (!oldOverrideNames.equals(newOverrideNames) && (simToExport.getScanCount() == simRoundTripped.getScanCount())){ + // simulation scan counts are the same, but overridden constants have different names, try substituting them into the math and compare the maths. + System.out.println("old names: "+oldOverrideNames+", new names: "+newOverrideNames); + for (int simJobIndex=0; simJobIndex < simToExport.getScanCount(); simJobIndex++){ + MathDescription oldMathDescription = new SimulationSymbolTable(simToExport, simJobIndex).getMathDescription(); + MathDescription newMathDescription = new SimulationSymbolTable(simRoundTripped, simJobIndex).getMathDescription(); + MathCompareResults subCompareResults = MathDescription.testEquivalency( + SimulationSymbolTable.createMathSymbolTableFactory(), oldMathDescription, newMathDescription); + Assert.assertTrue("math overrides names not equivalent for simulation '"+simName+"' " + + "in simContext '"+simContextName+"'", subCompareResults.isEquivalent()); + mathOverrideEquiv = true; + } + } + } + Assert.assertTrue("math overrides not equivalent for simulation '"+simName+"' in simContext '"+simContextName+"'", mathOverrideEquiv); + } + + Assert.assertNull("file "+test_case_name+" passed SEDML Round trip, but knownSEDMLFault was set", knownSEDMLFaults().get(testCase.filename)); + }catch (Exception | AssertionError e){ + if (e instanceof OmexPythonUtils.OmexValidationException){ + OmexPythonUtils.OmexValidationException validationException = (OmexPythonUtils.OmexValidationException) e; + if (validationException.errors.stream() + .anyMatch(err -> err.type == OmexPythonUtils.OmexValidationErrorType.OMEX_PARSE_ERROR)){ + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.OMEX_PARSER_ERRORS) { + System.err.println("Expected error: "+e.getMessage()); + return; + }else{ + System.err.println("add SEDML_FAULT.OMEX_PARSER_ERRORS to "+test_case_name+": "+e.getMessage()); + } + } + if (validationException.errors.stream() + .anyMatch(err -> err.type == OmexPythonUtils.OmexValidationErrorType.OMEX_VALIDATION_ERROR)){ + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.OMEX_VALIDATION_ERRORS) { + System.err.println("Expected error: "+e.getMessage()); + return; + }else{ + System.err.println("add SEDML_FAULT.OMEX_VALIDATION_ERRORS to "+test_case_name+": "+e.getMessage()); + } + } + } + if (e.getMessage()!=null && e.getMessage().contains("There are no models in ")){ + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.NO_MODELS_IN_OMEX) { + System.err.println("Expected error: "+e.getMessage()); + return; + }else{ + System.err.println("add SEDML_FAULT.NO_MODELS_IN_OMEX to "+test_case_name); + } + } + if (e.getMessage()!=null && e.getMessage().contains("expecting 1 biomodel in round trip")){ + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS) { + System.err.println("Expected error: "+e.getMessage()); + return; + }else{ + System.err.println("add SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS to "+test_case_name); + } + } + if (e.getMessage()!=null && e.getMessage().contains("Error constructing a new simulation context")) { + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.ERROR_CONSTRUCTING_SIMCONTEXT) { + System.err.println("Expected error: "+e.getMessage()); + return; + } else { + System.err.println("add SEDML_FAULT.ERROR_CONSTRUCTING_SIMCONTEXT to " + test_case_name); + } + } + if (e.getMessage()!=null && e.getMessage().contains("non-spatial stochastic simulation with histogram option to SEDML not supported")) { + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.NONSPATIAL_STOCH_HISTOGRAM) { + System.err.println("Expected error: "+e.getMessage()); + return; + } else { + System.err.println("add SEDML_FAULT.NONSPATIAL_STOCH_HISTOGRAM to " + test_case_name); + } + } + if (e.getMessage()!=null && e.getMessage().contains("math overrides not equivalent for simulation")) { + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT) { + System.err.println("Expected error: "+e.getMessage()); + return; + } else { + System.err.println("add SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT to " + test_case_name); + } + } + if (e.getMessage()!=null && e.getMessage().contains("math overrides names not equivalent for simulation")) { + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT) { + System.err.println("Expected error: "+e.getMessage()); + return; + } else { + System.err.println("add SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT to " + test_case_name); + } + } + if (e.getMessage()!=null && e.getMessage().contains("roundtripped simulationContext not found with name")) { + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME) { + System.err.println("Expected error: "+e.getMessage()); + return; + } else { + System.err.println("add SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME to " + test_case_name); + } + } + if (e.getMessage()!=null && e.getMessage().contains("roundtripped simulation not found with name")) { + if (knownSEDMLFaults().get(testCase.filename) == SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME) { + System.err.println("Expected error: "+e.getMessage()); + return; + } else { + System.err.println("add SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME to " + test_case_name); + } + } + throw e; + } + } + +} diff --git a/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterNightlyRoundTrip.java b/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterNightlyRoundTrip.java new file mode 100644 index 0000000000..9117a0e0d0 --- /dev/null +++ b/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterNightlyRoundTrip.java @@ -0,0 +1,374 @@ +package org.vcell.sbml; + +import cbit.util.xml.XmlUtil; +import cbit.vcell.biomodel.BioModel; +import cbit.vcell.biomodel.ModelUnitConverter; +import cbit.vcell.mapping.SimulationContext; +import cbit.vcell.math.MathCompareResults; +import cbit.vcell.math.MathDescription; +import cbit.vcell.resource.NativeLib; +import cbit.vcell.solver.Simulation; +import cbit.vcell.solver.SimulationSymbolTable; +import cbit.vcell.solver.SolverDescription; +import cbit.vcell.xml.XMLSource; +import cbit.vcell.xml.XmlHelper; +import com.google.common.io.Files; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.vcell.sbml.vcell.SBMLExporter; +import org.vcell.sedml.*; + +import java.io.*; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public abstract class SEDMLExporterNightlyRoundTrip { + + static class TestCase { + public final File VCML; + public final ModelFormat modelFormat; + + public TestCase(File VCML, ModelFormat modelFormat){ + this.VCML = VCML; + this.modelFormat = modelFormat; + } + } + + + final protected TestCase testCase; + private static boolean bDebug = false; + + // + // save state for zero side effects + // + protected static String locationOfVcmlToTest; + private static String previousInstallDirPropertyValue; + private static String previousCliWorkDirPropertyValue; + private static boolean previousWriteDebugFiles; + + public SEDMLExporterNightlyRoundTrip(TestCase testCase){ + this.testCase = testCase; + } + + public enum FAULT { + EXPRESSIONS_DIFFERENT, + EQUATION_REMOVED, + EXPRESSION_BINDING, + MATH_GENERATION_FAILURE, + MATHOVERRIDES_INVALID, + MATHOVERRIDES_SurfToVol, + MATHOVERRIDES_A_FUNCTION, + UNITS_EXCEPTION, + TOO_SLOW, + GEOMETRYSPEC_DIFFERENT, + NULL_POINTER_EXCEPTION, + UNKNOWN_IDENTIFIER, + SBML_IMPORT_FAILURE, + DIVIDE_BY_ZERO, + UNSUPPORTED_NONSPATIAL_STOCH_HISTOGRAM, + SEDML_UNSUPPORTED_ENTITY, + UNKNOWN_FAULT_OCCURRED + + }; + + public enum SEDML_FAULT { + DIFF_NUMBER_OF_BIOMODELS, + OMEX_PARSER_ERRORS, + OMEX_VALIDATION_ERRORS, + NO_MODELS_IN_OMEX, + ERROR_CONSTRUCTING_SIMCONTEXT, + NONSPATIAL_STOCH_HISTOGRAM, + MATH_OVERRIDE_NOT_EQUIVALENT, + MATH_OVERRIDE_NAMES_DIFFERENT, + SIMCONTEXT_NOT_FOUND_BY_NAME, + SIMULATION_NOT_FOUND_BY_NAME, + UNKNOWN_SEDML_FAULT_OCCURRED + }; + + @BeforeClass + public static void setup(){ + previousInstallDirPropertyValue = System.getProperty("vcell.installDir"); + previousCliWorkDirPropertyValue = System.getProperty("cli.workingDir"); + System.setProperty("vcell.installDir", ".."); + System.setProperty("cli.workingDir", System.getProperty("vcell.installDir") + "/vcell-cli-utils"); + NativeLib.combinej.load(); + previousWriteDebugFiles = SBMLExporter.bWriteDebugFiles; + SBMLExporter.bWriteDebugFiles = bDebug; + } + + @AfterClass + public static void teardown() throws IOException { + if (previousInstallDirPropertyValue !=null) { + System.setProperty("vcell.installDir", previousInstallDirPropertyValue); + } + if (previousCliWorkDirPropertyValue != null){ + System.setProperty("cli.workingDir", previousCliWorkDirPropertyValue); + } + SBMLExporter.bWriteDebugFiles = previousWriteDebugFiles; + } + + /** + * each file in largeFileSet is > 500K on disk and is not included in the test suite. + * @return + */ + public static Set largeFileSet() { + Set largeFiles = new HashSet<>(); + largeFiles.add("biomodel_101963252.vcml"); + return largeFiles; + } + + /** + * each file in the knownFaultsMap hold known problems in the current software + */ + abstract Map knownFaults(); + + + abstract Map knownSEDMLFaults(); + + + void sedml_roundtrip_common() throws Exception { + String test_case_name = testCase.modelFormat + "." + testCase.VCML.getName(); + String vcmlStr; + try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(testCase.VCML)))){ + vcmlStr = br.lines().collect(Collectors.joining("\n")); + } + + BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(vcmlStr)); + bioModel.updateAll(false); + + Predicate simulationExportFilter = sim -> true; + List simsToExport = Arrays.stream(bioModel.getSimulations()).filter(simulationExportFilter).collect(Collectors.toList()); + + // we replace the obsolete solver with the fully supported equivalent + for (Simulation simulation : simsToExport) { + if (simulation.getSolverTaskDescription().getSolverDescription().equals(SolverDescription.FiniteVolume)) { + simulation.getSolverTaskDescription().setSolverDescription(SolverDescription.SundialsPDE); + } + } + File outputDir = Files.createTempDir(); + String jsonFullyQualifiedName = new File(outputDir, test_case_name + ".json").getAbsolutePath(); + System.out.println(jsonFullyQualifiedName); + + boolean bHasPython = true; + boolean bRoundTripSBMLValidation = true; + boolean bWriteOmexArchive = true; + File omexFile = new File(outputDir, test_case_name + ".omex"); + Optional publicationMetadata = Optional.empty(); + Map unsupportedApplications = SEDMLExporter.getUnsupportedApplicationMap(bioModel, testCase.modelFormat); + Predicate simContextFilter = (SimulationContext sc) -> !unsupportedApplications.containsKey(sc.getName()); + try { + List sedmlTaskRecords = SEDMLExporter.writeBioModel( + bioModel, publicationMetadata, omexFile, testCase.modelFormat, simContextFilter, bHasPython, bRoundTripSBMLValidation, bWriteOmexArchive); + + boolean bAnyFailures = false; + for (SEDMLTaskRecord sedmlTaskRecord : sedmlTaskRecords) { + boolean bFailed = false; + switch (sedmlTaskRecord.getTaskType()) { + case BIOMODEL: { + break; + } + case SIMCONTEXT: { + bFailed = sedmlTaskRecord.getTaskResult() == TaskResult.FAILED && + (sedmlTaskRecord.getException() == null || !sedmlTaskRecord.getException().getClass().equals(UnsupportedSbmlExportException.class)); + break; + } + case UNITS: + case SIMULATION: { + bFailed = sedmlTaskRecord.getTaskResult() == TaskResult.FAILED; + break; + } + } + bAnyFailures |= bFailed; + if (!knownFaults().containsKey(testCase.VCML.getName())) { + // skip assert if the model is known to have a problem + Assert.assertFalse(sedmlTaskRecord.getCSV(), bFailed); + } + } + FAULT knownFault = knownFaults().get(testCase.VCML.getName()); + if (knownFault != null){ + // if in the knownFaults list, the model should fail + // this is how we can keep track of our list of known problems + // if we fix a model without removing it from the knownFaults map, then this test will fail + Assert.assertTrue( + "expecting fault "+knownFault.name()+" in "+test_case_name+" but it passed, Please remove from SEDMLExporterTest.knownFaults()", + bAnyFailures); + } + + if (testCase.modelFormat == ModelFormat.VCML){ + System.err.println("skipping re-importing SEDML for this test case, not yet supported for VCML"); + return; + } + SBMLExporter.MemoryVCLogger memoryVCLogger = new SBMLExporter.MemoryVCLogger(); + List bioModels = XmlHelper.readOmex(omexFile, memoryVCLogger); + Assert.assertTrue(memoryVCLogger.highPriority.size() == 0); + + File tempDir = Files.createTempDir(); + String origVcmlPath = new File(tempDir, "orig.vcml").getAbsolutePath(); + XmlUtil.writeXMLStringToFile(XmlHelper.bioModelToXML(bioModel), origVcmlPath, true); + + if (bDebug) { + SBMLExporter.bWriteDebugFiles=true; + for (int i = 0; i < bioModels.size(); i++) { + String rereadVcmlPath = new File(tempDir, "reread_" + i + ".vcml").getAbsolutePath(); + XmlUtil.writeXMLStringToFile(XmlHelper.bioModelToXML(bioModels.get(i)), rereadVcmlPath, true); + } + System.err.println("wrote original and final BioModel VCML files to " + tempDir.getAbsolutePath()); + } + + Assert.assertEquals("expecting 1 biomodel in round trip", 1, bioModels.size()); + BioModel importedBioModel = bioModels.get(0); + + boolean hasAnyOverrides = Arrays.stream(bioModel.getSimulations()).anyMatch(s -> s.getMathOverrides().getSize() > 0); + if (testCase.modelFormat == ModelFormat.SBML && hasAnyOverrides){ + importedBioModel = ModelUnitConverter.createBioModelWithNewUnitSystem(importedBioModel, bioModel.getModel().getUnitSystem()); + } + + // + // compare Math Overrides for each simulation + // + for (Simulation simToExport : simsToExport){ + SimulationContext simContextToExport = bioModel.getSimulationContext(simToExport); + String simContextName = simContextToExport.getName(); + String simName = simToExport.getName(); + SimulationContext simContextRoundTripped = importedBioModel.getSimulationContext(simContextName); + Assert.assertNotNull("roundtripped simulationContext not found with name '"+simContextName+"'", simContextRoundTripped); + Simulation simRoundTripped = simContextRoundTripped.getSimulation(simName); + Assert.assertNotNull("roundtripped simulation not found with name '"+simName+"'", simRoundTripped); + boolean mathOverrideEquiv = simToExport.getMathOverrides().compareEquivalent(simRoundTripped.getMathOverrides()); + if (!mathOverrideEquiv){ + // + // math overrides didn't compare as equivalent, if overridden names are different, try substituting into math and comparing math + // + List oldOverrideNames = Arrays.stream(simToExport.getMathOverrides().getOverridenConstantNames()).sorted().collect(Collectors.toList()); + List newOverrideNames = Arrays.stream(simRoundTripped.getMathOverrides().getOverridenConstantNames()).sorted().collect(Collectors.toList()); + if (!oldOverrideNames.equals(newOverrideNames) && (simToExport.getScanCount() == simRoundTripped.getScanCount())){ + // simulation scan counts are the same, but overridden constants have different names, try substituting them into the math and compare the maths. + System.out.println("old names: "+oldOverrideNames+", new names: "+newOverrideNames); + for (int simJobIndex=0; simJobIndex < simToExport.getScanCount(); simJobIndex++){ + MathDescription oldMathDescription = new SimulationSymbolTable(simToExport, simJobIndex).getMathDescription(); + MathDescription newMathDescription = new SimulationSymbolTable(simRoundTripped, simJobIndex).getMathDescription(); + MathCompareResults subCompareResults = MathDescription.testEquivalency( + SimulationSymbolTable.createMathSymbolTableFactory(), oldMathDescription, newMathDescription); + Assert.assertTrue("math overrides names not equivalent for simulation '"+simName+"' " + + "in simContext '"+simContextName+"'", subCompareResults.isEquivalent()); + mathOverrideEquiv = true; + } + } + } + Assert.assertTrue("math overrides not equivalent for simulation '"+simName+"' in simContext '"+simContextName+"'", mathOverrideEquiv); + } + + Assert.assertNull("file "+test_case_name+" passed SEDML Round trip, but knownSEDMLFault was set", knownSEDMLFaults().get(testCase.VCML.getName())); + } catch (Exception | AssertionError e){ + RoundTripException curatedException = new RoundTripException(false, SEDML_FAULT.UNKNOWN_SEDML_FAULT_OCCURRED); + if (e instanceof OmexPythonUtils.OmexValidationException){ + OmexPythonUtils.OmexValidationException validationException = (OmexPythonUtils.OmexValidationException) e; + if (validationException.errors.stream() + .anyMatch(err -> err.type == OmexPythonUtils.OmexValidationErrorType.OMEX_PARSE_ERROR)){ + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.OMEX_PARSER_ERRORS) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.OMEX_PARSER_ERRORS); + }else{ + String message = "add SEDML_FAULT.OMEX_PARSER_ERRORS to " + test_case_name + ": " + e.getMessage(); + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.OMEX_PARSER_ERRORS); + } + } + if (validationException.errors.stream() + .anyMatch(err -> err.type == OmexPythonUtils.OmexValidationErrorType.OMEX_VALIDATION_ERROR)){ + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.OMEX_VALIDATION_ERRORS) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.OMEX_VALIDATION_ERRORS); + }else{ + String message = "add SEDML_FAULT.OMEX_VALIDATION_ERRORS to " + test_case_name + ": " + e.getMessage(); + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.OMEX_VALIDATION_ERRORS); + } + } + } + if (e.getMessage()!=null && e.getMessage().contains("There are no models in ")){ + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.NO_MODELS_IN_OMEX) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.NO_MODELS_IN_OMEX); + }else{ + String message = "add SEDML_FAULT.NO_MODELS_IN_OMEX to " + test_case_name; + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.NO_MODELS_IN_OMEX); + } + } + if (e.getMessage()!=null && e.getMessage().contains("expecting 1 biomodel in round trip")){ + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS); + }else{ + String message = "add SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS to " + test_case_name; + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS); + } + } + if (e.getMessage()!=null && e.getMessage().contains("Error constructing a new simulation context")) { + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.ERROR_CONSTRUCTING_SIMCONTEXT) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.ERROR_CONSTRUCTING_SIMCONTEXT); + } else { + String message = "add SEDML_FAULT.ERROR_CONSTRUCTING_SIMCONTEXT to " + test_case_name; + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.ERROR_CONSTRUCTING_SIMCONTEXT); + } + } + if (e.getMessage()!=null && e.getMessage().contains("non-spatial stochastic simulation with histogram option to SEDML not supported")) { + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.NONSPATIAL_STOCH_HISTOGRAM) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.NONSPATIAL_STOCH_HISTOGRAM); + } else { + String message = "add SEDML_FAULT.NONSPATIAL_STOCH_HISTOGRAM to " + test_case_name; + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.NONSPATIAL_STOCH_HISTOGRAM); + } + } + if (e.getMessage()!=null && e.getMessage().contains("math overrides not equivalent for simulation")) { + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); + } else { + String message = "add SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT to " + test_case_name; + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); + } + } + if (e.getMessage()!=null && e.getMessage().contains("math overrides names not equivalent for simulation")) { + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); + } else { + String message = "add SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT to " + test_case_name; + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); + } + } + if (e.getMessage()!=null && e.getMessage().contains("roundtripped simulationContext not found with name")) { + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); + } else { + String message = "add SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME to " + test_case_name; + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); + } + } + if (e.getMessage()!=null && e.getMessage().contains("roundtripped simulation not found with name")) { + if (knownSEDMLFaults().get(testCase.VCML.getName()) == SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME) { + System.err.println("Expected error: " + e.getMessage()); + curatedException = new RoundTripException(e, true, SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); + } else { + String message = "add SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME to " + test_case_name; + System.err.println(message); + curatedException = new RoundTripException(message, e, false, SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); + } + } + throw curatedException; + } + } +} diff --git a/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterNightlyRoundTripSBMLTest.java b/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterNightlyRoundTripSBMLTest.java new file mode 100644 index 0000000000..8d455226b1 --- /dev/null +++ b/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterNightlyRoundTripSBMLTest.java @@ -0,0 +1,244 @@ +package org.vcell.sbml; + +import cbit.vcell.resource.NativeLib; +import cbit.vcell.resource.PropertyLoader; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.vcell.sbml.vcell.SBMLExporter; +import org.vcell.sedml.ModelFormat; +import org.vcell.test.RoundTrip; + +import java.io.*; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@RunWith(Parameterized.class) +@Category({RoundTrip.class}) +public class SEDMLExporterNightlyRoundTripSBMLTest extends SEDMLExporterNightlyRoundTrip { + + private final static String RESULTS_FILE_NAME = "rawRoundTripResults.txt"; + private static RoundTripStatistics resultsStatistics; + + @BeforeClass + public static void setup(){ + SEDMLExporterNightlyRoundTrip.setup(); + SEDMLExporterNightlyRoundTripSBMLTest.resultsStatistics = new RoundTripStatistics(); + } + + @AfterClass + public static void teardown() throws IOException { + Path resultsPath = Paths.get(PropertyLoader.getProperty( + PropertyLoader.vcellVcmlLocation, System.getProperty("user.home")), "results" , RESULTS_FILE_NAME); + if (!(resultsPath.getParent().toFile().exists() && resultsPath.getParent().toFile().isDirectory())){ + resultsPath.getParent().toFile().mkdirs(); + } + try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(resultsPath.toString()))){ + SEDMLExporterNightlyRoundTripSBMLTest.resultsStatistics.exportResultsToWriter(bufferedWriter); + } catch (IOException e){ + throw new RuntimeException("Unable to open results file writer.", e); + } + SEDMLExporterNightlyRoundTrip.teardown(); + } + + public SEDMLExporterNightlyRoundTripSBMLTest(TestCase testCase){ + super(testCase); + } + + @Override + Map knownFaults() { + HashMap faults = new HashMap<>(); + faults.put("biomodel_123269393.vcml", FAULT.MATHOVERRIDES_INVALID); // Kf_r7 - biomodel needs fixing - MathOverrides has entry for non-existent parameter Kf_r7 + faults.put("biomodel_124562627.vcml", FAULT.NULL_POINTER_EXCEPTION); // CSG/analytic geometry issue - SBML model does not have any geometryDefinition. Cannot proceed with import + faults.put("biomodel_156134818.vcml", FAULT.UNKNOWN_IDENTIFIER); // species named 'I' conflicts with membrane parameter I - Unable to sort, unknown identifier I_Gs_GDI_accel_deg_copy6 + faults.put("biomodel_220138948.vcml", FAULT.MATHOVERRIDES_INVALID); // Kf_Uptake invalid override - MathOverrides has entry for non-existent parameter Kf_Uptake + faults.put("biomodel_84982474.vcml", FAULT.UNSUPPORTED_NONSPATIAL_STOCH_HISTOGRAM); // not supported nonspatial histogram + + + return faults; + } + + @Override + Map knownSEDMLFaults() { + HashMap faults = new HashMap<>(); + faults.put("__export_adv_test.vcml", SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); // round-tripped simulation not found with name 'spatialnoscan' + faults.put("biomodel_100596964.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_100961371.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_113655498.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_116929912.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_116929971.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_116930032.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_123269393.vcml", SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); // round-tripped simulation not found with name 'Simulation2' + faults.put("biomodel_123465498.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_123465505.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_124562627.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_12522025.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Simulation 1' in simContext 'purkinje9-ss' + faults.put("biomodel_13717231.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'double -' + faults.put("biomodel_13736736.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_145545992.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_148700996.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Full sim' in simContext 'Fast B Compartmental' + faults.put("biomodel_154961582.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_155016832.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_156134818.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_16763273.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_16804037.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_168717401.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_169993006.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_17098642.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_17257105.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation '1 uM iso' in simContext 'compartmental' + faults.put("biomodel_188880263.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_18894555.vcml", SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); // simulation 'baseline' in simContext 'compartmental' + faults.put("biomodel_189321805.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new + faults.put("biomodel_189512756.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_189513183.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_20253928.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_211839191.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_220138948.vcml", SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); // round-tripped simulation not found with name 'Uptake_Larger Jumps' + faults.put("biomodel_22403233.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403238.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403244.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403250.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403358.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403576.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_225440511.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_232498815.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2912851.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2913730.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2915537.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2917738.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2917788.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2917999.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2930915.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2962862.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_32568171.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_32568356.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_34826524.vcml", SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); // simulation 'Cap=1, cof, prof varied' in simContext 'Steady State Turnover' + faults.put("biomodel_34855932.vcml", SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); // simulation 'INIT' in simContext 'cell4' + faults.put("biomodel_38086434.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new + faults.put("biomodel_55178308.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new + faults.put("biomodel_55396830.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_59280306.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation '1 uM iso' in simContext 'compartmental' + faults.put("biomodel_60203358.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_60227051.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_63307133.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_65311813.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // simulation 'Copy of Simulation 101x101x36' in simContext '3d image' + faults.put("biomodel_66264973.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Simulation - local sequestration' in simContext 'compartmental - IC-G2736X' + faults.put("biomodel_66265579.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_74924130.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Simulation0' in simContext 'Application0' + faults.put("biomodel_77305266.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_7803961.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_7803976.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_81284732.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_82250339.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_83446023.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // can't find math override for Kf_dimerization + faults.put("biomodel_83462243.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'spatial-hybrid' + faults.put("biomodel_83651737.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); + faults.put("biomodel_84982474.vcml", SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS); // not supported non-spatial histogram + faults.put("biomodel_9254662.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_92705462.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'stoch' + faults.put("biomodel_97075423.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_97705317.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_97786619.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_97786886.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'hybrid' + faults.put("biomodel_97787114.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'hybrid' + faults.put("biomodel_98147638.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_98150237.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new + faults.put("biomodel_98174143.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_98296160.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_98730962.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'Application0' + faults.put("biomodel_165181964.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + + + // SEDML Validator Errors + faults.put("biomodel_82065439.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // NON_UNIQUE_IDS: Each identified SED object must have a unique id. Multiple objects have the following ids:",[["compartmental"]] + faults.put("biomodel_220138948.vcml",SEDML_FAULT.OMEX_VALIDATION_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='OAT1']/@initialConcentration` does not match any elements of model `_0D`. + faults.put("biomodel_31523791.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='cAMP_Intracellular']/@initialConcentration` does not match any elements of model `Dose_response`. + faults.put("biomodel_34855932.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='Kf_GPCR_to_ICSC']/@value` does not match any elements of model `cell5` + faults.put("biomodel_40882931.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='ZO1staticF_PM']/@initialConcentration` does not match any elements of model `_3d_image` + faults.put("biomodel_40883509.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='PIK_PM']/@initialConcentration` does not match any elements of model `_3d_image` + faults.put("biomodel_65311813.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='Ran_nuc_diff']/@value` does not match any elements of model `_3d_image_0` + return faults; + } + @Parameterized.Parameters + public static Collection testCases() { + File testResourceDir; + + try { + PropertyLoader.loadProperties(new String[]{PropertyLoader.vcellVcmlLocation}); + } catch (IOException e){ + throw new RuntimeException("Error loading properties", e); + } + + // Check that the env var for the input directory has been set. + SEDMLExporterNightlyRoundTrip.locationOfVcmlToTest = PropertyLoader.getProperty(PropertyLoader.vcellVcmlLocation, null); + if (SEDMLExporterNightlyRoundTrip.locationOfVcmlToTest == null) + throw new RuntimeException( + String.format("Please set the `%s` system property with the path to the input file directory", + PropertyLoader.vcellVcmlLocation)); + + // Input validate the property's value + try { + testResourceDir = (new File(SEDMLExporterNightlyRoundTrip.locationOfVcmlToTest)).getCanonicalFile(); + } catch (IOException e){ + String message = String.format("Unable to determine the canonical path to provided directory `%s`.\n" + + "\tPlease check that the `%s` system property has been set properly", + SEDMLExporterNightlyRoundTrip.locationOfVcmlToTest, PropertyLoader.vcellVcmlLocation); + throw new RuntimeException(message, e); + } + // Validate the status of the input directory as a valid directory full of VCMLs + if (!testResourceDir.isDirectory()) throw new RuntimeException( + String.format("Path `%s` provided by property `%s` is not a directory", testResourceDir.getPath(), + PropertyLoader.vcellVcmlLocation)); + + // Prepare Filtering + FilenameFilter exemptFilesFilter = new NightlyRoundTripVCMLFilenameFilter(); + Predicate skipFilter_VCML = (t) -> exemptFilesFilter.accept(testResourceDir, t); + + // Collect Filenames to test with. + File[] filenamesToTest = testResourceDir.listFiles(exemptFilesFilter); + Stream vcmlTestCases = Arrays.stream(filenamesToTest).map(file -> new TestCase(file, ModelFormat.SBML)); + + //Stream sbml_test_cases = Arrays.stream(VcmlTestSuiteFiles.getVcmlTestCases()).filter(skipFilter_VCML).map(fName -> new TestCase(fName, ModelFormat.SBML)); + //return sbml_test_cases.collect(Collectors.toList()); + return vcmlTestCases.collect(Collectors.toList()); +// return Arrays.asList( +// new TestCase("biomodel_31523791.vcml", ModelFormat.SBML), +// new TestCase("biomodel_34855932.vcml", ModelFormat.SBML), +// new TestCase("biomodel_40882931.vcml", ModelFormat.SBML), +// new TestCase("biomodel_40883509.vcml", ModelFormat.SBML), +// new TestCase("biomodel_65311813.vcml", ModelFormat.SBML), +// new TestCase("biomodel_82065439.vcml", ModelFormat.SBML) +// ); + } + + @Test + public void test_sedml_roundtrip_SBML() throws Exception { + if (knownFaults().containsKey(testCase.VCML.getName())) { + return; // skip known faults + } +// if (knownSEDMLFaults().get(testCase.filename) != SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT +// && knownSEDMLFaults().get(testCase.filename) != SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT){ +// return; +// } + + try { + sedml_roundtrip_common(); + resultsStatistics.recordSuccessResult(); + } catch (RoundTripException e){ + resultsStatistics.recordFailureResult(e); + if (e.wasTheExpectedResult) return; + throw e; + } catch (Exception e){ + RoundTripException curatedException = new RoundTripException(e, false, SEDML_FAULT.UNKNOWN_SEDML_FAULT_OCCURRED); + resultsStatistics.recordFailureResult(curatedException); + throw curatedException; + } + } +} diff --git a/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterSBMLTest.java b/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterSBMLTest.java index 9b8fef2488..d6a1f96a0b 100644 --- a/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterSBMLTest.java +++ b/vcell-core/src/test/java/org/vcell/sbml/SEDMLExporterSBMLTest.java @@ -1,204 +1,210 @@ -package org.vcell.sbml; - -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.vcell.sedml.ModelFormat; -import org.vcell.test.SEDML_SBML_IT; - -import java.util.*; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@RunWith(Parameterized.class) -@Category({SEDML_SBML_IT.class}) -public class SEDMLExporterSBMLTest extends SEDMLExporterCommon { - - public SEDMLExporterSBMLTest(TestCase testCase){ - super(testCase); - } - - /** - * each file in the slowTestSet takes > 10s on disk and is not included in the unit test (move to integration testing) - */ - static Set slowTestSet() { - Set slowModels = new HashSet<>(); - slowModels.add("biomodel_101981216.vcml"); // 29s - slowModels.add("biomodel_147699816.vcml"); // 23s - slowModels.add("biomodel_17326658.vcml"); // 24s - slowModels.add("biomodel_188880263.vcml"); // 89s - slowModels.add("biomodel_200301029.vcml"); // 124s (and fails with java.lang.OutOfMemoryError: GC overhead limit exceeded) - slowModels.add("biomodel_200301683.vcml"); // 37s - slowModels.add("biomodel_28625786.vcml"); // 57s - slowModels.add("biomodel_34826524.vcml"); // 129s - slowModels.add("biomodel_47429473.vcml"); // 194s - slowModels.add("biomodel_59361239.vcml"); // 116s - slowModels.add("biomodel_60799209.vcml"); // 41s - slowModels.add("biomodel_61699798.vcml"); // 69s - slowModels.add("biomodel_62467093.vcml"); // 23s - slowModels.add("biomodel_62477836.vcml"); // 30s - slowModels.add("biomodel_62585003.vcml"); // 24s - slowModels.add("biomodel_66264206.vcml"); // 45s - slowModels.add("biomodel_93313420.vcml"); // 137s - slowModels.add("biomodel_9590643.vcml"); // 40s - return slowModels; - } - - static Set outOfMemorySet() { - Set outOfMemoryModels = new HashSet<>(); - outOfMemoryModels.add("biomodel_101963252.vcml"); // FAULT.JAVA_HEAP_SPACE - outOfMemoryModels.add("biomodel_200301029.vcml"); // FAULT.OUT_OF_MEMORY - GC Overhead Limit Exceeded (and 124s) - outOfMemoryModels.add("biomodel_26455186.vcml"); // FAULT.OUT_OF_MEMORY - GC Overhead Limit Exceeded - outOfMemoryModels.add("biomodel_27192647.vcml"); // FAULT.OUT_OF_MEMORY - GC Overhead Limit Exceeded - outOfMemoryModels.add("biomodel_27192717.vcml"); // FAULT.OUT_OF_MEMORY) - Java heap space: failed reallocation of scalar replaced objects - return outOfMemoryModels; - } - - @Override - Map knownFaults() { - HashMap faults = new HashMap<>(); - faults.put("biomodel_123269393.vcml", FAULT.MATHOVERRIDES_INVALID); // Kf_r7 - biomodel needs fixing - MathOverrides has entry for non-existent parameter Kf_r7 - faults.put("biomodel_124562627.vcml", FAULT.NULL_POINTER_EXCEPTION); // CSG/analytic geometry issue - SBML model does not have any geometryDefinition. Cannot proceed with import - faults.put("biomodel_156134818.vcml", FAULT.UNKNOWN_IDENTIFIER); // species named 'I' conflicts with membrane parameter I - Unable to sort, unknown identifier I_Gs_GDI_accel_deg_copy6 - faults.put("biomodel_220138948.vcml", FAULT.MATHOVERRIDES_INVALID); // Kf_Uptake invalid override - MathOverrides has entry for non-existent parameter Kf_Uptake - faults.put("biomodel_84982474.vcml", FAULT.UNSUPPORTED_NONSPATIAL_STOCH_HISTOGRAM); // not supported nonspatial histogram - - - return faults; - } - - @Override - Map knownSEDMLFaults() { - HashMap faults = new HashMap<>(); - faults.put("__export_adv_test.vcml", SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); // round-tripped simulation not found with name 'spatialnoscan' - faults.put("biomodel_100596964.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_100961371.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_113655498.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_116929912.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_116929971.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_116930032.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_123269393.vcml", SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); // round-tripped simulation not found with name 'Simulation2' - faults.put("biomodel_123465498.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_123465505.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_124562627.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_12522025.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Simulation 1' in simContext 'purkinje9-ss' - faults.put("biomodel_13717231.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'double -' - faults.put("biomodel_13736736.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_145545992.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_148700996.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Full sim' in simContext 'Fast B Compartmental' - faults.put("biomodel_154961582.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); -// faults.put("biomodel_155016832.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_156134818.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_16763273.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_16804037.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); -// faults.put("biomodel_168717401.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_169993006.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_17098642.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_17257105.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation '1 uM iso' in simContext 'compartmental' - faults.put("biomodel_188880263.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_18894555.vcml", SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); // simulation 'baseline' in simContext 'compartmental' - faults.put("biomodel_189321805.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new - faults.put("biomodel_189512756.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_189513183.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_20253928.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_211839191.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_220138948.vcml", SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); // round-tripped simulation not found with name 'Uptake_Larger Jumps' - faults.put("biomodel_22403233.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_22403238.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_22403244.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_22403250.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_22403358.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_22403576.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_225440511.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_232498815.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_2912851.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_2913730.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_2915537.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_2917738.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_2917788.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_2917999.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_2930915.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_2962862.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_32568171.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_32568356.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_34826524.vcml", SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); // simulation 'Cap=1, cof, prof varied' in simContext 'Steady State Turnover' - faults.put("biomodel_34855932.vcml", SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); // simulation 'INIT' in simContext 'cell4' - faults.put("biomodel_38086434.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new - faults.put("biomodel_55178308.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new - faults.put("biomodel_55396830.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_59280306.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation '1 uM iso' in simContext 'compartmental' - faults.put("biomodel_60203358.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_60227051.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_63307133.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_65311813.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // simulation 'Copy of Simulation 101x101x36' in simContext '3d image' - faults.put("biomodel_66264973.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Simulation - local sequestration' in simContext 'compartmental - IC-G2736X' - faults.put("biomodel_66265579.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_74924130.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Simulation0' in simContext 'Application0' - faults.put("biomodel_77305266.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_7803961.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_7803976.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_81284732.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_82250339.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_83446023.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // can't find math override for Kf_dimerization - faults.put("biomodel_83462243.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'spatial-hybrid' - faults.put("biomodel_83651737.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); - faults.put("biomodel_84982474.vcml", SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS); // not supported non-spatial histogram - faults.put("biomodel_9254662.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_92705462.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'stoch' - faults.put("biomodel_97075423.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_97705317.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_97786619.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_97786886.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'hybrid' - faults.put("biomodel_97787114.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'hybrid' - faults.put("biomodel_98147638.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_98150237.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new - faults.put("biomodel_98174143.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_98296160.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - faults.put("biomodel_98730962.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'Application0' - faults.put("biomodel_165181964.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); - - - // SEDML Validator Errors - faults.put("biomodel_82065439.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // NON_UNIQUE_IDS: Each identified SED object must have a unique id. Multiple objects have the following ids:",[["compartmental"]] - faults.put("biomodel_220138948.vcml",SEDML_FAULT.OMEX_VALIDATION_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='OAT1']/@initialConcentration` does not match any elements of model `_0D`. - faults.put("biomodel_31523791.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='cAMP_Intracellular']/@initialConcentration` does not match any elements of model `Dose_response`. - faults.put("biomodel_34855932.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='Kf_GPCR_to_ICSC']/@value` does not match any elements of model `cell5` - faults.put("biomodel_40882931.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='ZO1staticF_PM']/@initialConcentration` does not match any elements of model `_3d_image` - faults.put("biomodel_40883509.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='PIK_PM']/@initialConcentration` does not match any elements of model `_3d_image` - faults.put("biomodel_65311813.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='Ran_nuc_diff']/@value` does not match any elements of model `_3d_image_0` - return faults; - } - - @Parameterized.Parameters - public static Collection testCases() { - Predicate skipFilter_SBML = (t) -> - !outOfMemorySet().contains(t) && - !largeFileSet().contains(t) && - !slowTestSet().contains(t); - Stream sbml_test_cases = Arrays.stream(VcmlTestSuiteFiles.getVcmlTestCases()).filter(skipFilter_SBML).map(fName -> new TestCase(fName, ModelFormat.SBML)); - return sbml_test_cases.collect(Collectors.toList()); -// return Arrays.asList( -// new TestCase("biomodel_31523791.vcml", ModelFormat.SBML), -// new TestCase("biomodel_34855932.vcml", ModelFormat.SBML), -// new TestCase("biomodel_40882931.vcml", ModelFormat.SBML), -// new TestCase("biomodel_40883509.vcml", ModelFormat.SBML), -// new TestCase("biomodel_65311813.vcml", ModelFormat.SBML), -// new TestCase("biomodel_155016832.vcml", ModelFormat.SBML) -// ); - } - - @Test - public void test_sedml_roundtrip_SBML() throws Exception { - if (knownFaults().containsKey(testCase.filename)) { - return; // skip known faults - } -// if (knownSEDMLFaults().get(testCase.filename) != SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT -// && knownSEDMLFaults().get(testCase.filename) != SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT){ -// return; -// } - sedml_roundtrip_common(); - } - -} +package org.vcell.sbml; + +import cbit.vcell.resource.NativeLib; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.vcell.sbml.vcell.SBMLExporter; +import org.vcell.sedml.ModelFormat; +import org.vcell.test.SEDML_SBML_IT; + +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@RunWith(Parameterized.class) +@Category({SEDML_SBML_IT.class}) +public class SEDMLExporterSBMLTest extends SEDMLExporterCommon { + + private String previousInstallDirPropertyValue; + private String previousCliWorkDirPropertyValue; + + public SEDMLExporterSBMLTest(TestCase testCase){ + super(testCase); + } + + /** + * each file in the slowTestSet takes > 10s on disk and is not included in the unit test (move to integration testing) + */ + static Set slowTestSet() { + Set slowModels = new HashSet<>(); + slowModels.add("biomodel_101981216.vcml"); // 29s + slowModels.add("biomodel_147699816.vcml"); // 23s + slowModels.add("biomodel_17326658.vcml"); // 24s + slowModels.add("biomodel_188880263.vcml"); // 89s + slowModels.add("biomodel_200301029.vcml"); // 124s (and fails with java.lang.OutOfMemoryError: GC overhead limit exceeded) + slowModels.add("biomodel_200301683.vcml"); // 37s + slowModels.add("biomodel_28625786.vcml"); // 57s + slowModels.add("biomodel_34826524.vcml"); // 129s + slowModels.add("biomodel_47429473.vcml"); // 194s + slowModels.add("biomodel_59361239.vcml"); // 116s + slowModels.add("biomodel_60799209.vcml"); // 41s + slowModels.add("biomodel_61699798.vcml"); // 69s + slowModels.add("biomodel_62467093.vcml"); // 23s + slowModels.add("biomodel_62477836.vcml"); // 30s + slowModels.add("biomodel_62585003.vcml"); // 24s + slowModels.add("biomodel_66264206.vcml"); // 45s + slowModels.add("biomodel_93313420.vcml"); // 137s + slowModels.add("biomodel_9590643.vcml"); // 40s + return slowModels; + } + + static Set outOfMemorySet() { + Set outOfMemoryModels = new HashSet<>(); + outOfMemoryModels.add("biomodel_101963252.vcml"); // FAULT.JAVA_HEAP_SPACE + outOfMemoryModels.add("biomodel_200301029.vcml"); // FAULT.OUT_OF_MEMORY - GC Overhead Limit Exceeded (and 124s) + outOfMemoryModels.add("biomodel_26455186.vcml"); // FAULT.OUT_OF_MEMORY - GC Overhead Limit Exceeded + outOfMemoryModels.add("biomodel_27192647.vcml"); // FAULT.OUT_OF_MEMORY - GC Overhead Limit Exceeded + outOfMemoryModels.add("biomodel_27192717.vcml"); // FAULT.OUT_OF_MEMORY) - Java heap space: failed reallocation of scalar replaced objects + return outOfMemoryModels; + } + + @Override + Map knownFaults() { + HashMap faults = new HashMap<>(); + faults.put("biomodel_123269393.vcml", FAULT.MATHOVERRIDES_INVALID); // Kf_r7 - biomodel needs fixing - MathOverrides has entry for non-existent parameter Kf_r7 + faults.put("biomodel_124562627.vcml", FAULT.NULL_POINTER_EXCEPTION); // CSG/analytic geometry issue - SBML model does not have any geometryDefinition. Cannot proceed with import + faults.put("biomodel_156134818.vcml", FAULT.UNKNOWN_IDENTIFIER); // species named 'I' conflicts with membrane parameter I - Unable to sort, unknown identifier I_Gs_GDI_accel_deg_copy6 + faults.put("biomodel_220138948.vcml", FAULT.MATHOVERRIDES_INVALID); // Kf_Uptake invalid override - MathOverrides has entry for non-existent parameter Kf_Uptake + faults.put("biomodel_84982474.vcml", FAULT.UNSUPPORTED_NONSPATIAL_STOCH_HISTOGRAM); // not supported nonspatial histogram + + + return faults; + } + + @Override + Map knownSEDMLFaults() { + HashMap faults = new HashMap<>(); + faults.put("__export_adv_test.vcml", SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); // round-tripped simulation not found with name 'spatialnoscan' + faults.put("biomodel_100596964.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_100961371.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_113655498.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_116929912.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_116929971.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_116930032.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_123269393.vcml", SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); // round-tripped simulation not found with name 'Simulation2' + faults.put("biomodel_123465498.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_123465505.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_124562627.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_12522025.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Simulation 1' in simContext 'purkinje9-ss' + faults.put("biomodel_13717231.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'double -' + faults.put("biomodel_13736736.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_145545992.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_148700996.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Full sim' in simContext 'Fast B Compartmental' + faults.put("biomodel_154961582.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); +// faults.put("biomodel_155016832.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_156134818.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_16763273.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_16804037.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); +// faults.put("biomodel_168717401.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_169993006.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_17098642.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_17257105.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation '1 uM iso' in simContext 'compartmental' + faults.put("biomodel_188880263.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_18894555.vcml", SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); // simulation 'baseline' in simContext 'compartmental' + faults.put("biomodel_189321805.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new + faults.put("biomodel_189512756.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_189513183.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_20253928.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_211839191.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_220138948.vcml", SEDML_FAULT.SIMULATION_NOT_FOUND_BY_NAME); // round-tripped simulation not found with name 'Uptake_Larger Jumps' + faults.put("biomodel_22403233.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403238.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403244.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403250.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403358.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_22403576.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_225440511.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_232498815.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2912851.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2913730.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2915537.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2917738.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2917788.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2917999.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2930915.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_2962862.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_32568171.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_32568356.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_34826524.vcml", SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); // simulation 'Cap=1, cof, prof varied' in simContext 'Steady State Turnover' + faults.put("biomodel_34855932.vcml", SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT); // simulation 'INIT' in simContext 'cell4' + faults.put("biomodel_38086434.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new + faults.put("biomodel_55178308.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new + faults.put("biomodel_55396830.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_59280306.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation '1 uM iso' in simContext 'compartmental' + faults.put("biomodel_60203358.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_60227051.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_63307133.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_65311813.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // simulation 'Copy of Simulation 101x101x36' in simContext '3d image' + faults.put("biomodel_66264973.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Simulation - local sequestration' in simContext 'compartmental - IC-G2736X' + faults.put("biomodel_66265579.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_74924130.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // simulation 'Simulation0' in simContext 'Application0' + faults.put("biomodel_77305266.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_7803961.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_7803976.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_81284732.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_82250339.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_83446023.vcml", SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT); // can't find math override for Kf_dimerization + faults.put("biomodel_83462243.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'spatial-hybrid' + faults.put("biomodel_83651737.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); + faults.put("biomodel_84982474.vcml", SEDML_FAULT.DIFF_NUMBER_OF_BIOMODELS); // not supported non-spatial histogram + faults.put("biomodel_9254662.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_92705462.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'stoch' + faults.put("biomodel_97075423.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_97705317.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_97786619.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_97786886.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'hybrid' + faults.put("biomodel_97787114.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'hybrid' + faults.put("biomodel_98147638.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_98150237.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); // new + faults.put("biomodel_98174143.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_98296160.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + faults.put("biomodel_98730962.vcml", SEDML_FAULT.SIMCONTEXT_NOT_FOUND_BY_NAME); // round-tripped simulationContext not found with name 'Application0' + faults.put("biomodel_165181964.vcml", SEDML_FAULT.NO_MODELS_IN_OMEX); + + + // SEDML Validator Errors + faults.put("biomodel_82065439.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // NON_UNIQUE_IDS: Each identified SED object must have a unique id. Multiple objects have the following ids:",[["compartmental"]] + faults.put("biomodel_220138948.vcml",SEDML_FAULT.OMEX_VALIDATION_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='OAT1']/@initialConcentration` does not match any elements of model `_0D`. + faults.put("biomodel_31523791.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='cAMP_Intracellular']/@initialConcentration` does not match any elements of model `Dose_response`. + faults.put("biomodel_34855932.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='Kf_GPCR_to_ICSC']/@value` does not match any elements of model `cell5` + faults.put("biomodel_40882931.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='ZO1staticF_PM']/@initialConcentration` does not match any elements of model `_3d_image` + faults.put("biomodel_40883509.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfSpecies/sbml:species[@id='PIK_PM']/@initialConcentration` does not match any elements of model `_3d_image` + faults.put("biomodel_65311813.vcml", SEDML_FAULT.OMEX_PARSER_ERRORS); // XPATH_BAD: XPath `/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='Ran_nuc_diff']/@value` does not match any elements of model `_3d_image_0` + return faults; + } + @Parameterized.Parameters + public static Collection testCases() { + Predicate skipFilter_SBML = (t) -> + !outOfMemorySet().contains(t) && + !largeFileSet().contains(t) && + !slowTestSet().contains(t); + Stream sbml_test_cases = Arrays.stream(VcmlTestSuiteFiles.getVcmlTestCases()).filter(skipFilter_SBML).map(fName -> new TestCase(fName, ModelFormat.SBML)); + return sbml_test_cases.collect(Collectors.toList()); +// return Arrays.asList( +// new TestCase("biomodel_31523791.vcml", ModelFormat.SBML), +// new TestCase("biomodel_34855932.vcml", ModelFormat.SBML), +// new TestCase("biomodel_40882931.vcml", ModelFormat.SBML), +// new TestCase("biomodel_40883509.vcml", ModelFormat.SBML), +// new TestCase("biomodel_65311813.vcml", ModelFormat.SBML), +// new TestCase("biomodel_155016832.vcml", ModelFormat.SBML) +// ); + } + + @Test + public void test_sedml_roundtrip_SBML() throws Exception { + if (knownFaults().containsKey(testCase.filename)) { + return; // skip known faults + } +// if (knownSEDMLFaults().get(testCase.filename) != SEDML_FAULT.MATH_OVERRIDE_NOT_EQUIVALENT +// && knownSEDMLFaults().get(testCase.filename) != SEDML_FAULT.MATH_OVERRIDE_NAMES_DIFFERENT){ +// return; +// } + sedml_roundtrip_common(); + } + +} diff --git a/vcell-util/src/main/java/org/vcell/test/Nightly.java b/vcell-util/src/main/java/org/vcell/test/Nightly.java new file mode 100644 index 0000000000..e40840fa7a --- /dev/null +++ b/vcell-util/src/main/java/org/vcell/test/Nightly.java @@ -0,0 +1,3 @@ +package org.vcell.test; + +public interface Nightly {} diff --git a/vcell-util/src/main/java/org/vcell/test/RoundTrip.java b/vcell-util/src/main/java/org/vcell/test/RoundTrip.java new file mode 100644 index 0000000000..19de0a7d70 --- /dev/null +++ b/vcell-util/src/main/java/org/vcell/test/RoundTrip.java @@ -0,0 +1,3 @@ +package org.vcell.test; + +public interface RoundTrip extends Nightly {}