diff --git a/docs/at_variables_reference.rst b/docs/at_variables_reference.rst index a66821ad..a361d58e 100644 --- a/docs/at_variables_reference.rst +++ b/docs/at_variables_reference.rst @@ -11,8 +11,6 @@ e.g. ``experiment.py /path/to/instance1``, ``experiment.py /path/to/instance2``, ``@INSTANCE@`` variable that resolves to the respective paths of the instances. Then, we only need to specify ``experiments.py @INSTANCE@`` as experiment arguments. -.. - TODO: Add section Instances for generators and INSTANCE_FILENAME variable Below, we list all @-variables and where they can be used. @@ -21,9 +19,9 @@ Below, we list all @-variables and where they can be used. - ``@EXTRA_ARGS@``: extra arguments of all variants and the instance of an experiment - ``@INSTANCE@``: path of a :ref:`local `/:ref:`remote ` instance, i.e. ``/instance_directory/`` - ``@INSTANCE_DIR@``: path of the :ref:`InstanceDirectory` +- ``@INSTANCE_FILENAME@``: filename of the instance - ``@INSTANCE:@``: path of a :ref:`MultipleExtensions` instance with extension ````, i.e. ``/instance_directory/.`` - ``@INSTANCE:@``: path of an :ref:`ArbitraryInputFiles` instance with index ```` in the ``files`` key, i.e. ``/instance_directory/files[]`` -- ``@INSTANCE_FILENAME@``: filename of the instance - ``@OUTPUT@``: path to the output file of an experiment - ``@OUTPUT:@``: path to the output file with extension ```` of an experiment - ``@OUTPUT_SUBDIR@``: output subdirectory of the experiment where the output and status files are stored, i.e. ``/path_to_experiments_yml/output/`` @@ -148,6 +146,26 @@ Same as for the :ref:`AtVariablesExperimentsArgs` key `without` the ``@EXTRA_ARG Instances --------- +.. _AtVariablesInstanceArgs: + +args +^^^^ + +The following @-variables can be used in the ``args`` key: + + +- ``@BASE_DIR@`` +- ``@INSTANCE_DIR@`` +- ``@INSTANCE@`` +- ``@INSTANCE:@`` +- ``@INSTANCE:@`` + +environ +^^^^^^^ + +The values of the ``environ`` key will be substituted and the @-variables are the same as for +the :ref:`AtVariablesInstanceArgs` key. + extra_args ^^^^^^^^^^ @@ -170,6 +188,12 @@ The following @-variables can be used in the ``url`` key: - ``@INSTANCE_FILENAME@`` +workdir +^^^^^^^ + +Same as for the :ref:`AtVariablesInstanceArgs` key. + + Variants -------- @@ -197,3 +221,4 @@ procs_per_node ^^^^^^^^^^^^^^ Same as for the :ref:`experiments args ` key `without` the ``@EXTRA_ARGS@`` variable. + diff --git a/docs/experiments_reference.rst b/docs/experiments_reference.rst index c86b985c..f92f87c8 100644 --- a/docs/experiments_reference.rst +++ b/docs/experiments_reference.rst @@ -22,12 +22,16 @@ Instances This entry is a list of instances that will be used for experiments. The following keys are used for specifying instances: +- ``args``: list of postprocessing arguments +- ``environ``: dictionary of (environment variable, value)-pairs - ``extensions``: list of extensions that the instance has - ``files``: list of files the instance consists of - ``items``: list of instances - ``name``: name of the instance (used when dealing with instances that consist of unrelated files) +- ``postprocess``: list or string of postprocessing arguments - ``repo``: source of instances - ``set``: list of sets the instance belongs to +- ``workdir``: path of the working directory For detailed usage examples, see the :ref:`Instances` page. diff --git a/docs/instances.rst b/docs/instances.rst index 8bc6a296..2fde6e2f 100644 --- a/docs/instances.rst +++ b/docs/instances.rst @@ -13,7 +13,7 @@ list local instances that consist of zero or more files. More over simexpal can remote instances from the `SNAP `_ repository, Git repositories and arbitrary URLs. It is also possible to assign instances to instance sets that enable a more efficient usage of the :ref:`command line interface ` and are useful when -defining the run matrix. +defining the run matrix. Furthermore, you can add extra arguments to instances and postprocess them. .. _InstanceDirectory: @@ -71,8 +71,9 @@ to download the instances into the instance directory. .. note:: 1st December 2020: It is no longer possible to automatically download `KONECT `_ instances as the website is no longer publicly available. It is still possible to list them and - execute supported actions, e.g, transforming the instances to edgelist format via - ``simex instances run-transform --transform='to_edgelist'`` if you already have them saved locally. + execute supported actions, e.g, transforming the instances to edge list format via + ``simex instances run-transform --transform='to_edgelist'`` or :ref:`postprocess ` + them if you already have them saved locally. Instances From SNAP ^^^^^^^^^^^^^^^^^^^ @@ -467,6 +468,108 @@ and ``set2``, which contains ``instance2`` and ``instance3``. Instance sets will also be useful when using the :ref:`command line interface ` of simexpal and when defining the :ref:`RunMatrix`. +.. _PostprocessInstances: + +Postprocessing +-------------- + +There might be cases where you need to process the instances after installing or downloading them, before they +are ready to be used in the experiments. In order to do so, you can use the + +- ``postprocess``: list or string of postprocessing arguments + +key. Afterwards, you can install and postprocess the instances by calling + +.. code-block:: bash + + $ simex instances install + +in the terminal. + +Before processing an instance, simexpal copies the contents of each file belonging to an instance into separate +``.original`` files. After postprocessing an instance simexpal creates an ``.postprocessed`` +file, signalling the successful postprocessing of an instance. If an error occurs during the postprocessing of an +instance, the original instance files will be restored and the postprocessing will be skipped. + +Arbitrary Postprocessing +^^^^^^^^^^^^^^^^^^^^^^^^ + +You can define arbitrary postprocessing steps by setting the ``postprocess`` key to a list of dictionaries +containing the + +- ``args``: list of postprocessing arguments +- ``environ``: dictionary of (environment variable, value)-pairs +- ``workdir``: path of the working directory + +keys. + +Assume you want to postprocess the ``facebook_combined`` and ``cit-HepTh`` network from +`SNAP `_ using two executables ``postprocess1`` and ``postprocess2``, which +take the path of the instance as parameter. Also, you have to prepend the path for ``postprocess1`` to the +``PATH`` environment variable. Then, your ``experiments.yml`` file could look as follows: + +.. code-block:: YAML + :linenos: + :caption: How to arbitrarily postprocess instances in the experiments.yml file. + + instances: + - repo: snap + items: + - 'facebook_combined' + - 'cit-HepTh' + postprocess: + - args: ['postprocess1', '@INSTANCE@'] + environ: + 'PATH': '/path/to/postprocess1' + - args: ['postprocess2', '@INSTANCE@'] + +When executing the postprocessing arguments, the :ref:`@-variable ` ``@INSTANCE@`` will resolve +to the respective path of the instances. For instances with :ref:`MultipleExtensions` or +:ref:`ArbitraryInputFiles`, use the @-variables ``@INSTANCE:@`` and ``@INSTANCE:@`` respectively. + +.. warning:: + Make sure to use the :ref:`AtVariables` to access paths of instance files and to maintain the names and + locations of each file belonging to an instance (as passed by the @-variable) after every postprocessing step. + Simexpal temporarily renames instance files while postprocessing them. Manually renaming instance files might + break the postprocessing. + +Converting to Edge List Format +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To convert instances from `SNAP `_ or `KONECT `_, we can set +``postprocess: to_edgelist`` as follows: + +.. code-block:: YAML + :linenos: + :caption: How to convert SNAP/KONECT instances to edge list format in the experiments.yml file. + + instances: + - repo: snap + items: + - facebook_combined + - cit-HepTh + postprocess: to_edgelist + - repo: konect + items: + - dolphins + - ucidata-zachary + postprocess: to_edgelist + +In this way, simexpal will use its internal mechanism to convert the instances to edge list +format after downloading them. + +Re-Postprocessing +^^^^^^^^^^^^^^^^^ + +To re-postprocess instances, you can simply delete the respective ``.postprocessed`` files +before calling + +.. code-block:: bash + + $ simex instances install + +in the terminal. + Next ---- diff --git a/scripts/simex b/scripts/simex index 28c71927..7224854d 100755 --- a/scripts/simex +++ b/scripts/simex @@ -302,7 +302,10 @@ def do_instances_install(args): for instance in cfg.all_instances(): if args.overwrite: - util.try_rmfile(os.path.join(cfg.instance_dir(), instance.unique_filename)) + fullpath = instance.fullpath + util.try_rmfile(fullpath) + util.try_rmfile(fullpath + '.postprocessed') + util.try_rmfile(fullpath + '.original') instance.install() instances_install_parser = instances_subcmds.add_parser('install') diff --git a/simexpal/base.py b/simexpal/base.py index 51001b7e..d1a454d5 100644 --- a/simexpal/base.py +++ b/simexpal/base.py @@ -735,64 +735,191 @@ def check_available(self): def install(self): from . import instances - global DID_WARN_KONECT - - if self.check_available() or self.is_fileless: + if self.is_fileless: return - util.try_mkdir(self._cfg.instance_dir()) + instance_dir = self._cfg.instance_dir() + util.try_mkdir(instance_dir) - partial_path = os.path.join(self._cfg.instance_dir(), self.unique_filename) - if 'repo' in self._inst_yml: + if not self.check_available(): + if 'repo' in self._inst_yml: - if self._inst_yml['repo'] == 'local': - return - elif self._inst_yml['repo'] == 'konect': - if not DID_WARN_KONECT: - print("Downloading instances from konect is no longer possible.") - DID_WARN_KONECT = True - return + global DID_WARN_KONECT - print("Downloading instance '{}' from {} repository".format(self.shortname, - self._inst_yml['repo'])) + if self._inst_yml['repo'] == 'local': + return + elif self._inst_yml['repo'] == 'konect': + if not DID_WARN_KONECT: + print("Downloading instances from konect is no longer possible.") + DID_WARN_KONECT = True + return + else: + print("Downloading instance '{}' from {} repository".format( + self.shortname, self._inst_yml['repo'])) - instances.download_instance(self._inst_yml, - self.config.instance_dir(), self.unique_filename, partial_path, '.post0') - elif 'generator' in self._inst_yml: - import subprocess + instances.download_instance(self._inst_yml, instance_dir, self.unique_filename, + os.path.join(instance_dir, self.unique_filename), '.post0') - def substitute(p): - if p == 'INSTANCE_FILENAME': - return self.unique_filename - raise RuntimeError("Unexpected parameter {}".format(p)) + elif 'generator' in self._inst_yml: + import subprocess - print("Generating instance '{}'".format(self.shortname)) + def substitute(p): + if p == 'INSTANCE_FILENAME': + return self.unique_filename + raise RuntimeError("Unexpected parameter {}".format(p)) - assert isinstance(self._inst_yml['generator']['args'], list) - cmd = [util.expand_at_params(arg_tmpl, substitute) for arg_tmpl - in self._inst_yml['generator']['args']] + print("Generating instance '{}'".format(self.shortname)) - with open(partial_path + '.gen', 'w') as f: - subprocess.check_call(cmd, cwd=self.config.basedir, - stdout=f, stderr=subprocess.PIPE) - os.rename(partial_path + '.gen', partial_path + '.post0') - elif 'method' in self._inst_yml: - print(f"Downloading instance '{self.shortname}' with method '{self.method}'") + assert isinstance(self._inst_yml['generator']['args'], list) + cmd = [util.expand_at_params(arg_tmpl, substitute) for arg_tmpl + in self._inst_yml['generator']['args']] - instances.download_instance(self._inst_yml, - self.config.instance_dir(), self.unique_filename, partial_path, '.post0') - else: - raise RuntimeError(f"Unknown installation option for instance '{self.shortname}'") + partial_path = os.path.join(instance_dir, self.unique_filename) + with open(partial_path + '.gen', 'w') as f: + subprocess.check_call(cmd, cwd=self.config.basedir, + stdout=f, stderr=subprocess.PIPE) + os.rename(partial_path + '.gen', partial_path + '.post0') + elif 'method' in self._inst_yml: + print(f"Downloading instance '{self.shortname}' with method '{self.method}'") + + instances.download_instance(self._inst_yml, instance_dir, self.unique_filename, + os.path.join(instance_dir, self.unique_filename), '.post0') + else: + raise RuntimeError(f"Unknown installation option for instance '{self.shortname}'") stage = 0 + filenames = self.filenames if 'postprocess' in self._inst_yml: - assert self._inst_yml['postprocess'] == 'to_edgelist' - instances.convert_to_edgelist(self._inst_yml, - partial_path + '.post0', partial_path + '.post1') - os.unlink(partial_path + '.post0') - stage = 1 - os.rename(partial_path + '.post{}'.format(stage), partial_path) + did_work = False + postprocessed = os.path.isfile(os.path.join(instance_dir, self.yml_name) + '.postprocessed') + if not postprocessed: + + # Make sure that the .post0 files exist. + # For cases like 'repo: local' instances, adding the 'postprocess' key + # after downloading the instance or re-postprocessing instances. + for file in filenames: + if not os.path.isfile(os.path.join(instance_dir, file + '.post0')): + os.rename(os.path.join(instance_dir, file), os.path.join(instance_dir, file + '.post0')) + + print("simexpal: Start postprocessing of instance '{}'".format(self.shortname)) + if isinstance(self._inst_yml['postprocess'], str): + assert self._inst_yml['postprocess'] == 'to_edgelist' + + partial_path = os.path.join(instance_dir, self.unique_filename) + try: + print("simexpal: Converting instance '{}' to edge list format".format(self.shortname)) + instances.convert_to_edgelist(self._inst_yml, partial_path + '.post0', partial_path + '.post1') + os.rename(partial_path + '.post0', partial_path + '.original') + except RuntimeError as e: + print("simexpal: An error occurred while postprocessing the instance '{}': {}".format( + self.shortname, e)) + print("simexpal: Restoring original instance files") + os.rename(partial_path + '.post0', partial_path) + print("simexpal: Skipping postprocessing of instance '{}'".format(self.shortname)) + return + + stage = 1 + util.touch(os.path.join(instance_dir, self.yml_name) + '.postprocessed') + did_work = True + else: + assert isinstance(self._inst_yml['postprocess'], list) + + import subprocess + import shutil + + def get_qualified_filename(identifier): + if identifier.isdigit(): + identifier = int(identifier) + if not self.has_multi_files: + raise RuntimeError( + f"Instance '{self.shortname}' does not have any files specified in the experiments.yml" + ) from None + if len(self.filenames) <= identifier: + raise IndexError('File index out of range: {}'.format(identifier)) + return os.path.join(instance_dir, filenames[identifier] + '.post0') + else: + if not self.has_multi_ext: + raise RuntimeError( + f"Instance '{self.shortname}' does not have any extensions specified in the experiments.yml" + ) from None + if identifier not in self.extensions: + raise RuntimeError( + f"Unexpected file extension for instance '{self.shortname}': .{identifier}" + ) from None + return os.path.join(instance_dir, self.yml_name + '.' + identifier + '.post0') + + def substitute(var): + if var == 'BASE_DIR': + return self._cfg.basedir + elif var == 'INSTANCE_DIR': + return instance_dir + elif var == 'INSTANCE': + return os.path.join(instance_dir, self.yml_name + '.post0') + elif var.startswith('INSTANCE:'): + return get_qualified_filename(var.split(':')[1]) + + def prepend_env(var, items): + if var in os.environ: + return ':'.join(items) + ':' + os.environ[var] + return ':'.join(items) + + def do_step(step_yml, default_workdir=None): + workdir = default_workdir + if 'workdir' in step_yml: + workdir = util.expand_at_params(step_yml['workdir'], substitute) + + environ = os.environ.copy() + if 'environ' in step_yml: + for (var, value) in step_yml['environ'].items(): + environ[var] = prepend_env(var, util.expand_at_params(value, substitute)) + + if isinstance(step_yml['args'], list): + shell = False + args = [util.expand_at_params(arg, substitute) for arg in step_yml['args']] + else: + assert isinstance(step_yml['args'], str) + shell = True + args = util.expand_at_params(step_yml['args'], substitute) + + subprocess.check_call(args, cwd=workdir, env=environ, shell=shell) + + # Preserve original files before postprocessing. + for file in filenames: + with open(os.path.join(instance_dir, file + '.post0'), 'rb') as f_in: + with open(os.path.join(instance_dir, file + '.original'), 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + + for command_yml in self._inst_yml['postprocess']: + try: + do_step(command_yml, instance_dir) + except Exception as e: + print("simexpal: An error occurred while postprocessing the instance '{}': {}".format( + self.shortname, e)) + print("simexpal: Restoring original instance files") + for file in filenames: + os.rename(os.path.join(instance_dir, file + '.original'), os.path.join(instance_dir, file)) + os.unlink(os.path.join(instance_dir, file + '.post0')) + print("simexpal: Skipping postprocessing of instance '{}'".format(self.shortname)) + return + + for file in filenames: + os.rename(os.path.join(instance_dir, file + '.post0'), os.path.join(instance_dir, file + '.post1')) + + stage = 1 + util.touch(os.path.join(instance_dir, self.yml_name) + '.postprocessed') + did_work = True + + if not did_work: + print("simexpal: No postprocessing to do for instance '{}'".format(self.shortname)) + else: + print("simexpal: Finished postprocessing of instance '{}'".format(self.shortname)) + + for file in filenames: + try: + os.rename(os.path.join(instance_dir, file + '.post{}'.format(stage)), os.path.join(instance_dir, file)) + except FileNotFoundError: + pass def run_transform(self, transform, out_path): assert transform == 'to_edgelist' diff --git a/simexpal/instances.py b/simexpal/instances.py index 9ba109cd..d7a05652 100644 --- a/simexpal/instances.py +++ b/simexpal/instances.py @@ -132,6 +132,8 @@ def convert_to_edgelist(inst_yml, in_path, out_path): elif repo == 'snap': separator = '\t' comment_prefix = '#' + else: + raise RuntimeError("Only instances from the KONECT or SNAP repository can be converted to edge list format") def get_other_separator(separator): if separator == ' ': diff --git a/simexpal/schemes/experiments.json b/simexpal/schemes/experiments.json index 4595a352..cd977ceb 100644 --- a/simexpal/schemes/experiments.json +++ b/simexpal/schemes/experiments.json @@ -26,7 +26,7 @@ "type": "integer" } }, - "build_arguments": { + "commands": { "type": "array", "items": { "type": "object", @@ -74,10 +74,10 @@ "git": {"type": "string"}, "recursive-clone": {"type": "boolean"}, "requires": {"$ref": "#/definitions/str_or_str_list"}, - "regenerate": {"$ref": "#/definitions/build_arguments"}, - "configure": {"$ref": "#/definitions/build_arguments"}, - "compile": {"$ref": "#/definitions/build_arguments"}, - "install": {"$ref": "#/definitions/build_arguments"}, + "regenerate": {"$ref": "#/definitions/commands"}, + "configure": {"$ref": "#/definitions/commands"}, + "compile": {"$ref": "#/definitions/commands"}, + "install": {"$ref": "#/definitions/commands"}, "exports_python": {"type": "string"}, "extra_paths": {"$ref": "#/definitions/str_or_str_list"} }, @@ -134,6 +134,7 @@ }, "extra_args": {"$ref": "#/definitions/str_list"}, "set": {"$ref": "#/definitions/str_or_str_list"}, + "postprocess": {"$ref": "#/definitions/commands"}, "items": { "oneOf": [ { @@ -171,6 +172,7 @@ "extensions": {"$ref": "#/definitions/str_list"}, "extra_args": {"$ref": "#/definitions/str_list"}, "set": {"$ref": "#/definitions/str_or_str_list"}, + "postprocess": {"$ref": "#/definitions/commands"}, "items": { "oneOf": [ { @@ -216,6 +218,7 @@ "repo": {"const": "local"}, "extra_args": {"$ref": "#/definitions/str_list"}, "set": {"$ref": "#/definitions/str_or_str_list"}, + "postprocess": {"$ref": "#/definitions/commands"}, "items": { "type": "array", "items": { @@ -256,7 +259,7 @@ "url": {"type": "string"}, "extra_args": {"$ref": "#/definitions/str_list"}, "set": {"$ref": "#/definitions/str_or_str_list"}, - "postprocess": {"const": "to_edgelist"}, + "postprocess": {"$ref": "#/definitions/commands"}, "items": { "oneOf": [ { @@ -296,7 +299,7 @@ "commit": {"type": "string"}, "git_subdir": {"type": "string"}, "set": {"$ref": "#/definitions/str_or_str_list"}, - "postprocess": {"const": "to_edgelist"}, + "postprocess": {"$ref": "#/definitions/commands"}, "items": { "oneOf": [ { @@ -371,7 +374,17 @@ "enum": ["local", "konect", "snap"] }, "repo-subdir": {"type": "string"}, - "postprocess": {"const": "to_edgelist"}, + "postprocess": { + "oneOf": [ + { + "const": "to_edgelist" + }, + { + "$ref": "#/definitions/commands" + } + + ] + }, "extra_args": {"$ref": "#/definitions/str_list"}, "set": {"$ref": "#/definitions/str_or_str_list"}, "items": { diff --git a/tests/instances/experiments_ymls/postprocess/experiments.yml b/tests/instances/experiments_ymls/postprocess/experiments.yml new file mode 100644 index 00000000..ba613d11 --- /dev/null +++ b/tests/instances/experiments_ymls/postprocess/experiments.yml @@ -0,0 +1,62 @@ +# This file contains postprocessed SNAP, local, multiple extension +# arbitrary file, URL and Git instances. +instances: + # SNAP Instances + - repo: snap + items: + - 'facebook_combined' + - 'cit-HepTh' + postprocess: to_edgelist + - repo: snap + items: + - 'ca-CondMat' + - 'cit-HepPh' + postprocess: + - args: ['echo', '1', '@INSTANCE@'] + # Local Instances + - repo: local + items: + - 'instance1' + - 'instance2' + postprocess: + - args: ['echo', '1', '@INSTANCE@'] + # Multiple Extensions + - repo: local + extensions: + - 'graph' + - 'xyz' + items: + - 'instance3' + - 'instance4' + postprocess: + - args: ['echo', '1', '@INSTANCE:graph@'] + - args: ['echo', '2', '@INSTANCE:xyz@'] + # Arbitrary Files + - repo: local + items: + - name: foo + files: + - 'instance5' + - 'instance6' + postprocess: + - args: ['echo', '1', '@INSTANCE:0@'] + - args: ['echo', '2', '@INSTANCE:1@'] + # URL Instances + - method: url + url: 'https://raw.githubusercontent.com/hu-macsy/simexpal/master/simexpal/schemes/@INSTANCE_FILENAME@' + items: + - 'experiments.json' + - 'launchers.json' + postprocess: + - args: ['echo', '1', '@INSTANCE@'] + # Git Instances + - method: git + git: 'https://github.com/hu-macsy/simexpal' + repo_name: 'foo' + commit: 'master' + items: + - 'setup.py' + - 'pytest.ini' + postprocess: + - args: ['echo', '1', '@INSTANCE@'] + diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance1 b/tests/instances/experiments_ymls/postprocess/instances/instance1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance2 b/tests/instances/experiments_ymls/postprocess/instances/instance2 new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance3 b/tests/instances/experiments_ymls/postprocess/instances/instance3 new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance3.graph b/tests/instances/experiments_ymls/postprocess/instances/instance3.graph new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance3.xyz b/tests/instances/experiments_ymls/postprocess/instances/instance3.xyz new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance4 b/tests/instances/experiments_ymls/postprocess/instances/instance4 new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance4.graph b/tests/instances/experiments_ymls/postprocess/instances/instance4.graph new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance4.xyz b/tests/instances/experiments_ymls/postprocess/instances/instance4.xyz new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance5 b/tests/instances/experiments_ymls/postprocess/instances/instance5 new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/experiments_ymls/postprocess/instances/instance6 b/tests/instances/experiments_ymls/postprocess/instances/instance6 new file mode 100644 index 00000000..e69de29b diff --git a/tests/instances/test_installation.py b/tests/instances/test_installation.py index 86962f94..b80cfeab 100644 --- a/tests/instances/test_installation.py +++ b/tests/instances/test_installation.py @@ -7,7 +7,8 @@ yml_dirs = ['/experiments_ymls/snap/', '/experiments_ymls/url/', - '/experiments_ymls/git/'] + '/experiments_ymls/git/', + '/experiments_ymls/postprocess/'] @pytest.mark.parametrize('rel_yml_path', yml_dirs) def test_download(rel_yml_path): @@ -17,4 +18,11 @@ def test_download(rel_yml_path): instance.install() assert instance.check_available() - assert os.path.getsize(instance.fullpath) > 0 + + if 'postprocess' in instance._inst_yml: + instance_dir = instance.config.instance_dir() + + assert os.path.isfile(os.path.join(instance_dir, instance.yml_name) + '.postprocessed') + + for file in instance.filenames: + assert os.path.isfile(os.path.join(instance_dir, file + '.original'))