<commit_before>A docker container that includes a stable Debian Linux and convenience commands for grading a student submission.
Commands include tools from capturing the test output to submitting a feedback back to the grading service.

This container is just a base and does not include tools for different programming and scripting languages.
Thus, actual grading/assessment containers should derive from this container via the FROM instruction in their Dockerfiles.

You can find many grading containers on [the apluslms page on docker hub](https://hub.docker.com/u/apluslms/).
Containers starting with `grade-` are relevant for this purpose.

Version of grading base has format `<major>.<minor>`.
Major is updated when there is backwards incompatible change.
For example, when deprecated tool is removed.
Minor number is updated every time there is something new, where that bug fixes, added features or update on the debian base image.
Derived containers typically use format `<tool version>-<garding-base version>u<update>`,
where tool version is the version from upstream, grading-base is the version of this container and update is number that indicates update on containerisation.
So, for example, grade-python `3.5-2.2u1` means that there is python 3.5 on top of grading-base 2.2 and it's first update after initial release.
Update part is optional and can be omitted.

# The container entry point, the grade wrapper

Container has grade wrapper `/gw` set as the entry point.
This means that everything executed within this container (or derivative) is executed through this script.

The wrapper will take care of redirecting output (stdout and stderr) to `/feedback/grading-script-errors`.
In addition, the script will make sure that the working directory is set correctly.
After the grading script has been executed, the wrapper will execute `grade`.
Thus, the grading script does not need to call `cd` or `grade` anymore.

The wrapper has three different operations, based on the first argument.

1. If the first argument starts with `/bin/` or is `--exec`,
   then arguments are executed and the wrapper itself stops here.
   No redirections are done and `grade` is not executed.

2. If the first argument is `--sh`, then rest of the arguments are evaluated with `sh -c "$*"`.
   This makes strings with quoted text possible in mooc-grader environment.

3. The typical case. Argument list is executed as is.

The exit code from the grading script is stored in the grading-script-errors, but the grade wrapper always exits with 0.

# Filesystem layout

* `/submission/user`

    Files for the solution submitted by the student are stored here.
    This path can be used as working directory.

* `/exercise`

    Exercise files are mounted here in a read only mode.
    With mooc-grader, that means the path you entered in `mount`.
    Typically, this includes `run.sh` and unit test files.

* `/feedback`

    Grading script should store feedback in this path.
    Most utility commands do so, including `capture`, `testcase` and `grade`.
    In the future, mooc-grader will read files from this path instead of expecting a post request.

    * `/feedback/points`:

        Final points.
        Valid format for the data is `<points>/<max_points>` e.g. `5/10`.
        You can use `points` to update this file.
        Points are read by `grade`.

    * `/feedback/out`:

        Feedback that is going be presented in the LMS.
        Typically, data is in html format.
        You should use `pre` to wrap plain text to html.
        You can capture feedback with `capture pre <command>`, for example.

    * `/feedback/err`:

        Error messages from a student or a testing code.
        If present, `grade` will append this inside a pre tag at the end of the out file.
        This file typically contains stderr from the test code.
        For example, `capture` redirects stderr to this file.
        If stderr is normal output (e.g. with python unit tests), then you should consider using `err-to-out`.

    * `/feedback/grading-script-errors`:

        Errors that should be visible only to the staff.
        This file is added as a part of `grading_data` with key `errors` and send to the grading service.
        Then, data can be shown in the LMS to the course staff.
        Data is expected to be plain text messages from `run.sh` and other tools.
        By default, `/gw` redirects stdout and stderr from the `run.sh` to this file.

    * `/feedback/submission-set-error`:

        If this file contains `true`, then the submission is set in an error state in the LMS.
        You can use `set-error` in your script to set this file.

* `/feedback/<number>`

    A single feedback item.
    A set of these directories is considered the feedback list.
    Typically, one folder matches one test case.
    For now, this feedback list is not fully supported and the tool `create-test-feedback` is provided to render these directories to `/feedback/out`.
    Nevertheless, this allows building tools and scripts that export feedback in this format.
    In future, different templates can be used to render the feedback list in the grading service.
    The `grade` tool will automatically merge these directories to a single html file, if grading service doesn't support feedback as a list.

    For every numbered path (feedback item), there can exists any number of files, but following files are typical.
    Following files are supported by `create-test-feedback` and a basic template on the grading service.
    More advanced or specific templates can of course deviate from those.

    * `.../title`: A title or a display name for this feedback item.
    * `.../status`: The status of this feedback. Valid values: `ignored`, `skipped`, `passed`, `failed`, `error`.
    * `.../points`: Points given from this item.
    * `.../max_points`: Maximum points that could be given from this item.
    * `.../out.txt`: Stdout from the test.
    * `.../err.txt`: Stderr from the test.


# Utility commands

Following utility commands are provided in the path.

* `testcase [-t title] [-p points_on_success] [-s only_if_zero] CMD...`

    Defines a single test case.
    Useful when running multiple commands for grading.
    Creates `/feedback/<number>` directory with increasing number for every call.

    If `title` is provided, it's stored in `/feedback/<number>/title`.

    If `points_on_success` is provided, it will be written to `/feedback/<number>/max_points`.
    If CMD exits with 0, then it will also be written to `/feedback/<number>/points`.

    If `only_if_zero` is provided and not 0, then CMD is not executed and `testcase` exits with non-zero exit code.

    Status of this test is stored in `/feedback/<number>/status` accordingly.

* `capture [-o out] [-e err] [-u user] CMD...`

    Changes the ownership of the working directory to `user`,
    executes the command as `user`,
    and captures the stdout to `out` and the stderr to `err`.
    In addition, `capture` ensures that the environment does not contain `REC` or `SID` (the variables used for posting feedback).

    By default `user` is `nobody`, `out` is `/feedback/out` and `err` is `/feedback/err`.

    For example, `capture pre ./my_test` will execute `./my_test` as `nobody` and redirect stdout and stderr to `/feedback/out` and `/feedback/err`.

    If you need to run captured code as root, then use `capture -u root`.

* `asuser [-u user] CMD...`

    Ensures that environemnt variables `USER`, `HOME` and `PATH` are ok,
    removes `REC` and `SID` from the environemt and
    execute a command `CMD` as an user `user`.

* `pre [-c class] CMD...`

    Wraps the stdout of the command into &lt;pre&gt; HTML element
    and escapes any HTML inside. Can be chained, e.g.
    `capture pre ./my_assessment_code.sh arg1 arg2`
<commit_msg>Fix pre tag in readme<commit_after>A docker container that includes a stable Debian Linux and convenience commands for grading a student submission.
Commands include tools from capturing the test output to submitting a feedback back to the grading service.

This container is just a base and does not include tools for different programming and scripting languages.
Thus, actual grading/assessment containers should derive from this container via the FROM instruction in their Dockerfiles.

You can find many grading containers on [the apluslms page on docker hub](https://hub.docker.com/u/apluslms/).
Containers starting with `grade-` are relevant for this purpose.

Version of grading base has format `<major>.<minor>`.
Major is updated when there is backwards incompatible change.
For example, when deprecated tool is removed.
Minor number is updated every time there is something new, where that bug fixes, added features or update on the debian base image.
Derived containers typically use format `<tool version>-<garding-base version>u<update>`,
where tool version is the version from upstream, grading-base is the version of this container and update is number that indicates update on containerisation.
So, for example, grade-python `3.5-2.2u1` means that there is python 3.5 on top of grading-base 2.2 and it's first update after initial release.
Update part is optional and can be omitted.

# The container entry point, the grade wrapper

Container has grade wrapper `/gw` set as the entry point.
This means that everything executed within this container (or derivative) is executed through this script.

The wrapper will take care of redirecting output (stdout and stderr) to `/feedback/grading-script-errors`.
In addition, the script will make sure that the working directory is set correctly.
After the grading script has been executed, the wrapper will execute `grade`.
Thus, the grading script does not need to call `cd` or `grade` anymore.

The wrapper has three different operations, based on the first argument.

1. If the first argument starts with `/bin/` or is `--exec`,
   then arguments are executed and the wrapper itself stops here.
   No redirections are done and `grade` is not executed.

2. If the first argument is `--sh`, then rest of the arguments are evaluated with `sh -c "$*"`.
   This makes strings with quoted text possible in mooc-grader environment.

3. The typical case. Argument list is executed as is.

The exit code from the grading script is stored in the grading-script-errors, but the grade wrapper always exits with 0.

# Filesystem layout

* `/submission/user`

    Files for the solution submitted by the student are stored here.
    This path can be used as working directory.

* `/exercise`

    Exercise files are mounted here in a read only mode.
    With mooc-grader, that means the path you entered in `mount`.
    Typically, this includes `run.sh` and unit test files.

* `/feedback`

    Grading script should store feedback in this path.
    Most utility commands do so, including `capture`, `testcase` and `grade`.
    In the future, mooc-grader will read files from this path instead of expecting a post request.

    * `/feedback/points`:

        Final points.
        Valid format for the data is `<points>/<max_points>` e.g. `5/10`.
        You can use `points` to update this file.
        Points are read by `grade`.

    * `/feedback/out`:

        Feedback that is going be presented in the LMS.
        Typically, data is in html format.
        You should use `pre` to wrap plain text to html.
        You can capture feedback with `capture pre <command>`, for example.

    * `/feedback/err`:

        Error messages from a student or a testing code.
        If present, `grade` will append this inside a pre tag at the end of the out file.
        This file typically contains stderr from the test code.
        For example, `capture` redirects stderr to this file.
        If stderr is normal output (e.g. with python unit tests), then you should consider using `err-to-out`.

    * `/feedback/grading-script-errors`:

        Errors that should be visible only to the staff.
        This file is added as a part of `grading_data` with key `errors` and send to the grading service.
        Then, data can be shown in the LMS to the course staff.
        Data is expected to be plain text messages from `run.sh` and other tools.
        By default, `/gw` redirects stdout and stderr from the `run.sh` to this file.

    * `/feedback/submission-set-error`:

        If this file contains `true`, then the submission is set in an error state in the LMS.
        You can use `set-error` in your script to set this file.

* `/feedback/<number>`

    A single feedback item.
    A set of these directories is considered the feedback list.
    Typically, one folder matches one test case.
    For now, this feedback list is not fully supported and the tool `create-test-feedback` is provided to render these directories to `/feedback/out`.
    Nevertheless, this allows building tools and scripts that export feedback in this format.
    In future, different templates can be used to render the feedback list in the grading service.
    The `grade` tool will automatically merge these directories to a single html file, if grading service doesn't support feedback as a list.

    For every numbered path (feedback item), there can exists any number of files, but following files are typical.
    Following files are supported by `create-test-feedback` and a basic template on the grading service.
    More advanced or specific templates can of course deviate from those.

    * `.../title`: A title or a display name for this feedback item.
    * `.../status`: The status of this feedback. Valid values: `ignored`, `skipped`, `passed`, `failed`, `error`.
    * `.../points`: Points given from this item.
    * `.../max_points`: Maximum points that could be given from this item.
    * `.../out.txt`: Stdout from the test.
    * `.../err.txt`: Stderr from the test.


# Utility commands

Following utility commands are provided in the path.

* `testcase [-t title] [-p points_on_success] [-s only_if_zero] CMD...`

    Defines a single test case.
    Useful when running multiple commands for grading.
    Creates `/feedback/<number>` directory with increasing number for every call.

    If `title` is provided, it's stored in `/feedback/<number>/title`.

    If `points_on_success` is provided, it will be written to `/feedback/<number>/max_points`.
    If CMD exits with 0, then it will also be written to `/feedback/<number>/points`.

    If `only_if_zero` is provided and not 0, then CMD is not executed and `testcase` exits with non-zero exit code.

    Status of this test is stored in `/feedback/<number>/status` accordingly.

* `capture [-o out] [-e err] [-u user] CMD...`

    Changes the ownership of the working directory to `user`,
    executes the command as `user`,
    and captures the stdout to `out` and the stderr to `err`.
    In addition, `capture` ensures that the environment does not contain `REC` or `SID` (the variables used for posting feedback).

    By default `user` is `nobody`, `out` is `/feedback/out` and `err` is `/feedback/err`.

    For example, `capture pre ./my_test` will execute `./my_test` as `nobody` and redirect stdout and stderr to `/feedback/out` and `/feedback/err`.

    If you need to run captured code as root, then use `capture -u root`.

* `asuser [-u user] CMD...`

    Ensures that environemnt variables `USER`, `HOME` and `PATH` are ok,
    removes `REC` and `SID` from the environemt and
    execute a command `CMD` as an user `user`.

* `pre [-c class] CMD...`

    Wraps the stdout of the command into `<pre>` HTML element and escapes any HTML inside.
    Can be chained, e.g. `capture pre ./my_assessment_code.sh arg1 arg2`

{'fraction_non_alphanumeric': 0.07696228338430174, 'fraction_numerical': 0.0025484199796126403, 'mean_word_length': 3.3349903341618337, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 32, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6138469', 'n_tokens_mistral': 4326, 'n_tokens_neox': 4062, 'n_words': 2248}