Commit 099b64b0 authored by Siebers, Michael's avatar Siebers, Michael
Browse files

Merge branch '23-automate-api-tests' into 'master'

Resolve "Automate API-tests"

Closes #62, #52, #51, and #23

See merge request cogsys/dare2del/demonstrator!22
parents e910aa1c 3146834c
stages:
- test
- unit_test1
- unit_test2
- integration_test
- pre_build
- build
- validate
- deploy
variables:
SWI_VERSION: 8.2.2
CONTAINER_DEPLOY_IMAGE: "webapi"
SYSTEM_TEST_IMAGE: "testing/system"
FORCE_UNIT_TESTS:
value: "no"
description: >
Change this variable to "yes" to run unit tests whether required or not.
Per default, unit tests run fully for tag commits, run fully for commits
on the default branch, and run for MR pipelines targetting the default
branch if files depended on have changed. If forced, unit tests run for
all MR pipelines if files depended on have changed and run fully for all
commits on branches without MR.
FORCE_INTEGRATION_TESTS:
value: "no"
description: >
Change this variable to "yes" to run integration tests whether required or
not. Per default, integration tests run fully for tag commits, run fully
for commits on the default branch, and run for MR pipelines targetting the
default branch if files depended on have changed. If forced, integration
tests run for all MR pipelines if files depended on have changed and run
fully for all commits on branches without MR.
FORCE_SYSTEM_TESTS:
value: "no"
description: >
Change this variable to "yes" to run system tests whether required or
not. Per default, system tests run for tag commits, commits on the default
branch, and MR pipelines targetting the default branch. If forced, system
tests run for all MR pipelines and all commits on branches without MR.
FORCE_DOCKER_BUILD:
value: "no"
description: >
Change this variable to "yes" to build a docker image for branches other
than the default branch.
# NOTE: Several of job's rules could be simplified or easier to understand by
# using workflow:variables. However, this feature is currently not
# available at our GitLab server.
#
# Assuming all variables are initialized to "no", the following might
# do the trick.
#
# workflow:
# rules:
# - if: $CI_PIPELINE_SOURCE == "merge_request_event"
# && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
# variables:
# MERGE_TO_MASTER: "yes"
# - if: $CI_PIPELINE_SOURCE == "merge_request_event"
# variables:
# MERGE_TO_OTHER: "yes"
# - if: $CI_COMMIT_TAG
# variables:
# CREATE_TAG: "yes"
# - if: $CI_PIPELINE_SOURCE == "push"
# && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
# variables:
# PUSH_TO_MASTER: "yes"
# - if: $CI_PIPELINE_SOURCE == "push"
# && ($CI_OPEN_MERGE_REQUESTS == null || $CI_OPEN_MERGE_REQUESTS == "")
# variables:
# PUSH_TO_OTHER: "yes"
# PUSH_TO_OTHER_WITHOUT_MR: "yes"
# - if: $CI_PIPELINE_SOURCE == "push"
# variables:
# PUSH_TO_OTHER: "yes"
# PUSH_TO_OTHER_WITH_MR: "yes"
#
# Template for Prolog test jobs
.prolog_test:
image: swipl:$SWI_VERSION
stage: test
script:
- swipl -s "tests/${TEST_FILE}" -t "run_all_tests" > "${REPORT_PATH}"
- swipl "tests/plunit/${TEST_FILE}" > "${REPORT_PATH}"
timeout: 15m
artifacts:
paths:
......@@ -22,74 +93,168 @@ variables:
test_theory_common:
extends: .prolog_test
stage: unit_test1
variables:
TEST_FILE: irrelevance_common.plt
REPORT_PATH: coverage_irrelevance_common
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" || ( $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH )
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& ( $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
|| $FORCE_UNIT_TESTS == "yes" )
changes:
- src/version.pl
- irrelevance_common.pl
- tests/irrelevance_common.plt
- tests/test_utils.pl
- tests/data_theory_common.pl
- tests/plunit/irrelevance_common.plt
- tests/plunit/test_utils.pl
- tests/plunit/data_theory_common.pl
- if: $CI_COMMIT_TAG
- when: never
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "push"
&& ($CI_OPEN_MERGE_REQUESTS == null || $CI_OPEN_MERGE_REQUESTS == "")
&& $FORCE_UNIT_TESTS == "yes"
test_web_api:
extends: .prolog_test
stage: unit_test2
variables:
TEST_FILE: web_api.plt
REPORT_PATH: coverage_web_api
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" || ( $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH )
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& ( $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
|| $FORCE_UNIT_TESTS == "yes" )
changes:
- src/version.pl
- src/web_api.pl
- src/web_api/*.pl
- tests/web_api.plt
- tests/test_utils.pl
- tests/web_api/*.plt
- tests/plunit/web_api.plt
- tests/plunit/test_utils.pl
- tests/plunit/web_api/*.plt
- if: $CI_COMMIT_TAG
- when: never
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "push"
&& ($CI_OPEN_MERGE_REQUESTS == null || $CI_OPEN_MERGE_REQUESTS == "")
&& $FORCE_UNIT_TESTS == "yes"
test_types:
extends: .prolog_test
stage: unit_test2
variables:
TEST_FILE: types.plt
REPORT_PATH: coverage_types
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" || ( $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH )
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& ( $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
|| $FORCE_UNIT_TESTS == "yes" )
changes:
- src/version.pl
- src/types.pl
- tests/types.plt
- tests/types/*.plt
- tests/test_utils.pl
- tests/plunit/types.plt
- tests/plunit/types/*.plt
- tests/plunit/test_utils.pl
- if: $CI_COMMIT_TAG
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "push"
&& ($CI_OPEN_MERGE_REQUESTS == null || $CI_OPEN_MERGE_REQUESTS == "")
&& $FORCE_UNIT_TESTS == "yes"
needs: []
.test_start_stop:
image: swipl:$SWI_VERSION
stage: integration_test
variables:
START_SCRIPT: undefined
timeout: 5m
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& ( $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
|| $FORCE_INTEGRATION_TESTS == "yes" )
changes:
- $START_SCRIPT
- app_common.pl
- src/**/*.pl
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& $FORCE_INTEGRATION_TESTS == "yes"
- if: $CI_COMMIT_TAG
- when: never
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "push"
&& ($CI_OPEN_MERGE_REQUESTS == null || $CI_OPEN_MERGE_REQUESTS == "")
&& $FORCE_INTEGRATION_TESTS == "yes"
test_interactive:start_stop:
extends: .test_start_stop
variables:
START_SCRIPT: run.pl
script:
- swipl -t server_stop $START_SCRIPT
test_daemon:start_stop:
extends: .test_start_stop
variables:
START_SCRIPT: daemon.pl
script:
- swipl $START_SCRIPT --user nobody
- swipl $START_SCRIPT --shutdown
container:build:
stage: build
script:
- "docker build --tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA} ."
- docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" ${CI_REGISTRY}
- docker image pull "${CI_REGISTRY_IMAGE}/${CONTAINER_DEPLOY_IMAGE}:latest" || true
- docker image pull "${CI_REGISTRY_IMAGE}/${CONTAINER_DEPLOY_IMAGE}:$CI_COMMIT_REF_SLUG" || true
- "docker build --tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA} ${CACHE_OPTION} ."
- "docker push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}"
tags:
- docker
rules:
- if: $CI_COMMIT_TAG
variables:
CACHE_OPTION: --no-cache
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == "$CI_DEFAULT_BRANCH"
variables:
CACHE_OPTION: --cache-from "${CI_REGISTRY_IMAGE}/${CONTAINER_DEPLOY_IMAGE}:latest"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH
&& $FORCE_DOCKER_BUILD == "yes"
variables:
CACHE_OPTION: --cache-from "${CI_REGISTRY_IMAGE}/${CONTAINER_DEPLOY_IMAGE}:latest" --cache-from "${CI_REGISTRY_IMAGE}/${CONTAINER_DEPLOY_IMAGE}:${CI_COMMIT_REF_SLUG}"
container:validate:
stage: validate
image:
name: byrnedo/alpine-curl
name: postman/newman:5.2.3-alpine
entrypoint: ["/bin/sh", "-c"]
services:
- name: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}
alias: tested_container
alias: webapi
before_script:
- node --version
- newman --version
script:
- curl -fsS --location --output /dev/null --retry 50 --retry-delay 5 --retry-connrefused --retry-max-time 300 "http://tested_container/state"
needs: ["container:build"]
- newman run tests/container/up_and_running.json -e tests/container/env.json --reporters junit --reporter-junit-export="container-report.xml" --bail
rules:
- if: $CI_COMMIT_TAG
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH
&& $FORCE_DOCKER_BUILD == "yes"
needs:
- job: "container:build"
artifacts: false
artifacts:
when: always
reports:
junit: container-report.xml
container:deploy:
......@@ -97,27 +262,42 @@ container:deploy:
script:
- docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" ${CI_REGISTRY}
- "docker image pull ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}"
- "docker tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA} ${CI_REGISTRY_IMAGE}/${DEPLOY_IMAGE}:${DEPLOY_TAG}"
- "docker push ${CI_REGISTRY_IMAGE}/${DEPLOY_IMAGE}:${DEPLOY_TAG}"
- "docker tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA} ${CI_REGISTRY_IMAGE}/${CONTAINER_DEPLOY_IMAGE}:${DEPLOY_TAG}"
- "docker push ${CI_REGISTRY_IMAGE}/${CONTAINER_DEPLOY_IMAGE}:${DEPLOY_TAG}"
- "docker logout ${DEPLOY_REGISTRY}"
variables:
DEPLOY_IMAGE: "webapi"
tags:
- docker
rules:
- if: $CI_COMMIT_TAG
variables:
DEPLOY_TAG: $CI_COMMIT_REF_SLUG
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
variables:
DEPLOY_TAG: latest
- if: $CI_COMMIT_BRANCH
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH
&& $FORCE_DOCKER_BUILD == "yes"
variables:
DEPLOY_TAG: $CI_COMMIT_REF_SLUG
- when: never
standalone documentation:
documentation:prepare_container:
stage: pre_build
script:
- "true" # dummy for now
tags:
- docker
rules:
- if: $CI_COMMIT_TAG
variables:
CACHE_OPTION: --no-cache
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
variables:
CACHE_OPTION: --cache-from "${CI_REGISTRY_IMAGE}/${SYSTEM_TEST_IMAGE}:${CI_COMMIT_REF_SLUG}"
documentation:build:
stage: build
image: swipl:$SWI_VERSION
variables:
......@@ -129,18 +309,182 @@ standalone documentation:
- pip3 install lxml
- utils/generate_documentation.sh "$BUILD_DIR" "webapi"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" || ( $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "$CI_DEFAULT_BRANCH" )
changes:
- "*.pl"
- "doc/**/*"
- "src/**/*"
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == "$CI_DEFAULT_BRANCH"
variables:
NAME: latest
- if: $CI_COMMIT_TAG
variables:
NAME: $CI_COMMIT_REF_SLUG
- when: never
artifacts:
paths: ["${BUILD_DIR}/webapi-docs.zip"]
name: "webapi-${NAME}-docs"
dependencies: []
needs: ["documentation:prepare_container"]
system_test:prepare_container:
stage: pre_build
variables:
CACHE_OPTION: --cache-from "${CI_REGISTRY_IMAGE}/${SYSTEM_TEST_IMAGE}:${CI_COMMIT_REF_SLUG}"
script:
- docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" ${CI_REGISTRY}
- docker image pull "${CI_REGISTRY_IMAGE}/${SYSTEM_TEST_IMAGE}:${CI_COMMIT_REF_SLUG}" || true
- docker build --tag "${CI_REGISTRY_IMAGE}/${SYSTEM_TEST_IMAGE}:${CI_COMMIT_REF_SLUG}" ${CACHE_OPTION} --build-arg "SWI_VERSION=$SWI_VERSION" - < docker/Dockerfile.system_test
- docker push "${CI_REGISTRY_IMAGE}/${SYSTEM_TEST_IMAGE}:${CI_COMMIT_REF_SLUG}"
tags:
- docker
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& $FORCE_SYSTEM_TESTS == "yes"
- if: $CI_COMMIT_TAG
variables:
CACHE_OPTION: --no-cache
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == "$CI_DEFAULT_BRANCH"
- if: $CI_PIPELINE_SOURCE == "push"
&& ($CI_OPEN_MERGE_REQUESTS == null || $CI_OPEN_MERGE_REQUESTS == "")
&& $FORCE_SYSTEM_TESTS == "yes"
.system_test:run:
stage: validate
image: ${CI_REGISTRY_IMAGE}/${SYSTEM_TEST_IMAGE}:${CI_COMMIT_REF_SLUG}
before_script:
- node --version
- newman --version
- swipl --version
script:
- swipl daemon.pl --user nobody
- newman run tests/api/${TEST_NAME}-tests.json -e tests/api/env.json --reporters junit --reporter-junit-export="api-report.xml"
- swipl daemon.pl --shutdown
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& $FORCE_SYSTEM_TESTS == "yes"
- if: $CI_COMMIT_TAG
- if: $CI_PIPELINE_SOURCE == "push"
&& $CI_COMMIT_BRANCH == "$CI_DEFAULT_BRANCH"
- if: $CI_PIPELINE_SOURCE == "push"
&& ($CI_OPEN_MERGE_REQUESTS == null || $CI_OPEN_MERGE_REQUESTS == "")
&& $FORCE_SYSTEM_TESTS == "yes"
needs: ["system_test:prepare_container"]
artifacts:
when: always
reports:
junit: api-report.xml
.system_test:run_with_data:
extends: .system_test:run
script:
- swipl daemon.pl --user nobody
- newman run tests/api/${TEST_NAME}-tests.json -e tests/api/env.json -d tests/api/${TEST_NAME}-data.json --reporters junit --reporter-junit-export="api-report.xml"
- swipl daemon.pl --shutdown
.system_test:run_with_data_and_db:
extends: .system_test:run
script:
- cp -f tests/api/${TEST_NAME}-theory_bg.db theory_bg.db
- chown webapi theory_bg.db
- swipl daemon.pl --user webapi
- newman run tests/api/${TEST_NAME}-tests.json -e tests/api/env.json -d tests/api/${TEST_NAME}-data.json --reporters junit --reporter-junit-export="api-report.xml"
- swipl daemon.pl --shutdown
.system_test:run_with_db:
extends: .system_test:run
script:
- cp -f tests/api/${TEST_NAME}-theory_bg.db theory_bg.db
- chown webapi theory_bg.db
- swipl daemon.pl --user webapi
- newman run tests/api/${TEST_NAME}-tests.json -e tests/api/env.json --reporters junit --reporter-junit-export="api-report.xml"
- swipl daemon.pl --shutdown
system_test:up:
extends: .system_test:run
variables:
TEST_NAME: up_and_serving
system_test:endpoint_bg@add:
extends: .system_test:run_with_data
variables:
TEST_NAME: endpoint_bg@add
system_test:endpoint_bg@remove:
extends: .system_test:run_with_data_and_db
variables:
TEST_NAME: endpoint_bg@remove
system_test:endpoint_bg@clear:
extends: .system_test:run_with_db
variables:
TEST_NAME: endpoint_bg@clear
system_test:endpoint_bg@show:
extends: .system_test:run_with_data_and_db
variables:
TEST_NAME: endpoint_bg@show
system_test:endpoint_irrelevant@file:
extends: .system_test:run_with_data_and_db
variables:
TEST_NAME: endpoint_irrelevant@file
allow_failure: true # see issue #63
system_test:endpoint_explain:
extends: .system_test:run_with_data_and_db
variables:
TEST_NAME: endpoint_explain
allow_failure: true # see issue #63
system_test:robust against wrong method:
extends: .system_test:run_with_data
variables:
TEST_NAME: robust_wrong_method
system_test:robust against wrong body:
extends: .system_test:run_with_data
variables:
TEST_NAME: robust_wrong_content_payload
allow_failure: true # see issue #61
system_test:robust against superfluous payload:
extends: .system_test:run_with_data
variables:
TEST_NAME: robust_wrong_content_empty
allow_failure: true # see issue #61
system_test:bg robust against non-item payload:
extends: .system_test:run_with_data
variables:
TEST_NAME: robust_bg_non_item_payload
system_test:irrelevant robust against non-path payload:
extends: .system_test:run_with_data
variables:
TEST_NAME: robust_irrelevant@file_non_path_payload
allow_failure: true # see issue #64
system_test:explain robust against non-path payload:
extends: .system_test:run_with_data
variables:
TEST_NAME: robust_explain_non_path_payload
# If no FORCE_... variable is set to "yes", no pipeline is created for merge
# requests targetting a non-default branch. Thus, the MR cannot be merged. This
# dummy job remedies the missing pipeline.
dummy for MR:
stage: deploy
script: ["true"]
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
&& $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
&& $FORCE_UNIT_TESTS != "yes"
&& $FORCE_INTEGRATION_TESTS != "yes"
&& $FORCE_SYSTEM_TESTS != "yes"
&& $FORCE_DOCKER_BUILD != "yes"
......@@ -2,34 +2,42 @@
In this document, we will describe the general input output systematics of the WebAPI and its defined endpoints for interaction. Each category will be detailed in its own section below. For each endpoint detailed in the sections, we will give the expected HTTP request method, handled parameters, the expected body, possible HTTP return codes, the response body on success, and give an example call using the [curl command line tool](https://curl.se/).
1. [JSON Types and Objects ](<#json_types>)
*Categories*:
2. [Background Knowledge Manipulation](<#bg>)
3. [Irrelevance](<#irrelevance>)
4. [Server Information](<#server>)
5. [Documentation](<#documentation>)
In general, the request bodies (if required) and responses are formatted as JSON documents.
Thus, we will present custom JSON types and objects used throughout the endpoint descriptions first.
For limitations on JSON parsing and generation see section [Limitations](<#limitations>).
The general input and output of the API is implemented with request/response methods that entail a body formatted as JSON. Therefore we will present custom JSON types and objects used throughout the endpoint descriptions first.
## JSON Types and Objects {#json_types}
Besides the usual JSON types (string, number, object, array, boolean, and null),
Besides the usual JSON types (string, integer, number, object, array, boolean, and null),
we use the following type definitions in this documentation:
$ integer: An integer number.
$ nonnegative integer: An integer greater than or equal to 0.
$ Path: A string specifying a path. Path delimiter is the slash =|"/"|=.
A Path is interpreted as pseudo-absolute path. That means that every
path is considered absolute and not interpreted relative to some
other path.
For example the path =|"A/B"|= is interpreted as =B= in
directory =A=, where =A= itself is in no other directory. Thus, =A=
is assumed to be _|a|_(!) root directory. The empty string (=|""|=)
is not a valid Path. The *nix root is represented by a single slash
(=|"/"|=). No other Path may end in a slash!
$ Path: A pseudo-absolute file system path (see [Path](<#json_path>)).
$ File: An object representing a file on disk (see [File](<#json_file>)).
$ Directory: An object representing a directory on disk (see [Directory](<#json_directory>)).
$ Item: An object representing a file or a directory on disk.
$ Manipulation Response: A family of objects used as response in background manipulation (see [Manipulation Response](<#json_response>)).
$ Item: An object representing either a file or a directory on disk.
$ Error Response: The response body returned if the server encounters an error (see [Error Response](<#json_error>)).
### Path {#json_path}
A _Path_ is a string specifying a file system path. Path delimiter is the slash =|"/"|=.
A Path is interpreted as pseudo-absolute path. That means that every
path is considered absolute and not interpreted relative to some
other path.
For example the path =|"A/B"|= is interpreted as =B= in
directory =A=, where =A= itself is in no other directory. Thus, =A=
is assumed to be _|a|_(!) root directory. The empty string (=|""|=)
is not a valid Path. The *nix root is represented by a single slash
(=|"/"|=). No other Path may end in a slash!
A _Path_ follows [this JSON schema](<schema/type-path-schema.json>).
### File {#json_file}
A file is represented as a JSON object with the following properties:
......@@ -56,26 +64,16 @@ A directory is represented as a JSON object with the following properties:
[JSON Example for a valid directory](<schema/type-directory-example.json>), accompanying schema definition [here](<schema/type-directory-schema.json>).
### Manipulation Response {#json_response}
The API response after a completed action is represented as a JSON object with the following properties:
| Property | Type | Example | Description |
| `Action` | nonnegative integer | =21= | The number of items to which `action` was successfully applied. |
| received | nonnegative integer | =42= | The number of items successfully parsed from the client's request. |
| skipped | nonnegative integer | =0= | The number of items which were not processed. |
This type is rather a family of types, as `Action` is a variable property name. The used property depends on the action taken. An instance of this type (for `Action` =removed=) may look as follows:
### Error Response {#json_error}
When a request does not succeed or the server encounters an error it returns with a status code outside the 200 range. This usually signals an error (in the 400 or 500 range). If the requested endpoint is not serving the documentation (see section [Documentation](<#documentation>)), the response body consists of a JSON object detailing the error.
```
{
"received": 1,
"removed": 1,
"skipped": 0
}
```
For the accompanying schema definition see [here](<schema/type-manipulation-response-schema.json>).
| Property | Type | Required | Example | Description |
| code | nonnegative integer | yes | =|400|= | The status code this error caused. _Must_ be the same as the returned status code. |
| location | string | no | =|"/doc/index.html"|= | The location this error refers to. |
| message | string | yes | =|"Unexpected end of request body"|= | A detailed message what caused the error. |
| method | string | no | =|"OPTIONS"|= | The HTTP method of the offending endpoint. |
[JSON Example for an error response](<schema/response-error-example.json>), accompanying schema definition [here](<schema/response-error-schema.json>).
## Background Knowledge Manipulation {#bg}
Background Knowledge Manipulation can be done via the endpoints ``/bg/show``, ``/bg/add``, ``/bg/remove`` and ``/bg/clear`` which are described below.
......@@ -97,7 +95,7 @@ None.
| --- | --- | --- | --- |
| Ok | `200`| Request successful | a JSON object with properties `item_count` and `list` |
The property `item_count` (_nonnegative integer_) contains the number of items stored in the background knowledge. All items in the background knowledge are listed in `list` (list of [item](<#json_types>)s).
The property `item_count` (_nonnegative integer_) contains the number of items stored in the background knowledge. All items in the background knowledge are listed in `list` (list of [item](<#json_types>)s). The response body follows this [JSON schema](</doc/schema/response-bg-show-schema.json>).
#### Example Call
......@@ -135,18 +133,28 @@ curl --request GET 'http://localhost:4444/bg/show'
| =|/bg/add|= | `no` | =POST= |
#### Parameters
None.
| Argument | Example | Required | Description |
| --- | --- | --- | --- |
| _item_ or an array of _item_ | _see example call_ | Required | Asserts the arguments to the background knowledge.|
#### Request Body
A JSON document consisting either of a single [item](<#json_types>) or an array of items.
#### Return value
| Case | Code | Description | Response Body |
| --- | --- | --- | --- |