├── docs ├── CNAME ├── favicon.ico ├── img │ ├── logo.png │ ├── MockintoshConfig.png │ └── logo_dark.svg ├── examples │ ├── templates │ │ ├── company.json.j2 │ │ ├── users.json.j2 │ │ └── index.html.j2 │ └── example.yaml ├── _config.yml ├── Gemfile └── Videos.md ├── mockintosh ├── hbs │ └── __init__.py ├── j2 │ ├── __init__.py │ └── meta.py ├── res │ ├── version.txt │ ├── mock.png │ └── sample.yml ├── services │ ├── __init__.py │ └── asynchronous │ │ └── _looping.py ├── __main__.py ├── constants.py ├── performance.py ├── params.py ├── ssl │ ├── cert.pem │ └── key.pem └── exceptions.py ├── tests ├── configs │ ├── empty.yaml │ ├── empty.json │ ├── yaml │ │ ├── hbs │ │ │ ├── data_dir_override │ │ │ │ └── .gitkeep │ │ │ ├── core │ │ │ │ ├── schema │ │ │ │ │ └── empty_schema.json │ │ │ │ ├── templates │ │ │ │ │ ├── hello.json.hbs │ │ │ │ │ └── date.json.hbs │ │ │ │ ├── escape_html.yaml │ │ │ │ ├── binary_request_body.yaml │ │ │ │ ├── counter.yaml │ │ │ │ ├── subexpression.yaml │ │ │ │ ├── no_templating_engine.yaml │ │ │ │ ├── use_templating_false_in_response.yaml │ │ │ │ ├── no_use_templating_no_templating_engine_in_response.yaml │ │ │ │ ├── no_templating_engine_in_response.yaml │ │ │ │ ├── templating_engine_in_response.yaml │ │ │ │ ├── cors.yaml │ │ │ │ ├── oas │ │ │ │ │ └── oas.json │ │ │ │ ├── random.yaml │ │ │ │ ├── connection_reset.yaml │ │ │ │ └── date.yaml │ │ │ ├── body │ │ │ │ ├── body_schema_error.json │ │ │ │ ├── body_schema.json │ │ │ │ └── config.yaml │ │ │ ├── kafka │ │ │ │ ├── value_schema_error.json │ │ │ │ ├── templates │ │ │ │ │ └── example.txt │ │ │ │ ├── dataset.json │ │ │ │ ├── value_schema.json │ │ │ │ └── config_error.yaml │ │ │ ├── path │ │ │ │ └── templates │ │ │ │ │ ├── 1.json.hbs │ │ │ │ │ ├── 3.json.hbs │ │ │ │ │ ├── 2.json.hbs │ │ │ │ │ ├── 4.json.hbs │ │ │ │ │ └── 5.json.hbs │ │ │ ├── headers │ │ │ │ └── templates │ │ │ │ │ ├── 2.json.hbs │ │ │ │ │ ├── 3.json.hbs │ │ │ │ │ ├── 5.json.hbs │ │ │ │ │ ├── 1.json.hbs │ │ │ │ │ └── 4.json.hbs │ │ │ ├── query_string │ │ │ │ ├── templates │ │ │ │ │ ├── 2.json.hbs │ │ │ │ │ ├── 3.json.hbs │ │ │ │ │ ├── 1.json.hbs │ │ │ │ │ ├── 5.json.hbs │ │ │ │ │ └── 4.json.hbs │ │ │ │ └── config.yaml │ │ │ ├── graphql │ │ │ │ ├── templates │ │ │ │ │ ├── resp3.json.hbs │ │ │ │ │ ├── resp2.json.hbs │ │ │ │ │ ├── resp4.json.hbs │ │ │ │ │ └── resp1.json.hbs │ │ │ │ ├── example.graphql │ │ │ │ └── config.yaml │ │ │ ├── common │ │ │ │ ├── templates │ │ │ │ │ ├── companies.json.hbs │ │ │ │ │ ├── user.json.hbs │ │ │ │ │ └── users.json.hbs │ │ │ │ └── config.yaml │ │ │ ├── status │ │ │ │ └── status_code.yaml │ │ │ ├── amqp_properties │ │ │ │ └── config.yaml │ │ │ └── management │ │ │ │ └── config.yaml │ │ └── j2 │ │ │ ├── body │ │ │ ├── body_schema_error.json │ │ │ ├── body_schema.json │ │ │ └── config.yaml │ │ │ ├── path │ │ │ └── templates │ │ │ │ ├── 1.json.j2 │ │ │ │ ├── 3.json.j2 │ │ │ │ ├── 2.json.j2 │ │ │ │ ├── 4.json.j2 │ │ │ │ └── 5.json.j2 │ │ │ ├── core │ │ │ ├── templates │ │ │ │ ├── hello.json.j2 │ │ │ │ └── date.json.j2 │ │ │ ├── escape_html.yaml │ │ │ ├── counter.yaml │ │ │ ├── subexpression.yaml │ │ │ ├── no_templating_engine.yaml │ │ │ ├── use_templating_false_in_response.yaml │ │ │ ├── no_use_templating_no_templating_engine_in_response.yaml │ │ │ ├── no_templating_engine_in_response.yaml │ │ │ ├── templating_engine_in_response.yaml │ │ │ ├── random.yaml │ │ │ └── date.yaml │ │ │ ├── headers │ │ │ └── templates │ │ │ │ ├── 2.json.j2 │ │ │ │ ├── 5.json.j2 │ │ │ │ ├── 1.json.j2 │ │ │ │ ├── 3.json.j2 │ │ │ │ └── 4.json.j2 │ │ │ ├── query_string │ │ │ ├── templates │ │ │ │ ├── 2.json.j2 │ │ │ │ ├── 3.json.j2 │ │ │ │ ├── 1.json.j2 │ │ │ │ ├── 5.json.j2 │ │ │ │ └── 4.json.j2 │ │ │ └── config.yaml │ │ │ ├── graphql │ │ │ ├── templates │ │ │ │ ├── resp3.json.j2 │ │ │ │ ├── resp2.json.j2 │ │ │ │ ├── resp4.json.j2 │ │ │ │ └── resp1.json.j2 │ │ │ ├── example.graphql │ │ │ └── config.yaml │ │ │ ├── common │ │ │ ├── templates │ │ │ │ ├── companies.json.j2 │ │ │ │ ├── user.json.j2 │ │ │ │ └── users.json.j2 │ │ │ └── config.yaml │ │ │ └── status │ │ │ └── status_code.yaml │ ├── json │ │ ├── hbs │ │ │ ├── management │ │ │ │ ├── .gitignore │ │ │ │ ├── dataset.json │ │ │ │ ├── new_service2.yaml │ │ │ │ ├── new_service1.yaml │ │ │ │ ├── new_service2.json │ │ │ │ ├── no_endpoints.json │ │ │ │ ├── new_service1.json │ │ │ │ ├── new_config.yaml │ │ │ │ ├── oas_documents │ │ │ │ │ ├── service1_no_servers.json │ │ │ │ │ └── service1.json │ │ │ │ ├── new_config.json │ │ │ │ ├── multiresponse_comma_tag.json │ │ │ │ ├── config_custom_oas4.json │ │ │ │ ├── config_custom_oas.json │ │ │ │ ├── config_custom_oas3.json │ │ │ │ ├── config_custom_oas2.json │ │ │ │ ├── new_resources.json │ │ │ │ ├── config.json │ │ │ │ └── resources.json │ │ │ ├── body │ │ │ │ ├── body_schema_error.json │ │ │ │ ├── body_schema.json │ │ │ │ └── config.json │ │ │ ├── path │ │ │ │ └── templates │ │ │ │ │ ├── 1.json.hbs │ │ │ │ │ ├── 3.json.hbs │ │ │ │ │ ├── 2.json.hbs │ │ │ │ │ ├── 4.json.hbs │ │ │ │ │ └── 5.json.hbs │ │ │ ├── core │ │ │ │ ├── templates │ │ │ │ │ ├── hello.json.hbs │ │ │ │ │ ├── date.json.hbs │ │ │ │ │ └── faker.json.hbs │ │ │ │ ├── image.png │ │ │ │ ├── no_templating_engine.json │ │ │ │ ├── empty_response_body.json │ │ │ │ ├── no_response_body_204.json │ │ │ │ ├── use_templating_false_in_response.json │ │ │ │ ├── faker.json │ │ │ │ ├── no_use_templating_no_templating_engine_in_response.json │ │ │ │ ├── no_templating_engine_in_response.json │ │ │ │ ├── templating_engine_in_response.json │ │ │ │ ├── two_services_one_with_hostname_one_without.json │ │ │ │ ├── endpoint_id_header.json │ │ │ │ ├── binary_response.json │ │ │ │ ├── undefined.json │ │ │ │ ├── ssl_true.json │ │ │ │ ├── multiple_services_on_same_port.json │ │ │ │ ├── date.json │ │ │ │ └── http_verbs.json │ │ │ ├── headers │ │ │ │ └── templates │ │ │ │ │ ├── 2.json.hbs │ │ │ │ │ ├── 3.json.hbs │ │ │ │ │ ├── 5.json.hbs │ │ │ │ │ ├── 1.json.hbs │ │ │ │ │ └── 4.json.hbs │ │ │ ├── query_string │ │ │ │ └── templates │ │ │ │ │ ├── 2.json.hbs │ │ │ │ │ ├── 3.json.hbs │ │ │ │ │ ├── 1.json.hbs │ │ │ │ │ ├── 5.json.hbs │ │ │ │ │ └── 4.json.hbs │ │ │ ├── common │ │ │ │ ├── templates │ │ │ │ │ ├── companies.json.hbs │ │ │ │ │ ├── user.json.hbs │ │ │ │ │ └── users.json.hbs │ │ │ │ └── config.json │ │ │ ├── status │ │ │ │ └── status_code.json │ │ │ └── performance │ │ │ │ └── config.json │ │ └── j2 │ │ │ ├── body │ │ │ ├── body_schema_error.json │ │ │ ├── body_schema.json │ │ │ └── config.json │ │ │ ├── path │ │ │ └── templates │ │ │ │ ├── 1.json.j2 │ │ │ │ ├── 3.json.j2 │ │ │ │ ├── 2.json.j2 │ │ │ │ ├── 4.json.j2 │ │ │ │ └── 5.json.j2 │ │ │ ├── core │ │ │ ├── templates │ │ │ │ ├── hello.json.j2 │ │ │ │ ├── date.json.j2 │ │ │ │ └── faker.json.j2 │ │ │ ├── no_templating_engine.json │ │ │ ├── use_templating_false_in_response.json │ │ │ ├── faker.json │ │ │ ├── no_use_templating_no_templating_engine_in_response.json │ │ │ ├── no_templating_engine_in_response.json │ │ │ ├── templating_engine_in_response.json │ │ │ ├── undefined.json │ │ │ └── date.json │ │ │ ├── headers │ │ │ └── templates │ │ │ │ ├── 2.json.j2 │ │ │ │ ├── 5.json.j2 │ │ │ │ ├── 1.json.j2 │ │ │ │ ├── 3.json.j2 │ │ │ │ └── 4.json.j2 │ │ │ ├── query_string │ │ │ └── templates │ │ │ │ ├── 2.json.j2 │ │ │ │ ├── 3.json.j2 │ │ │ │ ├── 1.json.j2 │ │ │ │ ├── 5.json.j2 │ │ │ │ └── 4.json.j2 │ │ │ ├── common │ │ │ ├── templates │ │ │ │ ├── companies.json.j2 │ │ │ │ ├── user.json.j2 │ │ │ │ └── users.json.j2 │ │ │ └── config.json │ │ │ └── status │ │ │ └── status_code.json │ ├── invalid │ ├── stats_unhandled_service2.yaml │ ├── stats_unhandled_service1.yaml │ ├── stats_config_service2.yaml │ ├── stats_unhandled_service2.json │ ├── stats_unhandled.yaml │ ├── missing_ssl_cert_file.json │ ├── stats_config_service2.json │ ├── stats_unhandled_service1.json │ ├── inaccessible_ssl_cert_file.json │ ├── stats_config_service1.yaml │ ├── fallback_to.yaml │ ├── stats_config_service1.json │ ├── stats_unhandled.json │ ├── stats_config.yaml │ ├── internal_circular_fallback_to.json │ ├── fallback_to.json │ ├── stats_config.json │ └── stats_kafka.json ├── interceptingpackage │ ├── __init__.py │ └── interceptors.py ├── conftest.py ├── test-openapi-transpiler.sh ├── assets_copy_kafka_to_gpubsub.py ├── assets_copy_kafka_to_amqp.py ├── assets_copy_kafka_to_amazonsqs.py ├── assets_copy_kafka_to_mqtt.py ├── assets_copy_kafka_to_redis.py └── test_exceptions.py ├── tests_integrated ├── subdir │ ├── empty_schema.json │ ├── kafka_payload1.txt │ ├── dataset.json │ ├── image.png │ ├── oas.json │ ├── cert.pem │ └── key.pem ├── custom_interceptors.py ├── acceptance.sh └── cors.html ├── .codacy.yml ├── .dockerignore ├── release.sh ├── Dockerfile.cloud ├── ps.sh ├── MANIFEST.in ├── .coveragerc ├── setup.cfg ├── requirements.txt ├── Dockerfile ├── msi.sh ├── LICENSE ├── .travis.yml ├── msi.py └── .gitignore /docs/CNAME: -------------------------------------------------------------------------------- 1 | mockintosh.io -------------------------------------------------------------------------------- /mockintosh/hbs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mockintosh/j2/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/configs/empty.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mockintosh/res/version.txt: -------------------------------------------------------------------------------- 1 | 0.13.17 -------------------------------------------------------------------------------- /mockintosh/services/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/configs/empty.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /tests/interceptingpackage/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests_integrated/subdir/empty_schema.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/data_dir_override/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/schema/empty_schema.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/.gitignore: -------------------------------------------------------------------------------- 1 | res/ 2 | new_res/ 3 | -------------------------------------------------------------------------------- /tests/configs/invalid: -------------------------------------------------------------------------------- 1 | [ 2 | "hello world" ? "I'm invalid" 3 | ] 4 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/body/body_schema_error.json: -------------------------------------------------------------------------------- 1 | JSON Decode Error 2 | -------------------------------------------------------------------------------- /tests/configs/json/j2/body/body_schema_error.json: -------------------------------------------------------------------------------- 1 | JSON Decode Error 2 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/body/body_schema_error.json: -------------------------------------------------------------------------------- 1 | JSON Decode Error 2 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/body/body_schema_error.json: -------------------------------------------------------------------------------- 1 | JSON Decode Error 2 | -------------------------------------------------------------------------------- /mockintosh/__main__.py: -------------------------------------------------------------------------------- 1 | from mockintosh import initiate 2 | 3 | initiate() 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/kafka/value_schema_error.json: -------------------------------------------------------------------------------- 1 | JSON Decode Error 2 | -------------------------------------------------------------------------------- /.codacy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | exclude_paths: 3 | - "tests/**" 4 | - "tests_integrated/**" 5 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up9inc/mockintosh/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /docs/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up9inc/mockintosh/HEAD/docs/img/logo.png -------------------------------------------------------------------------------- /tests/configs/json/hbs/path/templates/1.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "var": "{{intoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/path/templates/1.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "var": "{{intoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/path/templates/1.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "var": "{{intoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/path/templates/1.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "var": "{{intoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/path/templates/3.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "capture": "{{varname}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/path/templates/3.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "capture": "{{varname}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/path/templates/3.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "capture": "{{varname}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/path/templates/3.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "capture": "{{varname}}" 3 | } 4 | -------------------------------------------------------------------------------- /mockintosh/res/mock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up9inc/mockintosh/HEAD/mockintosh/res/mock.png -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/templates/hello.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "{{ fake.first_name }}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/templates/hello.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "{{ fake.first_name() }}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/templates/hello.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "{{ fake.first_name() }}" 3 | } 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | */__pycache__ 2 | */.pytest_cache 3 | .idea 4 | .git 5 | tests 6 | .coveragerc 7 | !tests/*.sh -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/templates/hello.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "{{ fake "first_name" }}" 3 | } 4 | -------------------------------------------------------------------------------- /tests_integrated/subdir/kafka_payload1.txt: -------------------------------------------------------------------------------- 1 | reaction value 2 | {{consumed.key}} 3 | {{consumed.value}} 4 | -------------------------------------------------------------------------------- /docs/img/MockintoshConfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up9inc/mockintosh/HEAD/docs/img/MockintoshConfig.png -------------------------------------------------------------------------------- /tests/configs/json/j2/headers/templates/2.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with parameter": "{{anyValIntoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/headers/templates/2.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with parameter": "{{anyValIntoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | git push --force https://${GH_TOKEN}@github.com/up9inc/mockintosh.git HEAD:gh-pages 3 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/headers/templates/2.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with parameter": "{{anyValIntoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/headers/templates/5.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "hdr4 request header": "{{request.headers.hdr4}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/query_string/templates/2.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with parameter": "{{anyValIntoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/headers/templates/2.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with parameter": "{{anyValIntoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/headers/templates/5.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "hdr4 request header": "{{request.headers.hdr4}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/query_string/templates/2.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with parameter": "{{anyValIntoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/headers/templates/3.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with regex capture group": "{{capturedVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/headers/templates/5.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "hdr4 request header": "{{request.headers.hdr4}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/path/templates/2.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "request": { 3 | "path": "{{request.path}}" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/query_string/templates/2.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with parameter": "{{anyValIntoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/headers/templates/1.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with static value": "{{request.headers.hdr1}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/headers/templates/3.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with regex capture group": "{{capturedVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/path/templates/2.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "request": { 3 | "path": "{{request.path}}" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/headers/templates/3.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with regex capture group": "{{capturedVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/headers/templates/5.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "hdr4 request header": "{{request.headers.hdr4}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/path/templates/2.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "request": { 3 | "path": "{{request.path}}" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/query_string/templates/2.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with parameter": "{{anyValIntoVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/headers/templates/1.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with static value": "{{request.headers.hdr1}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/headers/templates/3.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with regex capture group": "{{capturedVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/path/templates/2.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "request": { 3 | "path": "{{request.path}}" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests_integrated/subdir/dataset.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "var1": "val3" 4 | }, 5 | { 6 | "var1": "val4" 7 | } 8 | ] -------------------------------------------------------------------------------- /tests_integrated/subdir/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up9inc/mockintosh/HEAD/tests_integrated/subdir/image.png -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/up9inc/mockintosh/HEAD/tests/configs/json/hbs/core/image.png -------------------------------------------------------------------------------- /tests/configs/json/hbs/headers/templates/1.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with static value": "{{request.headers.hdr1}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/query_string/templates/3.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with regex capture group": "{{capturedVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/query_string/templates/3.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with regex capture group": "{{capturedVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/headers/templates/1.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with static value": "{{request.headers.hdr1}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/query_string/templates/3.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with regex capture group": "{{capturedVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/query_string/templates/3.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with regex capture group": "{{capturedVar}}" 3 | } 4 | -------------------------------------------------------------------------------- /docs/examples/templates/company.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{{ fake.company() }}", 3 | "address": "{{ fake.address() }}" 4 | } 5 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/path/templates/4.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "var1": "{{var1}}", 3 | "var2": "{{var2}}", 4 | "var3": "{{var3}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/query_string/templates/1.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with static value": "{{request.queryString.param1}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/query_string/templates/5.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "param4 request query string": "{{request.queryString.param4}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/path/templates/4.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "var1": "{{var1}}", 3 | "var2": "{{var2}}", 4 | "var3": "{{var3}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/json/j2/query_string/templates/1.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with static value": "{{request.queryString.param1}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/json/j2/query_string/templates/5.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "param4 request query string": "{{request.queryString.param4}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/path/templates/4.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "var1": "{{var1}}", 3 | "var2": "{{var2}}", 4 | "var3": "{{var3}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/query_string/templates/1.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "matched with static value": "{{request.queryString.param1}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/query_string/templates/5.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "param4 request query string": "{{request.queryString.param4}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/path/templates/4.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "var1": "{{var1}}", 3 | "var2": "{{var2}}", 4 | "var3": "{{var3}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/query_string/templates/1.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "matched with static value": "{{request.queryString.param1}}" 3 | } 4 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/query_string/templates/5.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "param4 request query string": "{{request.queryString.param4}}" 3 | } 4 | -------------------------------------------------------------------------------- /Dockerfile.cloud: -------------------------------------------------------------------------------- 1 | FROM up9inc/mockintosh:latest 2 | 3 | WORKDIR /usr/src/mockintosh 4 | 5 | RUN pip3 install .[cloud] 6 | 7 | WORKDIR /tmp 8 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | title: " " 2 | theme: jekyll-theme-minimal 3 | logo: /img/logo.png 4 | google_analytics: UA-199507050-1 5 | repository: up9inc/mockintosh -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/graphql/templates/resp3.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "hero": { 4 | "name": "{{ name_eq }}" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/graphql/templates/resp3.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "hero": { 4 | "name": "{{ name_eq }}" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/kafka/templates/example.txt: -------------------------------------------------------------------------------- 1 | Some text 2 | {{ fake.random_digit }} 3 | Some other text 4 | {{ fake.random_int min=10 max=90 step=5 }} 5 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.hookimpl(hookwrapper=True) 5 | def pytest_runtest_protocol(item, nextitem): 6 | item.cls._item = item 7 | yield 8 | -------------------------------------------------------------------------------- /tests/configs/json/j2/body/body_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "somekey": {} 5 | }, 6 | "required": [ 7 | "somekey" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /tests/configs/json/j2/path/templates/5.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "var1": "{{var1}}", 3 | "var2": "{{var2}}", 4 | "var3": "{{var3}}", 5 | "var4": "{{var4}}", 6 | "var5": "{{var5}}" 7 | } 8 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/kafka/dataset.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "var1": "val1" 4 | }, 5 | { 6 | "var1": "val2" 7 | }, 8 | { 9 | "var1": "val3" 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/body/body_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "somekey": {} 5 | }, 6 | "required": [ 7 | "somekey" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/path/templates/5.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "var1": "{{var1}}", 3 | "var2": "{{var2}}", 4 | "var3": "{{var3}}", 5 | "var4": "{{var4}}", 6 | "var5": "{{var5}}" 7 | } 8 | -------------------------------------------------------------------------------- /ps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true 4 | do 5 | sleep 720 6 | echo Below is the container list 7 | docker ps 8 | echo Below is the process list 9 | ps auxff 10 | done 11 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/body/body_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "somekey": {} 5 | }, 6 | "required": [ 7 | "somekey" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/dataset.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "var1": "val1" 4 | }, 5 | { 6 | "var1": "val2" 7 | }, 8 | { 9 | "var1": "val3" 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/path/templates/5.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "var1": "{{var1}}", 3 | "var2": "{{var2}}", 4 | "var3": "{{var3}}", 5 | "var4": "{{var4}}", 6 | "var5": "{{var5}}" 7 | } 8 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/body/body_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "somekey": {} 5 | }, 6 | "required": [ 7 | "somekey" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/kafka/value_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "somekey": {} 5 | }, 6 | "required": [ 7 | "somekey" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/path/templates/5.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "var1": "{{var1}}", 3 | "var2": "{{var2}}", 4 | "var3": "{{var3}}", 5 | "var4": "{{var4}}", 6 | "var5": "{{var5}}" 7 | } 8 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # Include the license file 2 | include LICENSE 3 | 4 | # Include the requirements.txt 5 | include requirements.txt 6 | 7 | # Include the JSON schema 8 | include mockintosh/schema.json 9 | -------------------------------------------------------------------------------- /tests/configs/json/j2/headers/templates/4.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "request.headers.hdr1": "{{request.headers.hdr1}}", 3 | "anyValIntoVar": "{{anyValIntoVar}}", 4 | "capturedVar": "{{capturedVar}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/headers/templates/4.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "request.headers.hdr1": "{{request.headers.hdr1}}", 3 | "anyValIntoVar": "{{anyValIntoVar}}", 4 | "capturedVar": "{{capturedVar}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/headers/templates/4.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "request.headers.hdr1": "{{request.headers.hdr1}}", 3 | "anyValIntoVar": "{{anyValIntoVar}}", 4 | "capturedVar": "{{capturedVar}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/graphql/templates/resp2.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "hero": { 4 | "name": "{{ name_eq }} brother", 5 | "age": {{ random.int age_gt 50 }} 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/headers/templates/4.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "request.headers.hdr1": "{{request.headers.hdr1}}", 3 | "anyValIntoVar": "{{anyValIntoVar}}", 4 | "capturedVar": "{{capturedVar}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/graphql/templates/resp2.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "hero": { 4 | "name": "{{ name_eq }} brother", 5 | "age": {{ random.int(age_gt, 50) }} 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/query_string/templates/4.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "request.queryString.param1": "{{request.queryString.param1}}", 3 | "anyValIntoVar": "{{anyValIntoVar}}", 4 | "capturedVar": "{{capturedVar}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/json/j2/query_string/templates/4.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "request.queryString.param1": "{{request.queryString.param1}}", 3 | "anyValIntoVar": "{{anyValIntoVar}}", 4 | "capturedVar": "{{capturedVar}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/query_string/templates/4.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "request.queryString.param1": "{{request.queryString.param1}}", 3 | "anyValIntoVar": "{{anyValIntoVar}}", 4 | "capturedVar": "{{capturedVar}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/graphql/templates/resp4.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "hero": { 4 | "name": "{{ name_eq }} brother", 5 | "city": "{{ fake.address() | replace('\n','\\n') }}" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/query_string/templates/4.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "request.queryString.param1": "{{request.queryString.param1}}", 3 | "anyValIntoVar": "{{anyValIntoVar}}", 4 | "capturedVar": "{{capturedVar}}" 5 | } 6 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/common/templates/companies.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "companies": [ 3 | { 4 | "name": "{{ fake.company }}", 5 | "motto": "{{ fake.catch_phrase }}" 6 | } 7 | ], 8 | "total": 2 9 | } 10 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/common/templates/companies.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "companies": [ 3 | { 4 | "name": "{{ fake.company }}", 5 | "motto": "{{ fake.catch_phrase }}" 6 | } 7 | ], 8 | "total": 2 9 | } 10 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/graphql/templates/resp4.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "hero": { 4 | "name": "{{ name_eq }} brother", 5 | "city": "{{ replace ( fake.address ) old='\n' new='\\n' }}" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/graphql/example.graphql: -------------------------------------------------------------------------------- 1 | query HeroNameAndFriends { 2 | hero( 3 | where: {name: {_eq: "{{regEx '.*' 'name_eq'}}"}, _and: {age: {_gt: {{regEx '.*' 'age_gt'}}}}} 4 | ) { 5 | name 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/graphql/example.graphql: -------------------------------------------------------------------------------- 1 | query HeroNameAndFriends { 2 | hero( 3 | where: {name: {_eq: "{{regEx('.*', 'name_eq')}}"}, _and: {age: {_gt: {{regEx('.*', 'age_gt')}}}}} 4 | ) { 5 | name 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/escape_html.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Jinja2 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/endp1" 7 | method: GET 8 | response: "{{ escapeHtml('& < \" >') }}" 9 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/escape_html.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Handlebars 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/endp1" 7 | method: GET 8 | response: "{{ escapeHtml '& < \" >' }}" 9 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/counter.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Jinja2 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/counter" 7 | method: GET 8 | response: "Hello {{counter('counterName')}} world" 9 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/binary_request_body.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Handlebars 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/endpoint1" 7 | method: POST 8 | response: "{{request.body.example}}" 9 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/counter.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Handlebars 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/counter" 7 | method: GET 8 | response: "Hello {{counter 'counterName'}} world" 9 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/common/templates/user.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "id": {{ id }}, 3 | "firstName": "{{ fake.first_name }}", 4 | "lastName": "{{ fake.last_name }}", 5 | "friends": [ 6 | { 7 | "id": "{{ random.uuid4 }}" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/common/templates/user.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "id": {{ id }}, 3 | "firstName": "{{ fake.first_name }}", 4 | "lastName": "{{ fake.last_name }}", 5 | "friends": [ 6 | { 7 | "id": "{{ random.uuid4 }}" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/subexpression.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Jinja2 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/subexpression" 7 | method: GET 8 | response: "{{random.float(1.0, 2.0, random.int(1, 5))}}" 9 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/subexpression.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Handlebars 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/subexpression" 7 | method: GET 8 | response: "{{random.float 1.0 2.0 (random.int 1 5)}}" 9 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = mockintosh 3 | 4 | [report] 5 | exclude_lines = 6 | # Have to re-enable the standard pragma 7 | pragma: no cover 8 | 9 | # Don't complain if tests don't hit defensive assertion code: 10 | raise NotImplementedError 11 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/new_service2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Mock for Service2 3 | hostname: service2.example.com 4 | port: 8002 5 | managementRoot: __admin 6 | endpoints: 7 | - path: "/changed-endpoint/{{var}}" 8 | method: GET 9 | response: 'var: {{var}}' 10 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/no_templating_engine.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/{{regEx '(.*)' 'varname'}}" 8 | method: GET 9 | response: "{{varname}}" 10 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/no_templating_engine.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/{{regEx('(.*)', 'varname')}}" 8 | method: GET 9 | response: "{{varname}}" 10 | -------------------------------------------------------------------------------- /tests/configs/json/j2/common/templates/companies.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "companies": [{% for n in range(5) %} 3 | { 4 | "name": "{{ fake.company() }}", 5 | "motto": "{{ fake.catch_phrase() }}" 6 | }{% if not loop.last %},{% endif %} 7 | {% endfor %}], 8 | "total": 2 9 | } 10 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/common/templates/companies.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "companies": [{% for n in range(5) %} 3 | { 4 | "name": "{{ fake.company() }}", 5 | "motto": "{{ fake.catch_phrase() }}" 6 | }{% if not loop.last %},{% endif %} 7 | {% endfor %}], 8 | "total": 2 9 | } 10 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/use_templating_false_in_response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/" 8 | method: GET 9 | response: 10 | useTemplating: false 11 | body: "@templates/hello.json.hbs" 12 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/use_templating_false_in_response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/" 8 | method: GET 9 | response: 10 | useTemplating: false 11 | body: "@templates/hello.json.j2" 12 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | python-tag = py3 3 | 4 | [flake8] 5 | ignore = E501, E701 6 | exclude = build,dist 7 | 8 | [tool:pytest] 9 | markers = kafka 10 | 11 | [metadata] 12 | author = UP9 Inc. 13 | author_email = support@up9.com 14 | 15 | [radon] 16 | exclude = tests/*,tests_integrated/*,build/* 17 | cc_min = B 18 | -------------------------------------------------------------------------------- /tests/configs/stats_unhandled_service2.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | - name: Mock for Service2 3 | port: 8002 4 | hostname: service2.example.com 5 | endpoints: 6 | - path: /service2z 7 | method: GET 8 | response: '' 9 | - path: /service2q 10 | method: GET 11 | queryString: 12 | a[]: b 13 | response: '' 14 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/new_service1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Mock for Service1 3 | hostname: service1.example.com 4 | port: 8001 5 | managementRoot: __admin 6 | endpoints: 7 | - path: "/service1" 8 | method: GET 9 | response: service1 10 | - path: "/service1-new-service" 11 | method: GET 12 | response: service1-new-service 13 | -------------------------------------------------------------------------------- /tests/configs/json/j2/common/templates/user.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "id": {{ id }}, 3 | "firstName": "{{ fake.first_name() }}", 4 | "lastName": "{{ fake.last_name() }}", 5 | "friends": [{% for n in range(range(5) | random) %} 6 | { 7 | "id": "{{ random.uuid4() }}" 8 | }{% if not loop.last %},{% endif %} 9 | {% endfor %}] 10 | } 11 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/common/templates/user.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "id": {{ id }}, 3 | "firstName": "{{ fake.first_name() }}", 4 | "lastName": "{{ fake.last_name() }}", 5 | "friends": [{% for n in range(range(5) | random) %} 6 | { 7 | "id": "{{ random.uuid4() }}" 8 | }{% if not loop.last %},{% endif %} 9 | {% endfor %}] 10 | } 11 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Jinja2==2.11.3 2 | markupsafe==2.0.1 3 | Faker==4.18.0 4 | tornado>=6.1 5 | PyYAML>=5.4 6 | jsonschema==3.2.0 7 | pybars4>=0.9.11 8 | accept-types==0.4.1 9 | jsonpath-ng==1.5.2 10 | httpx==0.23.0 11 | confluent-kafka>=1.6.1 12 | prance[osv]>=0.21.2 13 | pika>=1.2.0 14 | PyRSMQ>=0.4.5 15 | paho-mqtt>=1.5.1 16 | graphql-core>=3.1.5 17 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/new_service2.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Mock for Service2", 3 | "hostname": "service2.example.com", 4 | "port": 8002, 5 | "managementRoot": "__admin", 6 | "endpoints": [ 7 | { 8 | "path": "/changed-endpoint/{{var}}", 9 | "method": "GET", 10 | "response": "var: {{var}}" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/common/templates/users.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "users": [ 3 | { 4 | "id": {{ random.int 10000 100000 }}, 5 | "firstName": "{{ fake.first_name }}", 6 | "lastName": "{{ fake.last_name }}", 7 | "friends": [ 8 | { 9 | "id": "{{ random.uuid4 }}" 10 | } 11 | ] 12 | } 13 | ], 14 | "total": 1 15 | } 16 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/common/templates/users.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "users": [ 3 | { 4 | "id": {{ random.int 10000 100000 }}, 5 | "firstName": "{{ fake.first_name }}", 6 | "lastName": "{{ fake.last_name }}", 7 | "friends": [ 8 | { 9 | "id": "{{ random.uuid4 }}" 10 | } 11 | ] 12 | } 13 | ], 14 | "total": 1 15 | } 16 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/no_use_templating_no_templating_engine_in_response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/" 8 | method: GET 9 | response: 10 | headers: 11 | Content-Type: "application/json; charset=UTF-8" 12 | body: "@templates/hello.json.hbs" 13 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/no_use_templating_no_templating_engine_in_response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/" 8 | method: GET 9 | response: 10 | headers: 11 | Content-Type: "application/json; charset=UTF-8" 12 | body: "@templates/hello.json.j2" 13 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/no_templating_engine_in_response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/" 8 | method: GET 9 | response: 10 | headers: 11 | Content-Type: "application/json; charset=UTF-8" 12 | useTemplating: true 13 | body: "@templates/hello.json.hbs" 14 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/no_templating_engine_in_response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/" 8 | method: GET 9 | response: 10 | headers: 11 | Content-Type: "application/json; charset=UTF-8" 12 | useTemplating: true 13 | body: "@templates/hello.json.j2" 14 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/templating_engine_in_response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/" 8 | method: GET 9 | response: 10 | headers: 11 | Content-Type: "application/json; charset=UTF-8" 12 | templatingEngine: "Jinja2" 13 | body: "@templates/hello.json.j2" 14 | -------------------------------------------------------------------------------- /tests/configs/stats_unhandled_service1.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | - name: Mock for Service1 3 | port: 8001 4 | hostname: service1.example.com 5 | endpoints: 6 | - path: /service1x 7 | method: GET 8 | response: '' 9 | - path: /service1y 10 | method: GET 11 | headers: 12 | Example-Header: Example-Value 13 | queryString: 14 | a: b 15 | c: d 16 | response: '' 17 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/templating_engine_in_response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | - name: Mock for Service1 4 | hostname: service1.example.com 5 | port: 8001 6 | endpoints: 7 | - path: "/" 8 | method: GET 9 | response: 10 | headers: 11 | Content-Type: "application/json; charset=UTF-8" 12 | templatingEngine: "Handlebars" 13 | body: "@templates/hello.json.hbs" 14 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/no_templating_engine.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/{{regEx '(.*)' 'varname'}}", 10 | "method": "GET", 11 | "response": "{{varname}}" 12 | } 13 | ] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/no_templating_engine.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/{{regEx('(.*)', 'varname')}}", 10 | "method": "GET", 11 | "response": "{{varname}}" 12 | } 13 | ] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/empty_response_body.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/endpoint1", 10 | "method": "GET", 11 | "response": { 12 | "body": "" 13 | } 14 | } 15 | ] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/no_response_body_204.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/endpoint1", 10 | "method": "GET", 11 | "response": { 12 | "status": 204 13 | } 14 | } 15 | ] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9.7-alpine 2 | 3 | RUN apk add --no-cache gcc musl-dev librdkafka-dev 4 | 5 | WORKDIR /usr/src/mockintosh 6 | 7 | COPY requirements.txt . 8 | RUN pip3 install -r requirements.txt 9 | 10 | COPY setup.cfg . 11 | COPY setup.py . 12 | COPY README.md . 13 | COPY mockintosh/ ./mockintosh/ 14 | 15 | RUN pip3 install . 16 | 17 | WORKDIR /tmp 18 | RUN mockintosh --help 19 | 20 | ENTRYPOINT ["mockintosh"] 21 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/graphql/templates/resp1.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "hero": { 4 | "name": "{{ name_eq }}", 5 | "age": {{ random.int age_gt 50 }}, 6 | "friends": [ 7 | { 8 | "name": "Luke Skywalker" 9 | }, 10 | { 11 | "name": "Han Solo" 12 | }, 13 | { 14 | "name": "Leia Organa" 15 | } 16 | ] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/graphql/templates/resp1.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "hero": { 4 | "name": "{{ name_eq }}", 5 | "age": {{ random.int(age_gt, 50) }}, 6 | "friends": [ 7 | { 8 | "name": "Luke Skywalker" 9 | }, 10 | { 11 | "name": "Han Solo" 12 | }, 13 | { 14 | "name": "Leia Organa" 15 | } 16 | ] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/test-openapi-transpiler.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | petstore=tests/configs/oas/petstore.json 4 | COVERAGE_NO_RUN=true coverage run --parallel -m mockintosh $petstore && \ 5 | coverage run --parallel -m mockintosh $petstore -c dev.json json && \ 6 | coverage run --parallel -m mockintosh $petstore -c dev.yaml yaml && \ 7 | coverage run --parallel -m mockintosh $petstore -c dev.yaml && \ 8 | jsonschema -i dev.json mockintosh/schema.json || exit 1 9 | -------------------------------------------------------------------------------- /tests/configs/stats_config_service2.yaml: -------------------------------------------------------------------------------- 1 | name: Mock for Service2 2 | hostname: service2.example.com 3 | port: 8002 4 | managementRoot: __admin 5 | endpoints: 6 | - path: /service2 7 | method: GET 8 | response: service2 9 | - path: /service2-rst 10 | method: GET 11 | response: 12 | status: RST 13 | body: service2-rst 14 | - path: /service2-fin 15 | method: GET 16 | response: 17 | status: FIN 18 | body: service2-fin 19 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/cors.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Handlebars 3 | services: 4 | - name: Mock for Service1 5 | port: 8001 6 | endpoints: 7 | - path: /cors-request 8 | method: post 9 | body: 10 | schema: '@schema/empty_schema.json' 11 | response: 12 | status: 201 13 | - path: /cors-request-overridden 14 | method: options 15 | response: 16 | status: 401 17 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/no_endpoints.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "templatingEngine": "Handlebars", 9 | "services": [ 10 | { 11 | "name": "Mock for Service1", 12 | "hostname": "service1.example.com", 13 | "port": 8001, 14 | "managementRoot": "__admin", 15 | "endpoints": [] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/new_service1.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Mock for Service1", 3 | "hostname": "service1.example.com", 4 | "port": 8001, 5 | "managementRoot": "__admin", 6 | "endpoints": [ 7 | { 8 | "path": "/service1", 9 | "method": "GET", 10 | "response": "service1" 11 | }, 12 | { 13 | "path": "/service1-new-service", 14 | "method": "GET", 15 | "response": "service1-new-service" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/use_templating_false_in_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/", 10 | "method": "GET", 11 | "response": { 12 | "useTemplating": false, 13 | "body": "@templates/hello.json.hbs" 14 | } 15 | } 16 | ] 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/use_templating_false_in_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/", 10 | "method": "GET", 11 | "response": { 12 | "useTemplating": false, 13 | "body": "@templates/hello.json.j2" 14 | } 15 | } 16 | ] 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /docs/examples/templates/users.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "users": [{% for n in range(5) %} 3 | { 4 | "id": {{ random.int(10000, 100000) }}, 5 | "firstName": "{{ fake.first_name() }}", 6 | "lastName": "{{ fake.last_name() }}", 7 | "friends": [{% for n in range(range(5) | random) %} 8 | { 9 | "id": "{{ random.uuid4() }}" 10 | }{% if not loop.last %},{% endif %} 11 | {% endfor %}] 12 | }{% if not loop.last %},{% endif %} 13 | {% endfor %}], 14 | "total": 10 15 | } 16 | -------------------------------------------------------------------------------- /tests/configs/json/j2/common/templates/users.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "users": [{% for n in range(5) %} 3 | { 4 | "id": {{ random.int(10000, 100000) }}, 5 | "firstName": "{{ fake.first_name() }}", 6 | "lastName": "{{ fake.last_name() }}", 7 | "friends": [{% for n in range(range(5) | random) %} 8 | { 9 | "id": "{{ random.uuid4() }}" 10 | }{% if not loop.last %},{% endif %} 11 | {% endfor %}] 12 | }{% if not loop.last %},{% endif %} 13 | {% endfor %}], 14 | "total": 10 15 | } 16 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/common/templates/users.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "users": [{% for n in range(5) %} 3 | { 4 | "id": {{ random.int(10000, 100000) }}, 5 | "firstName": "{{ fake.first_name() }}", 6 | "lastName": "{{ fake.last_name() }}", 7 | "friends": [{% for n in range(range(5) | random) %} 8 | { 9 | "id": "{{ random.uuid4() }}" 10 | }{% if not loop.last %},{% endif %} 11 | {% endfor %}] 12 | }{% if not loop.last %},{% endif %} 13 | {% endfor %}], 14 | "total": 10 15 | } 16 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/faker.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Jinja2", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/faker", 10 | "method": "GET", 11 | "response": { 12 | "headers": { 13 | "Content-Type": "application/json; charset=UTF-8" 14 | }, 15 | "body": "@templates/faker.json.j2" 16 | } 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/faker.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/faker", 10 | "method": "GET", 11 | "response": { 12 | "headers": { 13 | "Content-Type": "application/json; charset=UTF-8" 14 | }, 15 | "body": "@templates/faker.json.hbs" 16 | } 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /tests/configs/stats_unhandled_service2.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service2", 5 | "port": 8002, 6 | "hostname": "service2.example.com", 7 | "endpoints": [ 8 | { 9 | "path": "/service2z", 10 | "method": "GET", 11 | "response": "" 12 | }, 13 | { 14 | "path": "/service2q", 15 | "method": "GET", 16 | "queryString": { 17 | "a[]": "b" 18 | }, 19 | "response": "" 20 | } 21 | ] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /tests_integrated/subdir/oas.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.0", 3 | "info": { 4 | "title": "Service for management API / Dynamic configs", 5 | "description": "OAS provided externally", 6 | "version": "0.1.9" 7 | }, 8 | "servers": [ 9 | { 10 | "url": "https://invalid-url:8005", 11 | "description": "should be overridden" 12 | } 13 | ], 14 | "paths": { 15 | "/": { 16 | "get": { 17 | "responses": { 18 | "default": { 19 | "description": "" 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /tests/configs/json/j2/core/no_use_templating_no_templating_engine_in_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/", 10 | "method": "GET", 11 | "response": { 12 | "headers": { 13 | "Content-Type": "application/json; charset=UTF-8" 14 | }, 15 | "body": "@templates/hello.json.j2" 16 | } 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/no_use_templating_no_templating_engine_in_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/", 10 | "method": "GET", 11 | "response": { 12 | "headers": { 13 | "Content-Type": "application/json; charset=UTF-8" 14 | }, 15 | "body": "@templates/hello.json.hbs" 16 | } 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/oas/oas.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.0", 3 | "info": { 4 | "title": "Service for management API / Dynamic configs", 5 | "description": "OAS provided externally", 6 | "version": "0.1.9" 7 | }, 8 | "servers": [ 9 | { 10 | "url": "https://invalid-url:8005", 11 | "description": "should be overridden" 12 | } 13 | ], 14 | "paths": { 15 | "/": { 16 | "get": { 17 | "responses": { 18 | "default": { 19 | "description": "" 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/no_templating_engine_in_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/", 10 | "method": "GET", 11 | "response": { 12 | "useTemplating": true, 13 | "headers": { 14 | "Content-Type": "application/json; charset=UTF-8" 15 | }, 16 | "body": "@templates/hello.json.hbs" 17 | } 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/no_templating_engine_in_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/", 10 | "method": "GET", 11 | "response": { 12 | "headers": { 13 | "Content-Type": "application/json; charset=UTF-8" 14 | }, 15 | "useTemplating": true, 16 | "body": "@templates/hello.json.j2" 17 | } 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/templating_engine_in_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/", 10 | "method": "GET", 11 | "response": { 12 | "headers": { 13 | "Content-Type": "application/json; charset=UTF-8" 14 | }, 15 | "templatingEngine": "Jinja2", 16 | "body": "@templates/hello.json.j2" 17 | } 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/templating_engine_in_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "hostname": "service1.example.com", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/", 10 | "method": "GET", 11 | "response": { 12 | "headers": { 13 | "Content-Type": "application/json; charset=UTF-8" 14 | }, 15 | "templatingEngine": "Handlebars", 16 | "body": "@templates/hello.json.hbs" 17 | } 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/templates/date.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "now": "{{ date.date '%Y-%m-%d %H:%M %f' }}", 3 | "1_week_back": "{{ date.date '%Y-%m-%d %H:%M %f' -604800 }}", 4 | "1_week_forward": "{{ date.date '%Y-%m-%d %H:%M %f' 604800 }}", 5 | "1_day_back": "{{ date.date '%Y-%m-%d %H:%M %f' -86400 }}", 6 | "1_day_forward": "{{ date.date '%Y-%m-%d %H:%M %f' 86400 }}", 7 | "1_hour_back": "{{ date.date '%Y-%m-%d %H:%M %f' -3600 }}", 8 | "1_hour_forward": "{{ date.date '%Y-%m-%d %H:%M %f' 3600 }}", 9 | "1_minute_back": "{{ date.date '%Y-%m-%d %H:%M %f' -60 }}", 10 | "1_minute_forward": "{{ date.date '%Y-%m-%d %H:%M %f' 60 }}" 11 | } 12 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/templates/date.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "now": "{{ date.date '%Y-%m-%d %H:%M %f' }}", 3 | "1_week_back": "{{ date.date '%Y-%m-%d %H:%M %f' -604800 }}", 4 | "1_week_forward": "{{ date.date '%Y-%m-%d %H:%M %f' 604800 }}", 5 | "1_day_back": "{{ date.date '%Y-%m-%d %H:%M %f' -86400 }}", 6 | "1_day_forward": "{{ date.date '%Y-%m-%d %H:%M %f' 86400 }}", 7 | "1_hour_back": "{{ date.date '%Y-%m-%d %H:%M %f' -3600 }}", 8 | "1_hour_forward": "{{ date.date '%Y-%m-%d %H:%M %f' 3600 }}", 9 | "1_minute_back": "{{ date.date '%Y-%m-%d %H:%M %f' -60 }}", 10 | "1_minute_forward": "{{ date.date '%Y-%m-%d %H:%M %f' 60 }}" 11 | } 12 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/random.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Handlebars 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/int" 7 | method: GET 8 | response: "{{random.int 1 5}}" 9 | - path: "/float" 10 | method: GET 11 | response: "{{random.float 1.0 2.0 3}}" 12 | - path: "/alphanum" 13 | method: GET 14 | response: "{{random.alphanum 7}}" 15 | - path: "/hex" 16 | method: GET 17 | response: "{{random.hex 5}}" 18 | - path: "/uuid4" 19 | method: GET 20 | response: "{{random.uuid4}}" 21 | - path: "/ascii" 22 | method: GET 23 | response: "{{random.ascii 11}}" 24 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/status/status_code.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Jinja2 3 | services: 4 | - name: Mock for Service1 5 | hostname: service1.example.com 6 | port: 8001 7 | endpoints: 8 | - path: "/service1" 9 | method: GET 10 | response: 11 | status: 202 12 | body: service1 13 | - name: Mock for Service2 14 | hostname: service2.example.com 15 | port: 8002 16 | endpoints: 17 | - path: "/service2" 18 | method: GET 19 | response: 20 | status: '403' 21 | body: service2 22 | - path: "/service2-endpoint2" 23 | method: GET 24 | response: 25 | status: "{{request.queryString['rc']}}" 26 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/status/status_code.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Handlebars 3 | services: 4 | - name: Mock for Service1 5 | hostname: service1.example.com 6 | port: 8001 7 | endpoints: 8 | - path: "/service1" 9 | method: GET 10 | response: 11 | status: 202 12 | body: service1 13 | - name: Mock for Service2 14 | hostname: service2.example.com 15 | port: 8002 16 | endpoints: 17 | - path: "/service2" 18 | method: GET 19 | response: 20 | status: '403' 21 | body: service2 22 | - path: "/service2-endpoint2" 23 | method: GET 24 | response: 25 | status: "{{request.queryString.rc}}" 26 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/random.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Jinja2 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/int" 7 | method: GET 8 | response: "{{random.int(1, 5)}}" 9 | - path: "/float" 10 | method: GET 11 | response: "{{random.float(1.0, 2.0, 3)}}" 12 | - path: "/alphanum" 13 | method: GET 14 | response: "{{random.alphanum(7)}}" 15 | - path: "/hex" 16 | method: GET 17 | response: "{{random.hex(5)}}" 18 | - path: "/uuid4" 19 | method: GET 20 | response: "{{random.uuid4()}}" 21 | - path: "/ascii" 22 | method: GET 23 | response: "{{random.ascii(11)}}" 24 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/templates/date.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "now": "{{ date.date('%Y-%m-%d %H:%M %f') }}", 3 | "1_week_back": "{{ date.date('%Y-%m-%d %H:%M %f', -604800) }}", 4 | "1_week_forward": "{{ date.date('%Y-%m-%d %H:%M %f', 604800) }}", 5 | "1_day_back": "{{ date.date('%Y-%m-%d %H:%M %f', -86400) }}", 6 | "1_day_forward": "{{ date.date('%Y-%m-%d %H:%M %f', 86400) }}", 7 | "1_hour_back": "{{ date.date('%Y-%m-%d %H:%M %f', -3600) }}", 8 | "1_hour_forward": "{{ date.date('%Y-%m-%d %H:%M %f', 3600) }}", 9 | "1_minute_back": "{{ date.date('%Y-%m-%d %H:%M %f', -60) }}", 10 | "1_minute_forward": "{{ date.date('%Y-%m-%d %H:%M %f', 60) }}" 11 | } 12 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/templates/date.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "now": "{{ date.date('%Y-%m-%d %H:%M %f') }}", 3 | "1_week_back": "{{ date.date('%Y-%m-%d %H:%M %f', -604800) }}", 4 | "1_week_forward": "{{ date.date('%Y-%m-%d %H:%M %f', 604800) }}", 5 | "1_day_back": "{{ date.date('%Y-%m-%d %H:%M %f', -86400) }}", 6 | "1_day_forward": "{{ date.date('%Y-%m-%d %H:%M %f', 86400) }}", 7 | "1_hour_back": "{{ date.date('%Y-%m-%d %H:%M %f', -3600) }}", 8 | "1_hour_forward": "{{ date.date('%Y-%m-%d %H:%M %f', 3600) }}", 9 | "1_minute_back": "{{ date.date('%Y-%m-%d %H:%M %f', -60) }}", 10 | "1_minute_forward": "{{ date.date('%Y-%m-%d %H:%M %f', 60) }}" 11 | } 12 | -------------------------------------------------------------------------------- /tests/configs/stats_unhandled.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | - name: Mock for Service1 3 | port: 8001 4 | hostname: service1.example.com 5 | endpoints: 6 | - path: /service1x 7 | method: GET 8 | response: '' 9 | - path: /service1y 10 | method: GET 11 | headers: 12 | Example-Header: Example-Value 13 | queryString: 14 | a: b 15 | c: d 16 | response: '' 17 | - name: Mock for Service2 18 | port: 8002 19 | hostname: service2.example.com 20 | endpoints: 21 | - path: /service2z 22 | method: GET 23 | response: '' 24 | - path: /service2q 25 | method: GET 26 | queryString: 27 | a[]: b 28 | response: '' 29 | -------------------------------------------------------------------------------- /msi.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -xe 2 | 3 | python3 setup.py bdist_wheel 4 | 5 | # build wheels for projects that don't do it 6 | pip wheel -w dist paho-mqtt pybars4 PyMeta3 7 | 8 | # download appropriate native-including wheel 9 | pip download --no-deps --platform win_amd64 --dest dist ruamel.yaml.clib 10 | 11 | python3 -m venv --clear build/venv 12 | source build/venv/bin/activate 13 | 14 | pip install homebrew-pypi-poet wheel pynsist 15 | pip install -U ruamel.yaml.clib setuptools # to get it installed with certain version 16 | pip install -e .[cloud] 17 | 18 | mv dist dist-msi 19 | python3 msi.py 20 | echo $? 21 | ls -la build/nsis/Mockintosh_*_x64.exe 22 | 23 | deactivate 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/configs/missing_ssl_cert_file.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000 4 | }, 5 | "templatingEngine": "Handlebars", 6 | "services": [ 7 | { 8 | "name": "Mock for Service1", 9 | "hostname": "service1.example.com", 10 | "port": 8001, 11 | "ssl": true, 12 | "sslCertFile": "missing_dir/cert.pem", 13 | "sslKeyFile": "missing_dir/key.pem", 14 | "managementRoot": "__admin", 15 | "endpoints": [] 16 | }, 17 | { 18 | "name": "Mock for Service2", 19 | "hostname": "service2.example.com", 20 | "port": 8002, 21 | "managementRoot": "__admin", 22 | "endpoints": [] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/two_services_one_with_hostname_one_without.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/", 10 | "method": "GET", 11 | "response": "service1" 12 | } 13 | ] 14 | }, 15 | { 16 | "name": "Mock for Service2", 17 | "hostname": "service2.example.com", 18 | "port": 8002, 19 | "endpoints": [ 20 | { 21 | "path": "/", 22 | "method": "GET", 23 | "response": "service2" 24 | } 25 | ] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /tests_integrated/custom_interceptors.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from mockintosh import Request, Response 4 | 5 | 6 | def intercept_for_logging(req: Request, resp: Response): 7 | logging.info("Processed intercepted request: %r, produced response: %r", req, resp) 8 | 9 | 10 | def intercept_for_modifying(req: Request, resp: Response): 11 | # should have access to request path, query string, headers, body 12 | if req.path == '/interceptor-modified' and resp.status == 404: 13 | # should allow reading and modifying response status code, headers, body 14 | resp.status = 202 15 | resp.headers.add("someheader", "some-i-val") 16 | resp.body = "intercepted" 17 | -------------------------------------------------------------------------------- /tests/configs/stats_config_service2.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Mock for Service2", 3 | "hostname": "service2.example.com", 4 | "port": 8002, 5 | "managementRoot": "__admin", 6 | "endpoints": [ 7 | { 8 | "path": "/service2", 9 | "method": "GET", 10 | "response": "service2" 11 | }, 12 | { 13 | "path": "/service2-rst", 14 | "method": "GET", 15 | "response": { 16 | "status": "RST", 17 | "body": "service2-rst" 18 | } 19 | }, 20 | { 21 | "path": "/service2-fin", 22 | "method": "GET", 23 | "response": { 24 | "status": "FIN", 25 | "body": "service2-fin" 26 | } 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /tests/configs/stats_unhandled_service1.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "port": 8001, 6 | "hostname": "service1.example.com", 7 | "endpoints": [ 8 | { 9 | "path": "/service1x", 10 | "method": "GET", 11 | "response": "" 12 | }, 13 | { 14 | "path": "/service1y", 15 | "method": "GET", 16 | "headers": { 17 | "Example-Header": "Example-Value" 18 | }, 19 | "queryString": { 20 | "a": "b", 21 | "c": "d" 22 | }, 23 | "response": "" 24 | } 25 | ] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/new_config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | management: 3 | port: 8000 4 | ssl: true 5 | sslCertFile: cert.pem 6 | sslKeyFile: key.pem 7 | templatingEngine: Handlebars 8 | services: 9 | - name: Mock for Service1 10 | hostname: service1.example.com 11 | port: 8001 12 | managementRoot: __admin 13 | endpoints: 14 | - path: "/service1" 15 | method: GET 16 | response: service1 17 | - path: "/service1-new-config" 18 | method: GET 19 | response: service1-new-config 20 | - name: Mock for Service2 21 | hostname: service2.example.com 22 | port: 8002 23 | managementRoot: __admin 24 | endpoints: 25 | - path: "/service2" 26 | method: GET 27 | response: service2 28 | -------------------------------------------------------------------------------- /tests/configs/inaccessible_ssl_cert_file.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000 4 | }, 5 | "templatingEngine": "Handlebars", 6 | "services": [ 7 | { 8 | "name": "Mock for Service1", 9 | "hostname": "service1.example.com", 10 | "port": 8001, 11 | "ssl": true, 12 | "sslCertFile": "../../tests_integrated/subdir/cert.pem", 13 | "sslKeyFile": "../../tests_integrated/subdir/key.pem", 14 | "managementRoot": "__admin", 15 | "endpoints": [] 16 | }, 17 | { 18 | "name": "Mock for Service2", 19 | "hostname": "service2.example.com", 20 | "port": 8002, 21 | "managementRoot": "__admin", 22 | "endpoints": [] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /tests/configs/stats_config_service1.yaml: -------------------------------------------------------------------------------- 1 | name: Mock for Service1 2 | hostname: service1.example.com 3 | port: 8001 4 | managementRoot: __admin 5 | endpoints: 6 | - path: /service1 7 | method: GET 8 | response: service1 9 | - path: /service1-second/{{var}} 10 | method: GET 11 | response: 12 | headers: 13 | Content-Type: application/json; charset=UTF-8 14 | status: 201 15 | body: 'service1-second: {{var}}' 16 | - path: /service1-post 17 | method: POST 18 | response: service1 19 | - path: /service1-resource 20 | method: POST 21 | response: 22 | body: '@templates/hello.json.hbs' 23 | - path: /service1-resource2 24 | method: POST 25 | response: 26 | body: '@templates/hello2.json.hbs' 27 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/kafka/config_error.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Handlebars 3 | management: 4 | port: 8000 5 | ssl: true 6 | sslCertFile: cert.pem 7 | sslKeyFile: key.pem 8 | globals: 9 | headers: 10 | global-hdr1: globalval1 11 | global-hdr2: globalval2 12 | services: 13 | - name: Asynchronous Mocks 14 | type: kafka 15 | address: "{{env 'KAFKA_ADDR' 'localhost:9092'}}" 16 | actors: 17 | - name: multiproducer 18 | produce: 19 | - queue: topic12 20 | key: key12-1 21 | value: value12-1 22 | headers: 23 | hdr12-1: val12-1 24 | - queue: topic13 25 | key: key12-2 26 | value: value12-2 27 | headers: 28 | hdr12-2: val12-2 29 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/connection_reset.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Handlebars 2 | services: 3 | - name: Mock for Service1 4 | port: 8001 5 | endpoints: 6 | - path: "/normal" 7 | method: GET 8 | response: 9 | status: 200 10 | body: "Hello world" 11 | - path: "/reset" 12 | method: GET 13 | response: 14 | status: "RST" 15 | body: "Hello world" 16 | - path: "/close" 17 | method: GET 18 | response: 19 | status: "FIN" 20 | body: "Hello world" 21 | - path: "/reset2" 22 | method: GET 23 | response: 24 | status: "rst" 25 | body: "Hello world" 26 | - path: "/close2" 27 | method: GET 28 | response: 29 | status: "fin" 30 | body: "Hello world" 31 | -------------------------------------------------------------------------------- /mockintosh/constants.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | .. module:: __init__ 6 | :synopsis: module that contains the constants. 7 | """ 8 | 9 | from os import environ 10 | 11 | 12 | PROGRAM = 'mockintosh' 13 | 14 | PYBARS = 'Handlebars' 15 | JINJA = 'Jinja2' 16 | 17 | SHORT_PYBARS = 'hbs' 18 | SHORT_JINJA = 'j2' 19 | 20 | SPECIAL_CONTEXT = '%s_special_context' % PROGRAM 21 | 22 | JINJA_VARNAME_DICT = 'jinja_varname_dict' 23 | 24 | BASE64 = 'base64' 25 | 26 | LOGGING_LENGTH_LIMIT = int(environ.get('%s_LOGGING_LENGTH_LIMIT' % PROGRAM, 100)) 27 | 28 | WARN_GPUBSUB_PACKAGE = 'google-cloud-pubsub Python package is not installed! (gpubsub)' 29 | WARN_AMAZONSQS_PACKAGE = 'boto3 Python package is not installed! (amazonsqs)' 30 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/endpoint_id_header.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "hostname": "service1.example.com", 7 | "port": 8001, 8 | "endpoints": [ 9 | { 10 | "id": "endpoint-id-1", 11 | "path": "/service1", 12 | "method": "GET", 13 | "response": "service1" 14 | } 15 | ] 16 | }, 17 | { 18 | "name": "Mock for Service2", 19 | "hostname": "service2.example.com", 20 | "port": 8002, 21 | "endpoints": [ 22 | { 23 | "id": "endpoint-id-2", 24 | "path": "/service2", 25 | "method": "GET", 26 | "response": "service2" 27 | } 28 | ] 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /tests_integrated/acceptance.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -xe 2 | 3 | docker run -d -it --net=host up9inc/mockintosh:self-contained-kafka 4 | docker run -d -it --net=host rabbitmq:latest 5 | docker run -d -it --net=host redis:latest 6 | 7 | docker run -it mockintosh --help 8 | docker run -it mockintosh --sample-config /tmp/sample.yml 9 | 10 | docker run -d --net=host -v `pwd`/tests_integrated:/tmp/tests_integrated \ 11 | -e PYTHONPATH=/tmp/tests_integrated mockintosh \ 12 | -v \ 13 | -l /tmp/tests_integrated/server.log \ 14 | --interceptor=custom_interceptors.intercept_for_logging \ 15 | --interceptor=custom_interceptors.intercept_for_modifying \ 16 | /tmp/tests_integrated/integration_config.yaml 17 | 18 | sleep 5 19 | 20 | pytest tests_integrated/tests_integration.py -s -v --log-level=DEBUG # -m kafka -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/binary_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "management": { 4 | "port": 8000 5 | }, 6 | "services": [ 7 | { 8 | "name": "Mock for Service1", 9 | "port": 8001, 10 | "endpoints": [ 11 | { 12 | "path": "/image", 13 | "method": "GET", 14 | "response": { 15 | "body": "@image.png", 16 | "headers": { 17 | "Content-Type": "image/png" 18 | } 19 | } 20 | }, 21 | { 22 | "path": "/hello", 23 | "method": "GET", 24 | "response": { 25 | "body": "@templates/hello.json.hbs", 26 | "headers": { 27 | "Content-Type": "application/json; charset=UTF-8" 28 | } 29 | } 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/oas_documents/service1_no_servers.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.0", 3 | "info": { 4 | "title": "Mock for Service1 CUSTOM", 5 | "description": "Automatically generated Open API Specification.", 6 | "version": "0.1.9" 7 | }, 8 | "paths": { 9 | "/service1": { 10 | "get": { 11 | "responses": { 12 | "200": { 13 | "description": "" 14 | } 15 | } 16 | } 17 | }, 18 | "/service1-second/{var}": { 19 | "get": { 20 | "responses": { 21 | "201": { 22 | "description": "" 23 | } 24 | }, 25 | "parameters": [ 26 | { 27 | "in": "path", 28 | "name": "var", 29 | "required": true, 30 | "schema": { 31 | "type": "string" 32 | } 33 | } 34 | ] 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests_integrated/cors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CORS Example 6 | 7 | 8 | 9 | 404 10 | 11 | 12 | 30 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/core/date.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Handlebars 3 | services: 4 | - name: Mock for Service1 5 | port: 8001 6 | endpoints: 7 | - path: "/timestamp" 8 | method: GET 9 | response: "{{date.timestamp}}" 10 | - path: "/timestamp-shift" 11 | method: GET 12 | response: "{{date.timestamp}}
{{date.timestamp 42}}
{{date.timestamp -42}}" 13 | - path: "/ftimestamp" 14 | method: GET 15 | response: "{{date.ftimestamp}}
{{date.ftimestamp 0.0 7}}" 16 | - path: "/ftimestamp-shift" 17 | method: GET 18 | response: "{{date.ftimestamp}}
{{date.ftimestamp 3.14}}
{{date.ftimestamp -3.14}}" 19 | - path: "/date" 20 | method: GET 21 | response: "{{date.date}}
{{date.date '%Y-%m-%d %H:%M'}}" 22 | - path: "/date-shift" 23 | method: GET 24 | response: 25 | headers: 26 | Content-Type: application/json; charset=UTF-8 27 | body: "@templates/date.json.hbs" 28 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/core/date.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Jinja2 3 | services: 4 | - name: Mock for Service1 5 | port: 8001 6 | endpoints: 7 | - path: "/timestamp" 8 | method: GET 9 | response: "{{date.timestamp()}}" 10 | - path: "/timestamp-shift" 11 | method: GET 12 | response: "{{date.timestamp()}}
{{date.timestamp(42)}}
{{date.timestamp(-42)}}" 13 | - path: "/ftimestamp" 14 | method: GET 15 | response: "{{date.ftimestamp()}}
{{date.ftimestamp(0.0, 7)}}" 16 | - path: "/ftimestamp-shift" 17 | method: GET 18 | response: "{{date.ftimestamp()}}
{{date.ftimestamp(3.14)}}
{{date.ftimestamp(-3.14)}}" 19 | - path: "/date" 20 | method: GET 21 | response: "{{date.date()}}
{{date.date('%Y-%m-%d %H:%M')}}" 22 | - path: "/date-shift" 23 | method: GET 24 | response: 25 | headers: 26 | Content-Type: application/json; charset=UTF-8 27 | body: "@templates/date.json.j2" 28 | -------------------------------------------------------------------------------- /tests/assets_copy_kafka_to_gpubsub.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import yaml 4 | 5 | 6 | # Edit tests/configs/yaml/hbs/gpubsub/config.yaml 7 | data = yaml.safe_load(open('tests/configs/yaml/hbs/gpubsub/config.yaml', 'r')) 8 | 9 | data['services'][0]['type'] = 'gpubsub' 10 | data['services'][0]['address'] = "{{env 'PUBSUB_PROJECT_ID' 'test-gpubsub'}}@{{env 'PUBSUB_EMULATOR_HOST' 'localhost:8681'}}" 11 | data['services'][0]['actors'][9]['produce']['headers']['counter'] = "{{counter 'gpubsubCounter'}}" 12 | 13 | data['services'].pop() 14 | data['services'].pop() 15 | 16 | yaml.dump(data, open('tests/configs/yaml/hbs/gpubsub/config.yaml', 'w'), sort_keys=False) 17 | 18 | 19 | # Edit tests/configs/yaml/hbs/gpubsub/config.yaml 20 | data = yaml.safe_load(open('tests/configs/yaml/hbs/gpubsub/config_error.yaml', 'r')) 21 | 22 | data['services'][0]['type'] = 'gpubsub' 23 | del data['services'][0]['address'] 24 | 25 | yaml.dump(data, open('tests/configs/yaml/hbs/gpubsub/config_error.yaml', 'w'), sort_keys=False) 26 | -------------------------------------------------------------------------------- /tests/configs/fallback_to.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | management: 3 | port: 8000 4 | templatingEngine: Handlebars 5 | services: 6 | - name: Mock for Service1 7 | hostname: service1.example.com 8 | port: 8001 9 | managementRoot: __admin 10 | fallbackTo: http://localhost:8999/ 11 | endpoints: 12 | - path: "/service1" 13 | method: GET 14 | response: service1 15 | - path: "/service1-second/{{var}}" 16 | method: GET 17 | response: 18 | status: 201 19 | body: 'service1-second: {{var}}' 20 | - name: Mock for Service2 21 | hostname: service2.example.com 22 | port: 8002 23 | managementRoot: __admin 24 | fallbackTo: http://service1.example.com:8001 25 | endpoints: 26 | - path: "/service2" 27 | method: GET 28 | response: service2 29 | - path: "/service2-rst" 30 | method: GET 31 | response: 32 | status: RST 33 | body: service2-rst 34 | - path: "/service2-fin" 35 | method: GET 36 | response: 37 | status: FIN 38 | body: service2-fin 39 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/common/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Jinja2 3 | services: 4 | - name: Mock for Service1 5 | hostname: service1.example.com 6 | port: 8001 7 | endpoints: 8 | - path: "/users" 9 | method: GET 10 | response: 11 | headers: 12 | Content-Type: "application/json; charset=UTF-8" 13 | useTemplating: true 14 | body: "@templates/users.json.j2" 15 | - path: "/users/{{ id }}" 16 | method: GET 17 | response: 18 | headers: 19 | Content-Type: "application/json; charset=UTF-8" 20 | useTemplating: true 21 | body: "@templates/user.json.j2" 22 | - name: Mock for Service2 23 | hostname: service2.example.com 24 | port: 8002 25 | endpoints: 26 | - path: "/companies" 27 | method: POST 28 | response: 29 | headers: 30 | Content-Type: "application/json; charset=UTF-8" 31 | useTemplating: true 32 | body: "@templates/companies.json.j2" 33 | - name: Service with no endpoints, for bare interceptors 34 | port: 8003 35 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/common/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Handlebars 3 | services: 4 | - name: Mock for Service1 5 | hostname: service1.example.com 6 | port: 8001 7 | endpoints: 8 | - path: "/users" 9 | method: GET 10 | response: 11 | headers: 12 | Content-Type: "application/json; charset=UTF-8" 13 | useTemplating: true 14 | body: "@templates/users.json.hbs" 15 | - path: "/users/{{ id }}" 16 | method: GET 17 | response: 18 | headers: 19 | Content-Type: "application/json; charset=UTF-8" 20 | useTemplating: true 21 | body: "@templates/user.json.hbs" 22 | - name: Mock for Service2 23 | hostname: service2.example.com 24 | port: 8002 25 | endpoints: 26 | - path: "/companies" 27 | method: POST 28 | response: 29 | headers: 30 | Content-Type: "application/json; charset=UTF-8" 31 | useTemplating: true 32 | body: "@templates/companies.json.hbs" 33 | - name: Service with no endpoints, for bare interceptors 34 | port: 8003 35 | -------------------------------------------------------------------------------- /mockintosh/j2/meta.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | .. module:: __init__ 6 | :synopsis: Source: https://github.com/jappeace/offertex/blob/master/jinmeta.py 7 | """ 8 | 9 | from jinja2 import nodes, meta 10 | 11 | 12 | def find_undeclared_variables_in_order(ast): 13 | """ 14 | Returns a list of undeclared variables **IN ORDER**, 15 | unlike the same function from jinjia.meta 16 | """ 17 | 18 | undeclared_set = meta.find_undeclared_variables(ast) # undeclared, unordered 19 | ordered_nodes = [ 20 | node 21 | for node in ast.find_all(nodes.Name) # including declared, but in order 22 | if node.name in undeclared_set # filter out declared 23 | ] 24 | 25 | result = [] 26 | seen = set() 27 | 28 | # remove duplicates 29 | for node in ordered_nodes: 30 | name = node.name 31 | if name in seen: # pragma: no cover 32 | continue 33 | seen.add(name) 34 | result.append(name) 35 | 36 | return result 37 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/undefined.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/undefined", 10 | "method": "GET", 11 | "response": "Hello {{undefined_var}} world" 12 | }, 13 | { 14 | "path": "/undefined2", 15 | "method": "GET", 16 | "response": "Hello {{undefined_helper 1 2}} world" 17 | }, 18 | { 19 | "path": "/undefined3", 20 | "method": "GET", 21 | "response": "Hello {{undefined_obj.attr 1 2}} world" 22 | }, 23 | { 24 | "path": "/undefined4", 25 | "method": "GET", 26 | "response": "{{ date.date '%Y-%m-%d %H:%M %f' false 99999 }}" 27 | }, 28 | { 29 | "path": "/undefined5", 30 | "method": "GET", 31 | "response": "Hello {{date.undefined_attr}} world" 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/undefined.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Jinja2", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/undefined", 10 | "method": "GET", 11 | "response": "Hello {{undefined_var}} world" 12 | }, 13 | { 14 | "path": "/undefined2", 15 | "method": "GET", 16 | "response": "Hello {{undefined_helper(1, 2)}} world" 17 | }, 18 | { 19 | "path": "/undefined3", 20 | "method": "GET", 21 | "response": "Hello {{undefined_obj.attr(1, 2)}} world" 22 | }, 23 | { 24 | "path": "/undefined4", 25 | "method": "GET", 26 | "response": "{{ date.date('%Y-%m-%d %H:%M %f', false, 99999) }}" 27 | }, 28 | { 29 | "path": "/undefined5", 30 | "method": "GET", 31 | "response": "Hello {{date.undefined_attr}} world" 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/ssl_true.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "hostname": "service1.example.com", 7 | "ssl": true, 8 | "port": 8001, 9 | "endpoints": [ 10 | { 11 | "path": "/service1", 12 | "method": "GET", 13 | "response": "service1" 14 | } 15 | ] 16 | }, 17 | { 18 | "name": "Mock for Service2", 19 | "hostname": "service2.example.com", 20 | "port": 8002, 21 | "endpoints": [ 22 | { 23 | "path": "/service2", 24 | "method": "GET", 25 | "response": "service2" 26 | } 27 | ] 28 | }, 29 | { 30 | "name": "Mock for Service3", 31 | "hostname": "service3.example.com", 32 | "ssl": true, 33 | "port": 8003, 34 | "endpoints": [ 35 | { 36 | "path": "/service3", 37 | "method": "GET", 38 | "response": "service3" 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/oas_documents/service1.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.0", 3 | "info": { 4 | "title": "Mock for Service1 CUSTOM", 5 | "description": "Automatically generated Open API Specification.", 6 | "version": "0.1.9" 7 | }, 8 | "servers": [ 9 | { 10 | "url": "http://service1.example.com:8001", 11 | "description": "Mock for Service1" 12 | } 13 | ], 14 | "paths": { 15 | "/service1": { 16 | "get": { 17 | "responses": { 18 | "200": { 19 | "description": "" 20 | } 21 | } 22 | } 23 | }, 24 | "/service1-second/{var}": { 25 | "get": { 26 | "responses": { 27 | "201": { 28 | "description": "" 29 | } 30 | }, 31 | "parameters": [ 32 | { 33 | "in": "path", 34 | "name": "var", 35 | "required": true, 36 | "schema": { 37 | "type": "string" 38 | } 39 | } 40 | ] 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/status/status_code.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "hostname": "service1.example.com", 7 | "port": 8001, 8 | "endpoints": [ 9 | { 10 | "path": "/service1", 11 | "method": "GET", 12 | "response": { 13 | "status": 202, 14 | "body": "service1" 15 | } 16 | } 17 | ] 18 | }, 19 | { 20 | "name": "Mock for Service2", 21 | "hostname": "service2.example.com", 22 | "port": 8002, 23 | "endpoints": [ 24 | { 25 | "path": "/service2", 26 | "method": "GET", 27 | "response": { 28 | "status": "403", 29 | "body": "service2" 30 | } 31 | }, 32 | { 33 | "path": "/service2-endpoint2", 34 | "method": "GET", 35 | "response": { 36 | "status": "{{request.queryString.rc}}" 37 | } 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /tests/configs/json/j2/status/status_code.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Jinja2", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "hostname": "service1.example.com", 7 | "port": 8001, 8 | "endpoints": [ 9 | { 10 | "path": "/service1", 11 | "method": "GET", 12 | "response": { 13 | "status": 202, 14 | "body": "service1" 15 | } 16 | } 17 | ] 18 | }, 19 | { 20 | "name": "Mock for Service2", 21 | "hostname": "service2.example.com", 22 | "port": 8002, 23 | "endpoints": [ 24 | { 25 | "path": "/service2", 26 | "method": "GET", 27 | "response": { 28 | "status": "403", 29 | "body": "service2" 30 | } 31 | }, 32 | { 33 | "path": "/service2-endpoint2", 34 | "method": "GET", 35 | "response": { 36 | "status": "{{request.queryString['rc']}}" 37 | } 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /tests/assets_copy_kafka_to_amqp.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import yaml 4 | 5 | 6 | # Edit tests/configs/yaml/hbs/amqp/config.yaml 7 | data = yaml.safe_load(open('tests/configs/yaml/hbs/amqp/config.yaml', 'r')) 8 | 9 | data['services'][0]['type'] = 'amqp' 10 | data['services'][0]['address'] = "{{env 'AMQP_ADDR' 'localhost:5672'}}" 11 | data['services'][0]['actors'][9]['produce']['headers']['counter'] = "{{counter 'amqpCounter'}}" 12 | 13 | data['services'][2]['type'] = 'rabbitmq' 14 | data['services'][2]['address'] = 'localhost:5673' 15 | 16 | data['services'][3]['type'] = 'activemq' 17 | data['services'][3]['address'] = 'localhost:5674' 18 | 19 | yaml.dump(data, open('tests/configs/yaml/hbs/amqp/config.yaml', 'w'), sort_keys=False) 20 | 21 | 22 | # Edit tests/configs/yaml/hbs/amqp/config.yaml 23 | data = yaml.safe_load(open('tests/configs/yaml/hbs/amqp/config_error.yaml', 'r')) 24 | 25 | data['services'][0]['type'] = 'amqp' 26 | data['services'][0]['address'] = "{{env 'AMQP_ADDR' 'localhost:5672'}}" 27 | 28 | yaml.dump(data, open('tests/configs/yaml/hbs/amqp/config_error.yaml', 'w'), sort_keys=False) 29 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/new_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "templatingEngine": "Handlebars", 9 | "services": [ 10 | { 11 | "name": "Mock for Service1", 12 | "hostname": "service1.example.com", 13 | "port": 8001, 14 | "managementRoot": "__admin", 15 | "endpoints": [ 16 | { 17 | "path": "/service1", 18 | "method": "GET", 19 | "response": "service1" 20 | }, 21 | { 22 | "path": "/service1-new-config", 23 | "method": "GET", 24 | "response": "service1-new-config" 25 | } 26 | ] 27 | }, 28 | { 29 | "name": "Mock for Service2", 30 | "hostname": "service2.example.com", 31 | "port": 8002, 32 | "managementRoot": "__admin", 33 | "endpoints": [ 34 | { 35 | "path": "/service2", 36 | "method": "GET", 37 | "response": "service2" 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /tests/configs/stats_config_service1.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Mock for Service1", 3 | "hostname": "service1.example.com", 4 | "port": 8001, 5 | "managementRoot": "__admin", 6 | "endpoints": [ 7 | { 8 | "path": "/service1", 9 | "method": "GET", 10 | "response": "service1" 11 | }, 12 | { 13 | "path": "/service1-second/{{var}}", 14 | "method": "GET", 15 | "response": { 16 | "headers": { 17 | "Content-Type": "application/json; charset=UTF-8" 18 | }, 19 | "status": 201, 20 | "body": "service1-second: {{var}}" 21 | } 22 | }, 23 | { 24 | "path": "/service1-post", 25 | "method": "POST", 26 | "response": "service1" 27 | }, 28 | { 29 | "path": "/service1-resource", 30 | "method": "POST", 31 | "response": { 32 | "body": "@templates/hello.json.hbs" 33 | } 34 | }, 35 | { 36 | "path": "/service1-resource2", 37 | "method": "POST", 38 | "response": { 39 | "body": "@templates/hello2.json.hbs" 40 | } 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /docs/examples/templates/index.html.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | HTML Templating Example 4 | 11 | 12 | 13 | 14 | 15 |

HTML Templating Example

16 | 17 |

Hello {{ fake.first_name_nonbinary() }}!

18 | 19 |

Today is {{ date.date('%Y-%m-%d') }}.

20 | 21 |

I'm a {{ fake.job() | title }} and my favorite color is:

22 | 23 |
24 | 25 |

This is my cat {{ fake.first_name_male() }}:

26 | 27 | 28 | 29 |

and this is my house on {{ fake.street_address() }} St., {{ fake.city() }}:

30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 UP9 Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /mockintosh/performance.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | .. module:: __init__ 6 | :synopsis: module that contains classes for performance profiling. 7 | """ 8 | 9 | import random 10 | import time 11 | from typing import ( 12 | Union 13 | ) 14 | 15 | 16 | class PerformanceProfile(): 17 | 18 | def __init__( 19 | self, 20 | ratio: Union[float, int], 21 | delay: Union[float, int] = 0.0, 22 | faults: Union[dict, None] = None 23 | ): 24 | self.ratio = ratio 25 | self.delay = delay 26 | self.faults = {} if faults is None else faults 27 | 28 | def trigger(self, status_code: int) -> Union[int, str]: 29 | if random.uniform(0, 1) <= self.ratio: 30 | time.sleep(self.delay) 31 | if self.faults: 32 | chosen = random.choices(list(self.faults.keys()), weights=self.faults.values(), k=1)[0] 33 | if chosen == 'PASS': 34 | return status_code 35 | else: 36 | return int(chosen) if chosen not in ('RST', 'FIN') else chosen 37 | return status_code 38 | -------------------------------------------------------------------------------- /tests/configs/stats_unhandled.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": [ 3 | { 4 | "name": "Mock for Service1", 5 | "port": 8001, 6 | "hostname": "service1.example.com", 7 | "endpoints": [ 8 | { 9 | "path": "/service1x", 10 | "method": "GET", 11 | "response": "" 12 | }, 13 | { 14 | "path": "/service1y", 15 | "method": "GET", 16 | "headers": { 17 | "Example-Header": "Example-Value" 18 | }, 19 | "queryString": { 20 | "a": "b", 21 | "c": "d" 22 | }, 23 | "response": "" 24 | } 25 | ] 26 | }, 27 | { 28 | "name": "Mock for Service2", 29 | "port": 8002, 30 | "hostname": "service2.example.com", 31 | "endpoints": [ 32 | { 33 | "path": "/service2z", 34 | "method": "GET", 35 | "response": "" 36 | }, 37 | { 38 | "path": "/service2q", 39 | "method": "GET", 40 | "queryString": { 41 | "a[]": "b" 42 | }, 43 | "response": "" 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/multiresponse_comma_tag.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "templatingEngine": "Handlebars", 9 | "services": [ 10 | { 11 | "name": "Mock for Service3", 12 | "port": 8003, 13 | "managementRoot": "__admin", 14 | "endpoints": [ 15 | { 16 | "path": "/tagged-responses", 17 | "response": [ 18 | { 19 | "body": "3.1" 20 | }, 21 | { 22 | "tag": "firs,t", 23 | "body": "1.1" 24 | }, 25 | { 26 | "tag": "second", 27 | "body": "2.1" 28 | }, 29 | { 30 | "tag": "first", 31 | "body": "1.2" 32 | }, 33 | { 34 | "body": "3.2" 35 | }, 36 | { 37 | "tag": "second", 38 | "body": "2.2" 39 | }, 40 | { 41 | "body": "3.3" 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /tests/assets_copy_kafka_to_amazonsqs.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import yaml 4 | 5 | 6 | # Edit tests/configs/yaml/hbs/amazonsqs/config.yaml 7 | data = yaml.safe_load(open('tests/configs/yaml/hbs/amazonsqs/config.yaml', 'r')) 8 | 9 | data['services'][0]['type'] = 'amazonsqs' 10 | data['services'][0]['address'] = "{{env 'AMAZONSQS_ADDR' 'http://localhost:9324#elasticmq'}}" 11 | data['services'][0]['actors'][9]['produce']['headers']['counter'] = "{{counter 'amazonsqsCounter'}}" 12 | 13 | data['services'][2]['type'] = 'rabbitmq' 14 | data['services'][2]['address'] = 'localhost:9325' 15 | 16 | data['services'][3]['type'] = 'activemq' 17 | data['services'][3]['address'] = 'localhost:9326' 18 | 19 | yaml.dump(data, open('tests/configs/yaml/hbs/amazonsqs/config.yaml', 'w'), sort_keys=False) 20 | 21 | 22 | # Edit tests/configs/yaml/hbs/amazonsqs/config.yaml 23 | data = yaml.safe_load(open('tests/configs/yaml/hbs/amazonsqs/config_error.yaml', 'r')) 24 | 25 | data['services'][0]['type'] = 'amazonsqs' 26 | data['services'][0]['address'] = "{{env 'AMAZONSQS_ADDR' 'http://localhost:9324#elasticmq'}}" 27 | 28 | yaml.dump(data, open('tests/configs/yaml/hbs/amazonsqs/config_error.yaml', 'w'), sort_keys=False) 29 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/amqp_properties/config.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Handlebars 2 | management: 3 | port: 8000 4 | ssl: true 5 | globals: 6 | headers: 7 | global-hdr1: globalval1 8 | global-hdr2: globalval2 9 | services: 10 | - name: Asynchronous Mocks 11 | type: amqp 12 | address: '{{env ''AMQP_ADDR'' ''localhost:5672''}}' 13 | actors: 14 | - produce: 15 | queue: shipping-task 16 | create: true 17 | key: shipping-task 18 | value: '{"id":"2ea440f9-f221-4baf-bb21-5af70a4dc1cd","name":"60d8942dee11cb000156d96a"}' 19 | amqpProperties: 20 | priority: 0 21 | delivery_mode: 2 22 | content_encoding: "UTF-8" 23 | content_type: "application/json" 24 | headers: 25 | __TypeId__: "works.weave.socks.shipping.entities.Shipment" 26 | delay: 2 27 | limit: 100 28 | - consume: 29 | queue: shipping-task 30 | key: "{{var21_1}}" 31 | value: "{{var21_2}}" 32 | amqpProperties: 33 | priority: 0 34 | delivery_mode: 2 35 | content_encoding: "UTF-8" 36 | content_type: "application/json" 37 | headers: 38 | __TypeId__: "works.weave.socks.shipping.entities.Shipment" 39 | -------------------------------------------------------------------------------- /docs/examples/example.yaml: -------------------------------------------------------------------------------- 1 | # An example of a configuration file that demonstrates 2 | # the common features of Mockintosh. 3 | # Run: 4 | # $ mockintosh example.yaml 5 | 6 | templatingEngine: Jinja2 7 | services: 8 | - name: Mock for Service1 9 | hostname: localhost 10 | port: 8001 11 | managementRoot: __admin 12 | endpoints: 13 | - path: "/" 14 | method: GET 15 | response: 16 | headers: 17 | Content-Type: "text/html; charset=UTF-8" 18 | body: "@templates/index.html.j2" 19 | - path: "/users" 20 | method: GET 21 | response: 22 | headers: 23 | Content-Type: "application/json; charset=UTF-8" 24 | body: "@templates/users.json.j2" 25 | - name: Mock for Service2 26 | hostname: service2.example.com 27 | port: 8002 28 | endpoints: 29 | - path: "/companies" 30 | method: POST 31 | body: 32 | schema: 33 | type: object 34 | properties: 35 | name: 36 | type: string 37 | address: 38 | type: string 39 | required: 40 | - name 41 | - address 42 | response: 43 | headers: 44 | Content-Type: "application/json; charset=UTF-8" 45 | body: "@templates/company.json.j2" 46 | -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | # Hello! This is where you manage which Jekyll version is used to run. 3 | # When you want to use a different version, change it below, save the 4 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 5 | # 6 | # bundle exec jekyll serve 7 | # 8 | # This will help ensure the proper Jekyll version is running. 9 | # Happy Jekylling! 10 | # gem "jekyll", "~> 4.2.0" 11 | # This is the default theme for new Jekyll sites. You may change this to anything you like. 12 | gem "minima", "~> 2.5" 13 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and 14 | # uncomment the line below. To upgrade, run `bundle update github-pages`. 15 | gem "github-pages", "~> 225", group: :jekyll_plugins 16 | # If you have any plugins, put them here! 17 | group :jekyll_plugins do 18 | gem "jekyll-feed", "~> 0.12" 19 | end 20 | 21 | # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem 22 | # and associated library. 23 | platforms :mingw, :x64_mingw, :mswin, :jruby do 24 | gem "tzinfo", "~> 1.2" 25 | gem "tzinfo-data" 26 | end 27 | 28 | # Performance-booster for watching directories on Windows 29 | gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin] 30 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/management/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | management: 3 | port: 8000 4 | ssl: true 5 | sslCertFile: cert.pem 6 | sslKeyFile: key.pem 7 | globals: 8 | unused: unused 9 | templatingEngine: Handlebars 10 | services: 11 | - name: Mock for Service1 12 | hostname: service1.example.com 13 | port: 8001 14 | managementRoot: __admin 15 | endpoints: 16 | - path: "/service1" 17 | method: GET 18 | response: service1 19 | - path: "/service1-second/{{var}}" 20 | method: GET 21 | response: 22 | headers: 23 | Content-Type: application/json; charset=UTF-8 24 | status: 201 25 | body: "service1-second: {{var}}" 26 | - path: "/service1-post" 27 | method: POST 28 | response: service1 29 | - name: Mock for Service2 30 | hostname: service2.example.com 31 | port: 8002 32 | managementRoot: __admin 33 | endpoints: 34 | - path: "/service2" 35 | method: GET 36 | response: service2 37 | - path: "/service2-rst" 38 | method: GET 39 | response: 40 | status: "RST" 41 | body: "service2-rst" 42 | - path: "/service2-fin" 43 | method: GET 44 | response: 45 | status: "FIN" 46 | body: "service2-fin" 47 | - name: Asynchronous Mocks 48 | type: kafka 49 | address: localhost:9092 50 | actors: [] 51 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/multiple_services_on_same_port.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "hostname": "service1.example.com", 7 | "port": 8001, 8 | "endpoints": [ 9 | { 10 | "path": "/service1", 11 | "method": "GET", 12 | "response": "service1" 13 | } 14 | ] 15 | }, 16 | { 17 | "name": "Mock for Service2", 18 | "hostname": "service2.example.com", 19 | "port": 8001, 20 | "endpoints": [ 21 | { 22 | "path": "/service2", 23 | "method": "GET", 24 | "response": "service2" 25 | } 26 | ] 27 | }, 28 | { 29 | "hostname": "service4.example.com", 30 | "port": 8001, 31 | "endpoints": [ 32 | { 33 | "path": "/service4", 34 | "method": "GET", 35 | "response": "service4" 36 | } 37 | ] 38 | }, 39 | { 40 | "name": "Mock for Service3", 41 | "hostname": "service3.example.com", 42 | "port": 8001, 43 | "endpoints": [ 44 | { 45 | "path": "/service3", 46 | "method": "GET", 47 | "response": "service3" 48 | } 49 | ] 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/date.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/timestamp", 10 | "method": "GET", 11 | "response": "{{date.timestamp}}" 12 | }, 13 | { 14 | "path": "/timestamp-shift", 15 | "method": "GET", 16 | "response": "{{date.timestamp}}
{{date.timestamp 42}}
{{date.timestamp -42}}" 17 | }, 18 | { 19 | "path": "/ftimestamp", 20 | "method": "GET", 21 | "response": "{{date.ftimestamp}}
{{date.ftimestamp 0.0 7}}" 22 | }, 23 | { 24 | "path": "/ftimestamp-shift", 25 | "method": "GET", 26 | "response": "{{date.ftimestamp}}
{{date.ftimestamp 3.14}}
{{date.ftimestamp -3.14}}" 27 | }, 28 | { 29 | "path": "/date", 30 | "method": "GET", 31 | "response": "{{date.date}}
{{date.date '%Y-%m-%d %H:%M'}}" 32 | }, 33 | { 34 | "path": "/date-shift", 35 | "method": "GET", 36 | "response": { 37 | "headers": { 38 | "Content-Type": "application/json; charset=UTF-8" 39 | }, 40 | "body": "@templates/date.json.hbs" 41 | } 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/date.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Jinja2", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/timestamp", 10 | "method": "GET", 11 | "response": "{{date.timestamp()}}" 12 | }, 13 | { 14 | "path": "/timestamp-shift", 15 | "method": "GET", 16 | "response": "{{date.timestamp()}}
{{date.timestamp(42)}}
{{date.timestamp(-42)}}" 17 | }, 18 | { 19 | "path": "/ftimestamp", 20 | "method": "GET", 21 | "response": "{{date.ftimestamp()}}
{{date.ftimestamp(0.0, 7)}}" 22 | }, 23 | { 24 | "path": "/ftimestamp-shift", 25 | "method": "GET", 26 | "response": "{{date.ftimestamp()}}
{{date.ftimestamp(3.14)}}
{{date.ftimestamp(-3.14)}}" 27 | }, 28 | { 29 | "path": "/date", 30 | "method": "GET", 31 | "response": "{{date.date()}}
{{date.date('%Y-%m-%d %H:%M')}}" 32 | }, 33 | { 34 | "path": "/date-shift", 35 | "method": "GET", 36 | "response": { 37 | "headers": { 38 | "Content-Type": "application/json; charset=UTF-8" 39 | }, 40 | "body": "@templates/date.json.j2" 41 | } 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /tests/configs/stats_config.yaml: -------------------------------------------------------------------------------- 1 | management: 2 | port: 8000 3 | ssl: true 4 | sslCertFile: cert.pem 5 | sslKeyFile: key.pem 6 | globals: 7 | unused: unused 8 | templatingEngine: Handlebars 9 | services: 10 | - name: Mock for Service1 11 | hostname: service1.example.com 12 | port: 8001 13 | managementRoot: __admin 14 | endpoints: 15 | - path: /service1 16 | method: GET 17 | response: service1 18 | - path: /service1-second/{{var}} 19 | method: GET 20 | response: 21 | headers: 22 | Content-Type: application/json; charset=UTF-8 23 | status: 201 24 | body: 'service1-second: {{var}}' 25 | - path: /service1-post 26 | method: POST 27 | response: service1 28 | - path: /service1-resource 29 | method: POST 30 | response: 31 | body: '@templates/hello.json.hbs' 32 | - path: /service1-resource2 33 | method: POST 34 | response: 35 | body: '@templates/hello2.json.hbs' 36 | - name: Mock for Service2 37 | hostname: service2.example.com 38 | port: 8002 39 | managementRoot: __admin 40 | endpoints: 41 | - path: /service2 42 | method: GET 43 | response: service2 44 | - path: /service2-rst 45 | method: GET 46 | response: 47 | status: RST 48 | body: service2-rst 49 | - path: /service2-fin 50 | method: GET 51 | response: 52 | status: FIN 53 | body: service2-fin 54 | - name: Asynchronous Mocks 55 | type: kafka 56 | address: localhost:9092 57 | actors: [] 58 | -------------------------------------------------------------------------------- /tests/assets_copy_kafka_to_mqtt.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import yaml 4 | 5 | 6 | def remove_a_key(d, remove_key) -> dict: 7 | if isinstance(d, dict): 8 | for key in list(d.keys()): 9 | if key == remove_key: 10 | del d[key] 11 | else: 12 | remove_a_key(d[key], remove_key) 13 | elif isinstance(d, list): 14 | for x in d: 15 | remove_a_key(x, remove_key) 16 | 17 | 18 | # Edit tests/configs/yaml/hbs/mqtt/config.yaml 19 | data = yaml.safe_load(open('tests/configs/yaml/hbs/mqtt/config.yaml', 'r')) 20 | 21 | data['services'][0]['type'] = 'mqtt' 22 | data['services'][0]['address'] = "{{env 'MQTT_ADDR' 'localhost:1883'}}" 23 | data['services'][0]['actors'][9]['produce']['headers']['counter'] = "{{counter 'mqttCounter'}}" 24 | data['services'][0]['actors'][4]['produce']['value'] = "value5 and {{consumed.value}}" 25 | 26 | data['services'].pop() 27 | data['services'].pop() 28 | 29 | remove_a_key(data, 'key') 30 | remove_a_key(data, 'headers') 31 | 32 | yaml.dump(data, open('tests/configs/yaml/hbs/mqtt/config.yaml', 'w'), sort_keys=False) 33 | 34 | 35 | # Edit tests/configs/yaml/hbs/mqtt/config.yaml 36 | data = yaml.safe_load(open('tests/configs/yaml/hbs/mqtt/config_error.yaml', 'r')) 37 | 38 | data['services'][0]['type'] = 'mqtt' 39 | data['services'][0]['address'] = "{{env 'MQTT_ADDR' 'localhost:1883'}}" 40 | 41 | remove_a_key(data, 'key') 42 | remove_a_key(data, 'headers') 43 | 44 | yaml.dump(data, open('tests/configs/yaml/hbs/mqtt/config_error.yaml', 'w'), sort_keys=False) 45 | -------------------------------------------------------------------------------- /tests/configs/json/j2/common/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Jinja2", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "hostname": "service1.example.com", 7 | "port": 8001, 8 | "endpoints": [ 9 | { 10 | "path": "/users", 11 | "method": "GET", 12 | "response": { 13 | "headers": { 14 | "Content-Type": "application/json; charset=UTF-8" 15 | }, 16 | "useTemplating": true, 17 | "body": "@templates/users.json.j2" 18 | } 19 | }, 20 | { 21 | "path": "/users/{{ id }}", 22 | "method": "GET", 23 | "response": { 24 | "headers": { 25 | "Content-Type": "application/json; charset=UTF-8" 26 | }, 27 | "useTemplating": true, 28 | "body": "@templates/user.json.j2" 29 | } 30 | } 31 | ] 32 | }, 33 | { 34 | "name": "Mock for Service2", 35 | "hostname": "service2.example.com", 36 | "port": 8002, 37 | "endpoints": [ 38 | { 39 | "path": "/companies", 40 | "method": "POST", 41 | "response": { 42 | "headers": { 43 | "Content-Type": "application/json; charset=UTF-8" 44 | }, 45 | "useTemplating": true, 46 | "body": "@templates/companies.json.j2" 47 | } 48 | } 49 | ] 50 | }, 51 | { 52 | "name": "Service with no endpoints, for bare interceptors", 53 | "port": 8003 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/common/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "hostname": "service1.example.com", 7 | "port": 8001, 8 | "endpoints": [ 9 | { 10 | "path": "/users", 11 | "method": "GET", 12 | "response": { 13 | "headers": { 14 | "Content-Type": "application/json; charset=UTF-8" 15 | }, 16 | "useTemplating": true, 17 | "body": "@templates/users.json.hbs" 18 | } 19 | }, 20 | { 21 | "path": "/users/{{ id }}", 22 | "method": "GET", 23 | "response": { 24 | "headers": { 25 | "Content-Type": "application/json; charset=UTF-8" 26 | }, 27 | "useTemplating": true, 28 | "body": "@templates/user.json.hbs" 29 | } 30 | } 31 | ] 32 | }, 33 | { 34 | "name": "Mock for Service2", 35 | "hostname": "service2.example.com", 36 | "port": 8002, 37 | "endpoints": [ 38 | { 39 | "path": "/companies", 40 | "method": "POST", 41 | "response": { 42 | "headers": { 43 | "Content-Type": "application/json; charset=UTF-8" 44 | }, 45 | "useTemplating": true, 46 | "body": "@templates/companies.json.hbs" 47 | } 48 | } 49 | ] 50 | }, 51 | { 52 | "name": "Service with no endpoints, for bare interceptors", 53 | "port": 8003 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /tests/configs/internal_circular_fallback_to.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000 4 | }, 5 | "templatingEngine": "Handlebars", 6 | "services": [ 7 | { 8 | "name": "Mock for Service1", 9 | "hostname": "service1.example.com", 10 | "port": 8001, 11 | "managementRoot": "__admin", 12 | "fallbackTo": "http://service2.example.com:8002", 13 | "endpoints": [ 14 | { 15 | "path": "/service1", 16 | "method": "GET", 17 | "response": "service1" 18 | }, 19 | { 20 | "path": "/service1-second/{{var}}", 21 | "method": "GET", 22 | "response": { 23 | "status": 201, 24 | "body": "service1-second: {{var}}" 25 | } 26 | } 27 | ] 28 | }, 29 | { 30 | "name": "Mock for Service2", 31 | "hostname": "service2.example.com", 32 | "port": 8002, 33 | "managementRoot": "__admin", 34 | "fallbackTo": "http://service1.example.com:8001", 35 | "endpoints": [ 36 | { 37 | "path": "/service2", 38 | "method": "GET", 39 | "response": "service2" 40 | }, 41 | { 42 | "path": "/service2-rst", 43 | "method": "GET", 44 | "response": { 45 | "status": "RST", 46 | "body": "service2-rst" 47 | } 48 | }, 49 | { 50 | "path": "/service2-fin", 51 | "method": "GET", 52 | "response": { 53 | "status": "FIN", 54 | "body": "service2-fin" 55 | } 56 | } 57 | ] 58 | } 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/http_verbs.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/hello", 10 | "method": "GET", 11 | "response": "GET request" 12 | }, 13 | { 14 | "path": "/hello-lower", 15 | "method": "get", 16 | "response": "GET request" 17 | }, 18 | { 19 | "path": "/hello", 20 | "method": "POST", 21 | "response": "POST request" 22 | }, 23 | { 24 | "path": "/hello", 25 | "method": "HEAD", 26 | "response": "HEAD request" 27 | }, 28 | { 29 | "path": "/hello", 30 | "method": "DELETE", 31 | "response": "DELETE request" 32 | }, 33 | { 34 | "path": "/hello", 35 | "method": "PATCH", 36 | "response": "PATCH request" 37 | }, 38 | { 39 | "path": "/hello", 40 | "method": "PUT", 41 | "response": "PUT request" 42 | }, 43 | { 44 | "path": "/hello", 45 | "method": "OPTIONS", 46 | "response": "OPTIONS request" 47 | }, 48 | { 49 | "path": "/method-not-allowed-unless-get", 50 | "method": "GET", 51 | "response": "GET request" 52 | }, 53 | { 54 | "path": "/method-not-allowed-unless-post", 55 | "method": "POST", 56 | "response": "POST request" 57 | } 58 | ] 59 | } 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/config_custom_oas4.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "templatingEngine": "Handlebars", 9 | "services": [ 10 | { 11 | "name": "Mock for Service1", 12 | "hostname": "service1.example.com", 13 | "port": 8001, 14 | "managementRoot": "__admin", 15 | "oas": "@../common/config.json", 16 | "endpoints": [ 17 | { 18 | "path": "/service1", 19 | "method": "GET", 20 | "response": "service1" 21 | }, 22 | { 23 | "path": "/service1-second/{{var}}", 24 | "method": "GET", 25 | "response": { 26 | "status": 201, 27 | "body": "service1-second: {{var}}" 28 | } 29 | } 30 | ] 31 | }, 32 | { 33 | "name": "Mock for Service2", 34 | "hostname": "service2.example.com", 35 | "port": 8002, 36 | "managementRoot": "__admin", 37 | "endpoints": [ 38 | { 39 | "path": "/service2", 40 | "method": "GET", 41 | "response": "service2" 42 | }, 43 | { 44 | "path": "/service2-rst", 45 | "method": "GET", 46 | "response": { 47 | "status": "RST", 48 | "body": "service2-rst" 49 | } 50 | }, 51 | { 52 | "path": "/service2-fin", 53 | "method": "GET", 54 | "response": { 55 | "status": "FIN", 56 | "body": "service2-fin" 57 | } 58 | } 59 | ] 60 | } 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/config_custom_oas.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "templatingEngine": "Handlebars", 9 | "services": [ 10 | { 11 | "name": "Mock for Service1", 12 | "hostname": "service1.example.com", 13 | "port": 8001, 14 | "managementRoot": "__admin", 15 | "oas": "@oas_documents/service1.json", 16 | "endpoints": [ 17 | { 18 | "path": "/service1", 19 | "method": "GET", 20 | "response": "service1" 21 | }, 22 | { 23 | "path": "/service1-second/{{var}}", 24 | "method": "GET", 25 | "response": { 26 | "status": 201, 27 | "body": "service1-second: {{var}}" 28 | } 29 | } 30 | ] 31 | }, 32 | { 33 | "name": "Mock for Service2", 34 | "hostname": "service2.example.com", 35 | "port": 8002, 36 | "managementRoot": "__admin", 37 | "endpoints": [ 38 | { 39 | "path": "/service2", 40 | "method": "GET", 41 | "response": "service2" 42 | }, 43 | { 44 | "path": "/service2-rst", 45 | "method": "GET", 46 | "response": { 47 | "status": "RST", 48 | "body": "service2-rst" 49 | } 50 | }, 51 | { 52 | "path": "/service2-fin", 53 | "method": "GET", 54 | "response": { 55 | "status": "FIN", 56 | "body": "service2-fin" 57 | } 58 | } 59 | ] 60 | } 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/config_custom_oas3.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "templatingEngine": "Handlebars", 9 | "services": [ 10 | { 11 | "name": "Mock for Service1", 12 | "hostname": "service1.example.com", 13 | "port": 8001, 14 | "managementRoot": "__admin", 15 | "oas": "@oas_documents/not_existing_file.json", 16 | "endpoints": [ 17 | { 18 | "path": "/service1", 19 | "method": "GET", 20 | "response": "service1" 21 | }, 22 | { 23 | "path": "/service1-second/{{var}}", 24 | "method": "GET", 25 | "response": { 26 | "status": 201, 27 | "body": "service1-second: {{var}}" 28 | } 29 | } 30 | ] 31 | }, 32 | { 33 | "name": "Mock for Service2", 34 | "hostname": "service2.example.com", 35 | "port": 8002, 36 | "managementRoot": "__admin", 37 | "endpoints": [ 38 | { 39 | "path": "/service2", 40 | "method": "GET", 41 | "response": "service2" 42 | }, 43 | { 44 | "path": "/service2-rst", 45 | "method": "GET", 46 | "response": { 47 | "status": "RST", 48 | "body": "service2-rst" 49 | } 50 | }, 51 | { 52 | "path": "/service2-fin", 53 | "method": "GET", 54 | "response": { 55 | "status": "FIN", 56 | "body": "service2-fin" 57 | } 58 | } 59 | ] 60 | } 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/config_custom_oas2.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "templatingEngine": "Handlebars", 9 | "services": [ 10 | { 11 | "name": "Mock for Service1", 12 | "hostname": "service1.example.com", 13 | "port": 8001, 14 | "managementRoot": "__admin", 15 | "oas": "@/oas_documents/service1_no_servers.json", 16 | "endpoints": [ 17 | { 18 | "path": "/service1", 19 | "method": "GET", 20 | "response": "service1" 21 | }, 22 | { 23 | "path": "/service1-second/{{var}}", 24 | "method": "GET", 25 | "response": { 26 | "status": 201, 27 | "body": "service1-second: {{var}}" 28 | } 29 | } 30 | ] 31 | }, 32 | { 33 | "name": "Mock for Service2", 34 | "hostname": "service2.example.com", 35 | "port": 8002, 36 | "managementRoot": "__admin", 37 | "endpoints": [ 38 | { 39 | "path": "/service2", 40 | "method": "GET", 41 | "response": "service2" 42 | }, 43 | { 44 | "path": "/service2-rst", 45 | "method": "GET", 46 | "response": { 47 | "status": "RST", 48 | "body": "service2-rst" 49 | } 50 | }, 51 | { 52 | "path": "/service2-fin", 53 | "method": "GET", 54 | "response": { 55 | "status": "FIN", 56 | "body": "service2-fin" 57 | } 58 | } 59 | ] 60 | } 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /tests/assets_copy_kafka_to_redis.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import yaml 4 | 5 | 6 | def remove_a_key(d, remove_key) -> dict: 7 | if isinstance(d, dict): 8 | for key in list(d.keys()): 9 | if key == remove_key: 10 | del d[key] 11 | else: 12 | remove_a_key(d[key], remove_key) 13 | elif isinstance(d, list): 14 | for x in d: 15 | remove_a_key(x, remove_key) 16 | 17 | 18 | # Edit tests/configs/yaml/hbs/redis/config.yaml 19 | data = yaml.safe_load(open('tests/configs/yaml/hbs/redis/config.yaml', 'r')) 20 | 21 | data['services'][0]['type'] = 'redis' 22 | data['services'][0]['address'] = "{{env 'REDIS_ADDR' 'localhost:6379'}}" 23 | data['services'][0]['actors'][9]['produce']['headers']['counter'] = "{{counter 'redisCounter'}}" 24 | data['services'][0]['actors'][4]['produce']['value'] = "value5 and {{consumed.value}}" 25 | 26 | data['services'][2]['type'] = 'redis' 27 | data['services'][2]['address'] = 'localhost:6380' 28 | 29 | data['services'][3]['type'] = 'redis' 30 | data['services'][3]['address'] = 'localhost:6381' 31 | 32 | remove_a_key(data, 'key') 33 | remove_a_key(data, 'headers') 34 | 35 | yaml.dump(data, open('tests/configs/yaml/hbs/redis/config.yaml', 'w'), sort_keys=False) 36 | 37 | 38 | # Edit tests/configs/yaml/hbs/redis/config.yaml 39 | data = yaml.safe_load(open('tests/configs/yaml/hbs/redis/config_error.yaml', 'r')) 40 | 41 | data['services'][0]['type'] = 'redis' 42 | data['services'][0]['address'] = "{{env 'AMQP_ADDR' 'localhost:6379'}}" 43 | 44 | remove_a_key(data, 'key') 45 | remove_a_key(data, 'headers') 46 | 47 | yaml.dump(data, open('tests/configs/yaml/hbs/redis/config_error.yaml', 'w'), sort_keys=False) 48 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.8" 4 | branches: 5 | only: 6 | - main 7 | - /^(\d+\.?)+$/ 8 | services: 9 | - docker 10 | addons: 11 | hosts: 12 | - service1.example.com 13 | - service2.example.com 14 | - service3.example.com 15 | install: 16 | - travis_fold start "Install.Pip.Package" && make install-cloud && make install-dev && pip3 show mockintosh && travis_fold end "Install.Pip.Package" 17 | - travis_fold start "Build.Image" && make build && docker image ls mockintosh && travis_fold end "Build.Image" 18 | script: 19 | - stty cols 120 20 | - ./ps.sh & 21 | - travis_fold start "Unit.Tests" && make test-with-coverage && travis_fold end "Unit.Tests" 22 | - travis_fold start "StopContainers.Tests" && make stop-containers && travis_fold end "StopContainers.Tests" 23 | - travis_fold start "Integration.Tests" && make test-integration && travis_fold end "Integration.Tests" 24 | after_success: 25 | - if [[ $TRAVIS_TAG =~ ^([0-9]+\.?)+$ ]]; then ./release.sh; else echo Not pushing "$TRAVIS_TAG"; fi 26 | - make coverage-after 27 | - codecov 28 | # after_failure: 29 | # - travis_fold start "server_log" && ( cat tests_integrated/server.log || echo No logfile) && travis_fold end "server_log" # the log from container 30 | before_deploy: 31 | - sudo apt-get -y update && sudo apt-get install -y nsis 32 | - ./msi.sh 33 | deploy: 34 | - provider: releases 35 | api_key: "$GH_TOKEN" 36 | file_glob: true 37 | file: "build/nsis/Mockintosh_*_x64.exe" 38 | skip_cleanup: true 39 | on: 40 | tags: true 41 | - edge: true # use latest v2 deploy 42 | provider: pypi 43 | distributions: "sdist bdist_wheel" 44 | # skip_cleanup: true 45 | skip_existing: true 46 | on: 47 | tags: true 48 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/body/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Handlebars 3 | services: 4 | - name: Mock for Service1 5 | port: 8001 6 | endpoints: 7 | - path: "/body-jsonpath-tpl" 8 | method: POST 9 | response: 'body jsonpath matched: {{jsonPath request.json ''$.key''}} {{jsonPath 10 | request.json ''$.key2''}}' 11 | - path: "/body-json-schema" 12 | method: POST 13 | body: 14 | schema: 15 | type: object 16 | properties: 17 | somekey: {} 18 | required: 19 | - somekey 20 | response: body json schema matched 21 | - path: "/body-json-schema-file" 22 | method: POST 23 | body: 24 | schema: "@body_schema.json" 25 | response: body json schema matched 26 | - path: "/body-json-schema-file-error" 27 | method: POST 28 | body: 29 | schema: "@body_schema_error.json" 30 | response: body json schema matched 31 | - path: "/body-regex" 32 | method: POST 33 | body: 34 | text: "{{regEx '(\\d)-required-(\\d)' 'val1' 'val2'}}" 35 | response: 'body regex matched: {{val1}} {{val2}}' 36 | - path: "/body-urlencoded" 37 | method: POST 38 | body: 39 | urlencoded: 40 | key1: constant 41 | key2: "{{var1}}" 42 | key3: "{{regEx 'prefix-(.*)-(.*)-suffix' 'var2' 'var3'}}" 43 | response: 'body urlencoded matched: {{request.body.key1}} {{var1}} {{var2}} {{var3}}' 44 | - path: "/body-multipart" 45 | method: POST 46 | body: 47 | multipart: 48 | key1: constant 49 | key2: "{{var1}}" 50 | key3: "{{regEx 'prefix-(.*)-(.*)-suffix' 'var2' 'var3'}}" 51 | response: 'body multipart matched: {{request.body.key1}} {{var1}} {{var2}} {{var3}}' 52 | - path: "/body-text" 53 | method: POST 54 | body: 55 | text: "{{body_text}}" 56 | response: 'body text matched: {{body_text}}' 57 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/body/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Jinja2 3 | services: 4 | - name: Mock for Service1 5 | port: 8001 6 | endpoints: 7 | - path: "/body-jsonpath-tpl" 8 | method: POST 9 | response: 'body jsonpath matched: {{jsonPath(request.json, ''$.key'')}} {{jsonPath(request.json, 10 | ''$.key2'')}}' 11 | - path: "/body-json-schema" 12 | method: POST 13 | body: 14 | schema: 15 | type: object 16 | properties: 17 | somekey: {} 18 | required: 19 | - somekey 20 | response: body json schema matched 21 | - path: "/body-json-schema-file" 22 | method: POST 23 | body: 24 | schema: "@body_schema.json" 25 | response: body json schema matched 26 | - path: "/body-json-schema-file-error" 27 | method: POST 28 | body: 29 | schema: "@body_schema_error.json" 30 | response: body json schema matched 31 | - path: "/body-regex" 32 | method: POST 33 | body: 34 | text: "{{regEx('(\\d)-required-(\\d)', 'val1', 'val2')}}" 35 | response: 'body regex matched: {{val1}} {{val2}}' 36 | - path: "/body-urlencoded" 37 | method: POST 38 | body: 39 | urlencoded: 40 | key1: constant 41 | key2: "{{var1}}" 42 | key3: "{{regEx('prefix-(.*)-(.*)-suffix', 'var2', 'var3')}}" 43 | response: 'body urlencoded matched: {{request.body.key1}} {{var1}} {{var2}} {{var3}}' 44 | - path: "/body-multipart" 45 | method: POST 46 | body: 47 | multipart: 48 | key1: constant 49 | key2: "{{var1}}" 50 | key3: "{{regEx('prefix-(.*)-(.*)-suffix', 'var2', 'var3')}}" 51 | response: 'body multipart matched: {{request.body.key1}} {{var1}} {{var2}} {{var3}}' 52 | - path: "/body-text" 53 | method: POST 54 | body: 55 | text: "{{body_text}}" 56 | response: 'body text matched: {{body_text}}' 57 | -------------------------------------------------------------------------------- /tests/interceptingpackage/interceptors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | .. module:: __init__ 6 | :synopsis: module that contains dummy interceptors for testing. 7 | """ 8 | 9 | import logging 10 | 11 | from mockintosh import Request, Response 12 | 13 | 14 | def dummy1(req: Request, resp: Response): 15 | resp.status = 414 16 | 17 | 18 | def dummy2(req: Request, resp: Response): 19 | resp.status = 417 20 | 21 | 22 | def not_existing_path(req: Request, resp: Response): 23 | if req.path == '/interceptor-modified': 24 | # should allow reading and modifying response status code, headers, body 25 | resp.status = 201 26 | resp.headers['someheader'] = 'some-i-val' 27 | resp.body = 'intercepted' 28 | 29 | 30 | def intercept_logging(req: Request, resp: Response): 31 | logging.info("Processed intercepted request: %r, produced response: %r", req, resp) 32 | 33 | 34 | def request_object(req: Request, resp: Response): 35 | if req.path == '/request1': 36 | assert req.version == 'HTTP/1.1' 37 | assert req.remoteIp in ('127.0.0.1', '::1') 38 | assert req.protocol == 'http' 39 | assert req.host == 'localhost:8003' 40 | assert req.hostName == 'localhost' 41 | assert req.uri == '/request1?a=hello%20world&b=3' 42 | assert req.method == 'GET' 43 | assert req.path == '/request1' 44 | assert req.headers['Host'] == 'localhost:8003' 45 | assert req.headers['Accept'] == '*/*' 46 | assert req.headers['Connection'] == 'keep-alive' 47 | assert req.headers['Cache-Control'] == 'no-cache' 48 | assert req.queryString['a'] == 'hello world' 49 | assert req.queryString['b'] == '3' 50 | elif req.path == '/request2': 51 | assert req.method == 'POST' 52 | assert req.body['param1'] == 'value1' 53 | assert req.body['param2'] == 'value2' 54 | 55 | resp.status = 200 56 | -------------------------------------------------------------------------------- /mockintosh/params.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | .. module:: __init__ 6 | :synopsis: module that contains classes for request parameters. 7 | """ 8 | 9 | from typing import ( 10 | Union 11 | ) 12 | 13 | 14 | class ParamBase: 15 | 16 | def __init__(self, key: str, value: Union[dict, str]): 17 | self.key = key 18 | self.value = value 19 | 20 | 21 | class HeaderParam(ParamBase): 22 | 23 | def __init__(self, key: str, value: Union[dict, str]): 24 | super().__init__(key, value) 25 | 26 | 27 | class QueryStringParam(ParamBase): 28 | 29 | def __init__(self, key: str, value: Union[dict, str]): 30 | super().__init__(key, value) 31 | 32 | 33 | class BodyTextParam(ParamBase): 34 | 35 | def __init__(self, key: str, value: Union[dict, str]): 36 | super().__init__(key, value) 37 | 38 | 39 | class BodyUrlencodedParam(ParamBase): 40 | 41 | def __init__(self, key: str, value: Union[dict, str]): 42 | super().__init__(key, value) 43 | 44 | 45 | class BodyMultipartParam(ParamBase): 46 | 47 | def __init__(self, key: str, value: Union[dict, str]): 48 | super().__init__(key, value) 49 | 50 | 51 | class BodyGraphQLVariablesParam(ParamBase): 52 | 53 | def __init__(self, key: str, value: Union[dict, str]): 54 | super().__init__(key, value) 55 | 56 | 57 | class AsyncValueParam(ParamBase): 58 | 59 | def __init__(self, key: str, value: Union[dict, str]): 60 | super().__init__(key, value) 61 | 62 | 63 | class AsyncKeyParam(ParamBase): 64 | 65 | def __init__(self, key: str, value: Union[dict, str]): 66 | super().__init__(key, value) 67 | 68 | 69 | class AsyncHeadersParam(ParamBase): 70 | 71 | def __init__(self, key: str, value: Union[dict, str]): 72 | super().__init__(key, value) 73 | 74 | 75 | class AsyncAmqpPropertiesParam(ParamBase): 76 | 77 | def __init__(self, key: str, value: Union[dict, str]): 78 | super().__init__(key, value) 79 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/performance/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "management": { 4 | "port": 8000 5 | }, 6 | "performanceProfiles": { 7 | "profile1": { 8 | "ratio": 1.0, 9 | "delay": 1.5, 10 | "faults": { 11 | "PASS": 0.4, 12 | "RST": 0.2, 13 | "FIN": 0.1, 14 | "200": 0.3, 15 | "201": 0.1, 16 | "400": 0.1, 17 | "500": 0.2, 18 | "503": 0.1 19 | } 20 | }, 21 | "profile2": { 22 | "ratio": 0.3, 23 | "delay": 1.8 24 | }, 25 | "profile3": { 26 | "ratio": 1.0, 27 | "delay": 7.3 28 | }, 29 | "profile4": { 30 | "ratio": 0.5, 31 | "delay": 13.3 32 | } 33 | }, 34 | "globals": { 35 | "performanceProfile": "profile1" 36 | }, 37 | "services": [ 38 | { 39 | "name": "Mock for Service1", 40 | "hostname": "service1.example.com", 41 | "port": 8001, 42 | "endpoints": [ 43 | { 44 | "path": "/service1", 45 | "method": "GET", 46 | "response": "service1" 47 | } 48 | ] 49 | }, 50 | { 51 | "performanceProfile": "profile2", 52 | "name": "Mock for Service2", 53 | "hostname": "service2.example.com", 54 | "port": 8002, 55 | "endpoints": [ 56 | { 57 | "path": "/service2", 58 | "method": "GET", 59 | "response": "service2" 60 | }, 61 | { 62 | "performanceProfile": "profile4", 63 | "path": "/service2-endpoint2", 64 | "method": "GET", 65 | "response": "service2-endpoint2" 66 | } 67 | ] 68 | }, 69 | { 70 | "name": "Mock for Service3", 71 | "hostname": "service3.example.com", 72 | "port": 8003, 73 | "endpoints": [ 74 | { 75 | "performanceProfile": "profile3", 76 | "path": "/service3", 77 | "method": "GET", 78 | "response": "service3" 79 | } 80 | ] 81 | } 82 | ] 83 | } 84 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/graphql/config.yaml: -------------------------------------------------------------------------------- 1 | management: 2 | port: 8000 3 | services: 4 | - name: GrahpQL Example 5 | port: 8001 6 | managementRoot: __admin 7 | endpoints: 8 | - path: /graphql 9 | response: 10 | headers: 11 | Content-Type: application/json 12 | body: '@templates/resp1.json.hbs' 13 | useTemplating: true 14 | method: post 15 | body: 16 | graphql-query: | 17 | query HeroNameAndFriends { 18 | hero( 19 | where: {name: {_eq: "{{regEx '.*' 'name_eq'}}"}, _and: {age: {_gt: {{regEx '.*' 'age_gt'}}}}} 20 | ) { 21 | name 22 | age 23 | friends { 24 | name 25 | } 26 | } 27 | } 28 | - path: /graphql 29 | response: 30 | headers: 31 | Content-Type: application/json 32 | body: '@templates/resp2.json.hbs' 33 | useTemplating: true 34 | method: post 35 | body: 36 | graphql-query: | 37 | query HeroNameAndFriends { 38 | hero( 39 | where: {name: {_eq: "{{regEx '.*' 'name_eq'}}"}, _and: {age: {_gt: {{regEx '.*' 'age_gt'}}}}} 40 | ) { 41 | name 42 | age 43 | } 44 | } 45 | - path: /graphql 46 | response: 47 | headers: 48 | Content-Type: application/json 49 | body: '@templates/resp3.json.hbs' 50 | useTemplating: true 51 | method: post 52 | body: 53 | graphql-query: "@example.graphql" 54 | - path: /graphql 55 | response: 56 | headers: 57 | Content-Type: application/json 58 | body: '@templates/resp4.json.hbs' 59 | useTemplating: true 60 | method: post 61 | body: 62 | graphql-query: | 63 | query HeroNameAndFriends { 64 | hero( 65 | where: {name: {_eq: "{{regEx '.*' 'name_eq'}}"}, _and: {age: {_gt: {{regEx '.*' 'age_gt'}}}}} 66 | ) { 67 | name 68 | city 69 | } 70 | } 71 | graphql-variables: 72 | var1: val1 73 | var2: "{{regEx '\\d'}}" 74 | -------------------------------------------------------------------------------- /tests/configs/fallback_to.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000 4 | }, 5 | "templatingEngine": "Handlebars", 6 | "services": [ 7 | { 8 | "name": "Mock for Service1", 9 | "hostname": "service1.example.com", 10 | "port": 8001, 11 | "managementRoot": "__admin", 12 | "fallbackTo": "http://localhost:8999/", 13 | "endpoints": [ 14 | { 15 | "path": "/service1", 16 | "method": "GET", 17 | "response": "service1" 18 | }, 19 | { 20 | "path": "/service1-second/{{var}}", 21 | "method": "GET", 22 | "response": { 23 | "status": 201, 24 | "body": "service1-second: {{var}}" 25 | } 26 | } 27 | ] 28 | }, 29 | { 30 | "name": "Mock for Service2", 31 | "hostname": "service2.example.com", 32 | "port": 8002, 33 | "managementRoot": "__admin", 34 | "fallbackTo": "http://service1.example.com:8001", 35 | "endpoints": [ 36 | { 37 | "path": "/service2", 38 | "method": "GET", 39 | "response": "service2" 40 | }, 41 | { 42 | "path": "/service2-rst", 43 | "method": "GET", 44 | "response": { 45 | "status": "RST", 46 | "body": "service2-rst" 47 | } 48 | }, 49 | { 50 | "path": "/service2-fin", 51 | "method": "GET", 52 | "response": { 53 | "status": "FIN", 54 | "body": "service2-fin" 55 | } 56 | } 57 | ] 58 | }, 59 | { 60 | "name": "Mock for Service3", 61 | "hostname": "service3.example.com", 62 | "port": 8003, 63 | "managementRoot": "__admin", 64 | "fallbackTo": "http://localhost:8999", 65 | "endpoints": [] 66 | }, 67 | { 68 | "name": "Mock for Service4", 69 | "hostname": "service4.example.com", 70 | "port": 8004, 71 | "managementRoot": "__admin", 72 | "fallbackTo": "http://service4.example.com:8004", 73 | "endpoints": [] 74 | } 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /mockintosh/ssl/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | hcCKxHqzRA== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/graphql/config.yaml: -------------------------------------------------------------------------------- 1 | templatingEngine: Jinja2 2 | management: 3 | port: 8000 4 | services: 5 | - name: GrahpQL Example 6 | port: 8001 7 | managementRoot: __admin 8 | endpoints: 9 | - path: /graphql 10 | response: 11 | headers: 12 | Content-Type: application/json 13 | body: '@templates/resp1.json.j2' 14 | useTemplating: true 15 | method: post 16 | body: 17 | graphql-query: | 18 | query HeroNameAndFriends { 19 | hero( 20 | where: {name: {_eq: "{{regEx('.*', 'name_eq')}}"}, _and: {age: {_gt: {{regEx('.*', 'age_gt')}}}}} 21 | ) { 22 | name 23 | age 24 | friends { 25 | name 26 | } 27 | } 28 | } 29 | - path: /graphql 30 | response: 31 | headers: 32 | Content-Type: application/json 33 | body: '@templates/resp2.json.j2' 34 | useTemplating: true 35 | method: post 36 | body: 37 | graphql-query: | 38 | query HeroNameAndFriends { 39 | hero( 40 | where: {name: {_eq: "{{regEx('.*', 'name_eq')}}"}, _and: {age: {_gt: {{regEx('.*', 'age_gt')}}}}} 41 | ) { 42 | name 43 | age 44 | } 45 | } 46 | - path: /graphql 47 | response: 48 | headers: 49 | Content-Type: application/json 50 | body: '@templates/resp3.json.j2' 51 | useTemplating: true 52 | method: post 53 | body: 54 | graphql-query: "@example.graphql" 55 | - path: /graphql 56 | response: 57 | headers: 58 | Content-Type: application/json 59 | body: '@templates/resp4.json.j2' 60 | useTemplating: true 61 | method: post 62 | body: 63 | graphql-query: | 64 | query HeroNameAndFriends { 65 | hero( 66 | where: {name: {_eq: "{{regEx('.*', 'name_eq')}}"}, _and: {age: {_gt: {{regEx('.*', 'age_gt')}}}}} 67 | ) { 68 | name 69 | city 70 | } 71 | } 72 | graphql-variables: 73 | var1: val1 74 | var2: "{{regEx('\\d')}}" 75 | -------------------------------------------------------------------------------- /msi.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | import os 3 | import platform 4 | 5 | import pkg_resources 6 | from nsist import main as pynsist_main 7 | from poet import merge_graphs, make_graph 8 | 9 | from mockintosh import __version__ 10 | 11 | 12 | def generate_pynsist_config(dependencies, wheel_dir, version): 13 | cfg = configparser.ConfigParser() 14 | cfg['Application'] = { 15 | 'name': 'Mockintosh', 16 | 'version': version, 17 | 'publisher': 'UP9 Inc.', 18 | 'entry_point': 'mockintosh:demo_run', 19 | 'console': 'true', 20 | 'icon': 'docs/favicon.ico', 21 | 'license_file': 'LICENSE', 22 | } 23 | 24 | cfg['Command mockintosh'] = { 25 | 'entry_point': 'mockintosh:initiate', 26 | 'console': 'true', 27 | } 28 | 29 | cfg['Python'] = { 30 | 'bitness': 64, 31 | 'version': platform.python_version(), 32 | } 33 | 34 | wheels_list = ["%s==%s" % (package_name, version) for package_name, version in dependencies] 35 | 36 | cfg['Include'] = { 37 | 'pypi_wheels': "\n".join(wheels_list), 38 | 'extra_wheel_sources': wheel_dir, 39 | 'files': '\n'.join([ 40 | 'README.md' 41 | ]) 42 | } 43 | 44 | cfg['Build'] = { 45 | 'installer_name': "Mockintosh_%s_x64.exe" % version 46 | } 47 | 48 | return cfg 49 | 50 | 51 | def get_deps(pkgs): 52 | # copied a piece from `poet` 53 | nodes = merge_graphs(make_graph(p) for p in pkgs) 54 | return nodes 55 | 56 | 57 | def main(): 58 | wheel_dir = "dist-msi" 59 | os.makedirs(wheel_dir, exist_ok=True) 60 | 61 | dependencies = [(x['name'], x['version']) for x in get_deps(['mockintosh']).values()] 62 | dependencies.extend((x.key, x.version) for x in pkg_resources.working_set if x.key == 'setuptools') 63 | cfg = generate_pynsist_config(dependencies, wheel_dir, __version__) 64 | 65 | fname = 'msi.cfg' 66 | with open(fname, 'w') as fp: 67 | cfg.write(fp) 68 | 69 | rc = pynsist_main([fname]) 70 | assert not rc, "pynsist failed with code %s" % rc 71 | 72 | 73 | if __name__ == '__main__': 74 | main() 75 | -------------------------------------------------------------------------------- /tests_integrated/subdir/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | X8EOd69Piw== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/new_resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "templatingEngine": "Handlebars", 9 | "services": [ 10 | { 11 | "name": "Mock for Service1", 12 | "hostname": "service1.example.com", 13 | "port": 8001, 14 | "managementRoot": "__admin", 15 | "endpoints": [ 16 | { 17 | "path": "/service1", 18 | "method": "GET", 19 | "response": "service1" 20 | }, 21 | { 22 | "path": "/service1-second/{{var}}", 23 | "method": "GET", 24 | "response": { 25 | "status": 201, 26 | "body": "service1-second: {{var}}" 27 | } 28 | }, 29 | { 30 | "path": "/service1-new-file", 31 | "method": "GET", 32 | "response": { 33 | "status": 200, 34 | "body": "@new_res/new_body.txt" 35 | } 36 | }, 37 | { 38 | "path": "/service1-new-file-2", 39 | "method": "GET", 40 | "response": { 41 | "status": 200, 42 | "body": "@new_res/new_body2.txt" 43 | } 44 | }, 45 | { 46 | "path": "/service1-new-file-3-dir", 47 | "method": "GET", 48 | "response": { 49 | "status": 200, 50 | "body": "@new_res" 51 | } 52 | } 53 | ] 54 | }, 55 | { 56 | "name": "Mock for Service2", 57 | "hostname": "service2.example.com", 58 | "port": 8002, 59 | "managementRoot": "__admin", 60 | "endpoints": [ 61 | { 62 | "path": "/service2", 63 | "method": "GET", 64 | "response": "service2" 65 | }, 66 | { 67 | "path": "/service2-rst", 68 | "method": "GET", 69 | "response": { 70 | "status": "RST", 71 | "body": "service2-rst" 72 | } 73 | }, 74 | { 75 | "path": "/service2-fin", 76 | "method": "GET", 77 | "response": { 78 | "status": "FIN", 79 | "body": "service2-fin" 80 | } 81 | } 82 | ] 83 | } 84 | ] 85 | } 86 | -------------------------------------------------------------------------------- /tests/configs/stats_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "globals": { 9 | "unused": "unused" 10 | }, 11 | "templatingEngine": "Handlebars", 12 | "services": [ 13 | { 14 | "name": "Mock for Service1", 15 | "hostname": "service1.example.com", 16 | "port": 8001, 17 | "managementRoot": "__admin", 18 | "endpoints": [ 19 | { 20 | "path": "/service1", 21 | "method": "GET", 22 | "response": "service1" 23 | }, 24 | { 25 | "path": "/service1-second/{{var}}", 26 | "method": "GET", 27 | "response": { 28 | "headers": { 29 | "Content-Type": "application/json; charset=UTF-8" 30 | }, 31 | "status": 201, 32 | "body": "service1-second: {{var}}" 33 | } 34 | }, 35 | { 36 | "path": "/service1-post", 37 | "method": "POST", 38 | "response": "service1" 39 | }, 40 | { 41 | "path": "/service1-resource", 42 | "method": "POST", 43 | "response": { 44 | "body": "@templates/hello.json.hbs" 45 | } 46 | }, 47 | { 48 | "path": "/service1-resource2", 49 | "method": "POST", 50 | "response": { 51 | "body": "@templates/hello2.json.hbs" 52 | } 53 | } 54 | ] 55 | }, 56 | { 57 | "name": "Mock for Service2", 58 | "hostname": "service2.example.com", 59 | "port": 8002, 60 | "managementRoot": "__admin", 61 | "endpoints": [ 62 | { 63 | "path": "/service2", 64 | "method": "GET", 65 | "response": "service2" 66 | }, 67 | { 68 | "path": "/service2-rst", 69 | "method": "GET", 70 | "response": { 71 | "status": "RST", 72 | "body": "service2-rst" 73 | } 74 | }, 75 | { 76 | "path": "/service2-fin", 77 | "method": "GET", 78 | "response": { 79 | "status": "FIN", 80 | "body": "service2-fin" 81 | } 82 | } 83 | ] 84 | }, 85 | { 86 | "name": "Asynchronous Mocks", 87 | "type": "kafka", 88 | "address": "localhost:9092", 89 | "actors": [] 90 | } 91 | ] 92 | } 93 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "globals": { 9 | "unused": "unused" 10 | }, 11 | "templatingEngine": "Handlebars", 12 | "services": [ 13 | { 14 | "name": "Mock for Service1", 15 | "hostname": "service1.example.com", 16 | "port": 8001, 17 | "managementRoot": "__admin", 18 | "endpoints": [ 19 | { 20 | "path": "/service1", 21 | "method": "GET", 22 | "response": "service1" 23 | }, 24 | { 25 | "path": "/service1-second/{{var}}", 26 | "method": "GET", 27 | "response": { 28 | "headers": { 29 | "Content-Type": "application/json; charset=UTF-8" 30 | }, 31 | "status": 201, 32 | "body": "service1-second: {{var}}" 33 | } 34 | }, 35 | { 36 | "path": "/service1-post", 37 | "method": "POST", 38 | "response": "service1" 39 | }, 40 | { 41 | "path": "/service1-resource", 42 | "method": "POST", 43 | "response": { 44 | "body": "@templates/hello.json.hbs" 45 | } 46 | }, 47 | { 48 | "path": "/service1-resource2", 49 | "method": "POST", 50 | "response": { 51 | "body": "@templates/hello2.json.hbs" 52 | } 53 | } 54 | ] 55 | }, 56 | { 57 | "name": "Mock for Service2", 58 | "hostname": "service2.example.com", 59 | "port": 8002, 60 | "managementRoot": "__admin", 61 | "endpoints": [ 62 | { 63 | "path": "/service2", 64 | "method": "GET", 65 | "response": "service2" 66 | }, 67 | { 68 | "path": "/service2-rst", 69 | "method": "GET", 70 | "response": { 71 | "status": "RST", 72 | "body": "service2-rst" 73 | } 74 | }, 75 | { 76 | "path": "/service2-fin", 77 | "method": "GET", 78 | "response": { 79 | "status": "FIN", 80 | "body": "service2-fin" 81 | } 82 | } 83 | ] 84 | }, 85 | { 86 | "name": "Asynchronous Mocks", 87 | "type": "kafka", 88 | "address": "localhost:9092", 89 | "actors": [] 90 | } 91 | ] 92 | } 93 | -------------------------------------------------------------------------------- /mockintosh/services/asynchronous/_looping.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | .. module:: __init__ 6 | :synopsis: module that contains asynchronous looping related methods. 7 | """ 8 | 9 | import sys 10 | import threading 11 | 12 | from mockintosh.services.asynchronous import AsyncService, AsyncConsumerGroup, AsyncActor, AsyncProducer, AsyncConsumer 13 | from mockintosh.services.asynchronous.kafka import KafkaConsumerGroup # noqa: F401 14 | from mockintosh.services.asynchronous.amqp import AmqpConsumerGroup # noqa: F401 15 | from mockintosh.services.asynchronous.redis import RedisConsumerGroup # noqa: F401 16 | 17 | try: 18 | from mockintosh.services.asynchronous.gpubsub import GpubsubConsumerGroup # noqa: F401 19 | except ModuleNotFoundError: 20 | pass 21 | 22 | try: 23 | from mockintosh.services.asynchronous.amazonsqs import AmazonsqsConsumerGroup # noqa: F401 24 | except ModuleNotFoundError: 25 | pass 26 | 27 | from mockintosh.services.asynchronous.mqtt import MqttConsumerGroup # noqa: F401 28 | 29 | 30 | def run_loops(): 31 | for service in AsyncService.services: 32 | class_name_prefix = service.type.capitalize() 33 | consumer_groups = {} 34 | 35 | for actor in service.actors: 36 | t = threading.Thread(target=actor.run_produce_loop, args=(), kwargs={}) 37 | t.daemon = True 38 | t.start() 39 | 40 | if actor.consumer is not None: 41 | if actor.consumer.topic not in consumer_groups.keys(): 42 | consumer_group = getattr(sys.modules[__name__], '%sConsumerGroup' % class_name_prefix)() 43 | consumer_group.add_consumer(actor.consumer) 44 | consumer_groups[actor.consumer.topic] = consumer_group 45 | else: 46 | consumer_groups[actor.consumer.topic].add_consumer(actor.consumer) 47 | 48 | for consumer_group in AsyncConsumerGroup.groups: 49 | t = threading.Thread(target=consumer_group.consume, args=(), kwargs={}) 50 | t.daemon = True 51 | t.start() 52 | 53 | 54 | def stop_loops(): 55 | for actor in AsyncActor.actors: 56 | actor.stop = True 57 | 58 | for consumer_group in AsyncConsumerGroup.groups: 59 | consumer_group.stop = True 60 | 61 | AsyncService.services = [] 62 | AsyncActor.actors = [] 63 | AsyncProducer.producers = [] 64 | AsyncConsumer.consumers = [] 65 | AsyncConsumerGroup.groups = [] 66 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/management/resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "management": { 3 | "port": 8000, 4 | "ssl": true, 5 | "sslCertFile": "cert.pem", 6 | "sslKeyFile": "key.pem" 7 | }, 8 | "templatingEngine": "Handlebars", 9 | "services": [ 10 | { 11 | "name": "Mock for Service1", 12 | "hostname": "service1.example.com", 13 | "port": 8001, 14 | "managementRoot": "__admin", 15 | "endpoints": [ 16 | { 17 | "path": "/service1", 18 | "method": "GET", 19 | "response": "service1" 20 | }, 21 | { 22 | "path": "/service1-second/{{var}}", 23 | "method": "GET", 24 | "response": { 25 | "status": 201, 26 | "body": "service1-second: {{var}}" 27 | } 28 | }, 29 | { 30 | "path": "/service1-file", 31 | "method": "GET", 32 | "response": { 33 | "status": 200, 34 | "body": "@res/body.txt" 35 | } 36 | }, 37 | { 38 | "path": "/service1-file2", 39 | "method": "GET", 40 | "response": { 41 | "status": 200, 42 | "body": "@/res/body.txt" 43 | } 44 | }, 45 | { 46 | "path": "/service1-file3", 47 | "method": "GET", 48 | "response": { 49 | "status": 200, 50 | "body": "@../common/config.json" 51 | } 52 | }, 53 | { 54 | "path": "/service1-file-forbidden-path", 55 | "method": "GET", 56 | "response": { 57 | "status": 200, 58 | "body": "@../body/config.json" 59 | } 60 | } 61 | ] 62 | }, 63 | { 64 | "name": "Mock for Service2", 65 | "hostname": "service2.example.com", 66 | "port": 8002, 67 | "managementRoot": "__admin", 68 | "endpoints": [ 69 | { 70 | "path": "/service2", 71 | "method": "GET", 72 | "response": "service2" 73 | }, 74 | { 75 | "path": "/service2-rst", 76 | "method": "GET", 77 | "response": { 78 | "status": "RST", 79 | "body": "service2-rst" 80 | } 81 | }, 82 | { 83 | "path": "/service2-fin", 84 | "method": "GET", 85 | "response": { 86 | "status": "FIN", 87 | "body": "service2-fin" 88 | } 89 | } 90 | ] 91 | } 92 | ] 93 | } 94 | -------------------------------------------------------------------------------- /docs/Videos.md: -------------------------------------------------------------------------------- 1 | # Tutorial Videos 2 | 3 | ## Webinars 4 | 5 | ### #1: Open Source Microservice Mocking: Introducing Mockintosh 6 | 7 | 8 | 9 | 10 | 11 | --- 12 | 13 | ### #2: The Mock Actor Approach for Kafka (with Open Source Mockintosh) 14 | 15 | 16 | 17 | 18 | 19 | ## Features Overview Series 20 | 21 | ### Part #0: Introduction 22 | 23 | 24 | 25 | 26 | 27 | --- 28 | 29 | ### Part #1: Configuration Syntax 30 | 31 | 32 | 33 | 34 | 35 | --- 36 | 37 | ### Part #2: Request Matching 38 | 39 | 40 | 41 | 42 | 43 | --- 44 | 45 | ### Part #3: Response Templating 46 | 47 | 48 | 49 | 50 | 51 | --- 52 | 53 | ### Part #4: Multiple Responses & Datasets 54 | 55 | 56 | 57 | 58 | 59 | --- 60 | 61 | ### Part #5: Chaos & Resiliency Testing 62 | 63 | 64 | 65 | 66 | 67 | --- 68 | 69 | ### Part #6: Management UI 70 | 71 | 72 | 73 | 74 | 75 | --- 76 | 77 | ### Part #7: Kafka Mock Actors 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /docs/img/logo_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 30 | 32 | 56 | 62 | 68 | 73 | 78 | 79 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/body/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Handlebars", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/body-jsonpath-tpl", 10 | "method": "POST", 11 | "response": "body jsonpath matched: {{jsonPath request.json '$.key'}} {{jsonPath request.json '$.key2'}}" 12 | }, 13 | { 14 | "path": "/body-json-schema", 15 | "method": "POST", 16 | "body": { 17 | "schema": { 18 | "type": "object", 19 | "properties": { 20 | "somekey": {} 21 | }, 22 | "required": [ 23 | "somekey" 24 | ] 25 | } 26 | }, 27 | "response": "body json schema matched" 28 | }, 29 | { 30 | "path": "/body-json-schema-file", 31 | "method": "POST", 32 | "body": { 33 | "schema": "@body_schema.json" 34 | }, 35 | "response": "body json schema matched" 36 | }, 37 | { 38 | "path": "/body-json-schema-file-error", 39 | "method": "POST", 40 | "body": { 41 | "schema": "@body_schema_error.json" 42 | }, 43 | "response": "body json schema matched" 44 | }, 45 | { 46 | "path": "/body-regex", 47 | "method": "POST", 48 | "body": { 49 | "text": "{{regEx '(\\d)-required-(\\d)' 'val1' 'val2'}}" 50 | }, 51 | "response": "body regex matched: {{val1}} {{val2}}" 52 | }, 53 | { 54 | "path": "/body-urlencoded", 55 | "method": "POST", 56 | "body": { 57 | "urlencoded": { 58 | "key1": "constant", 59 | "key2": "{{var1}}", 60 | "key3": "{{regEx 'prefix-(.*)-(.*)-suffix' 'var2' 'var3'}}" 61 | } 62 | }, 63 | "response": "body urlencoded matched: {{request.body.key1}} {{var1}} {{var2}} {{var3}}" 64 | }, 65 | { 66 | "path": "/body-multipart", 67 | "method": "POST", 68 | "body": { 69 | "multipart": { 70 | "key1": "constant", 71 | "key2": "{{var1}}", 72 | "key3": "{{regEx 'prefix-(.*)-(.*)-suffix' 'var2' 'var3'}}" 73 | } 74 | }, 75 | "response": "body multipart matched: {{request.body.key1}} {{var1}} {{var2}} {{var3}}" 76 | }, 77 | { 78 | "path": "/body-text", 79 | "method": "POST", 80 | "body": { 81 | "text": "{{body_text}}" 82 | }, 83 | "response": "body text matched: {{body_text}}" 84 | } 85 | ] 86 | } 87 | ] 88 | } 89 | -------------------------------------------------------------------------------- /tests/configs/json/j2/body/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "templatingEngine": "Jinja2", 3 | "services": [ 4 | { 5 | "name": "Mock for Service1", 6 | "port": 8001, 7 | "endpoints": [ 8 | { 9 | "path": "/body-jsonpath-tpl", 10 | "method": "POST", 11 | "response": "body jsonpath matched: {{jsonPath(request.json, '$.key')}} {{jsonPath(request.json, '$.key2')}}" 12 | }, 13 | { 14 | "path": "/body-json-schema", 15 | "method": "POST", 16 | "body": { 17 | "schema": { 18 | "type": "object", 19 | "properties": { 20 | "somekey": {} 21 | }, 22 | "required": [ 23 | "somekey" 24 | ] 25 | } 26 | }, 27 | "response": "body json schema matched" 28 | }, 29 | { 30 | "path": "/body-json-schema-file", 31 | "method": "POST", 32 | "body": { 33 | "schema": "@body_schema.json" 34 | }, 35 | "response": "body json schema matched" 36 | }, 37 | { 38 | "path": "/body-json-schema-file-error", 39 | "method": "POST", 40 | "body": { 41 | "schema": "@body_schema_error.json" 42 | }, 43 | "response": "body json schema matched" 44 | }, 45 | { 46 | "path": "/body-regex", 47 | "method": "POST", 48 | "body": { 49 | "text": "{{regEx('(\\d)-required-(\\d)', 'val1', 'val2')}}" 50 | }, 51 | "response": "body regex matched: {{val1}} {{val2}}" 52 | }, 53 | { 54 | "path": "/body-urlencoded", 55 | "method": "POST", 56 | "body": { 57 | "urlencoded": { 58 | "key1": "constant", 59 | "key2": "{{var1}}", 60 | "key3": "{{regEx('prefix-(.*)-(.*)-suffix', 'var2', 'var3')}}" 61 | } 62 | }, 63 | "response": "body urlencoded matched: {{request.body.key1}} {{var1}} {{var2}} {{var3}}" 64 | }, 65 | { 66 | "path": "/body-multipart", 67 | "method": "POST", 68 | "body": { 69 | "multipart": { 70 | "key1": "constant", 71 | "key2": "{{var1}}", 72 | "key3": "{{regEx('prefix-(.*)-(.*)-suffix', 'var2', 'var3')}}" 73 | } 74 | }, 75 | "response": "body multipart matched: {{request.body.key1}} {{var1}} {{var2}} {{var3}}" 76 | }, 77 | { 78 | "path": "/body-text", 79 | "method": "POST", 80 | "body": { 81 | "text": "{{body_text}}" 82 | }, 83 | "response": "body text matched: {{body_text}}" 84 | } 85 | ] 86 | } 87 | ] 88 | } 89 | -------------------------------------------------------------------------------- /tests/configs/yaml/j2/query_string/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Jinja2 3 | services: 4 | - name: Mock for Service1 5 | port: 8001 6 | endpoints: 7 | - path: "/static-value" 8 | method: GET 9 | queryString: 10 | param1: my Value 11 | response: 12 | body: 'matched with static value: {{request.queryString.param1}}' 13 | status: 200 14 | - path: "/static-value/template-file" 15 | method: GET 16 | queryString: 17 | param1: my Value 18 | response: 19 | headers: 20 | Content-Type: "application/json; charset=UTF-8" 21 | body: "@templates/1.json.j2" 22 | status: 200 23 | - path: "/parameter" 24 | method: GET 25 | queryString: 26 | param1: "{{anyValIntoVar}}" 27 | response: 28 | body: 'matched with parameter: {{anyValIntoVar}}' 29 | status: 200 30 | - path: "/parameter/template-file" 31 | method: GET 32 | queryString: 33 | param1: "{{anyValIntoVar}}" 34 | response: 35 | headers: 36 | Content-Type: "application/json; charset=UTF-8" 37 | body: "@templates/2.json.j2" 38 | status: 200 39 | - path: "/regex-capture-group" 40 | method: GET 41 | queryString: 42 | param1: "{{regEx('prefix-(.+)-suffix', 'capturedVar')}}" 43 | response: 44 | body: 'matched with regex capture group: {{capturedVar}}' 45 | status: 200 46 | - path: "/regex-capture-group/template-file" 47 | method: GET 48 | queryString: 49 | param1: "{{regEx('prefix-(.+)-suffix', 'capturedVar')}}" 50 | response: 51 | headers: 52 | Content-Type: "application/json; charset=UTF-8" 53 | body: "@templates/3.json.j2" 54 | status: 200 55 | - path: "/alternative" 56 | method: GET 57 | queryString: 58 | param1: my Value 59 | param2: "{{anyValIntoVar}}" 60 | param3: "{{regEx('prefix-(.+)-suffix', 'capturedVar')}}" 61 | response: 62 | body: 'query string match: {{request.queryString.param1}} {{anyValIntoVar}} 63 | {{capturedVar}}' 64 | status: 201 65 | - path: "/alternative" 66 | queryString: 67 | param4: another query string 68 | response: 69 | body: 'param4 request query string: {{request.queryString.param4}}' 70 | - path: "/alternative/template-file" 71 | method: GET 72 | queryString: 73 | param1: my Value 74 | param2: "{{anyValIntoVar}}" 75 | param3: "{{regEx('prefix-(.+)-suffix', 'capturedVar')}}" 76 | response: 77 | headers: 78 | Content-Type: "application/json; charset=UTF-8" 79 | body: "@templates/4.json.j2" 80 | status: 201 81 | - path: "/alternative/template-file" 82 | queryString: 83 | param4: another query string 84 | response: 85 | headers: 86 | Content-Type: "application/json; charset=UTF-8" 87 | body: "@templates/5.json.j2" 88 | -------------------------------------------------------------------------------- /tests/configs/yaml/hbs/query_string/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | templatingEngine: Handlebars 3 | services: 4 | - name: Mock for Service1 5 | port: 8001 6 | endpoints: 7 | - path: "/static-value" 8 | method: GET 9 | queryString: 10 | param1: my Value 11 | response: 12 | body: 'matched with static value: {{request.queryString.param1}}' 13 | status: 200 14 | - path: "/static-value/template-file" 15 | method: GET 16 | queryString: 17 | param1: my Value 18 | response: 19 | headers: 20 | Content-Type: "application/json; charset=UTF-8" 21 | body: "@templates/1.json.hbs" 22 | status: 200 23 | - path: "/parameter" 24 | method: GET 25 | queryString: 26 | param1: "{{anyValIntoVar}}" 27 | response: 28 | body: 'matched with parameter: {{anyValIntoVar}}' 29 | status: 200 30 | - path: "/parameter/template-file" 31 | method: GET 32 | queryString: 33 | param1: "{{anyValIntoVar}}" 34 | response: 35 | headers: 36 | Content-Type: "application/json; charset=UTF-8" 37 | body: "@templates/2.json.hbs" 38 | status: 200 39 | - path: "/regex-capture-group" 40 | method: GET 41 | queryString: 42 | param1: "{{regEx 'prefix-(.+)-suffix' 'capturedVar'}}" 43 | response: 44 | body: 'matched with regex capture group: {{capturedVar}}' 45 | status: 200 46 | - path: "/regex-capture-group/template-file" 47 | method: GET 48 | queryString: 49 | param1: "{{regEx 'prefix-(.+)-suffix' 'capturedVar'}}" 50 | response: 51 | headers: 52 | Content-Type: "application/json; charset=UTF-8" 53 | body: "@templates/3.json.hbs" 54 | status: 200 55 | - path: "/alternative" 56 | method: GET 57 | queryString: 58 | param1: my Value 59 | param2: "{{anyValIntoVar}}" 60 | param3: "{{regEx 'prefix-(.+)-suffix' 'capturedVar'}}" 61 | response: 62 | body: 'query string match: {{request.queryString.param1}} {{anyValIntoVar}} 63 | {{capturedVar}}' 64 | status: 201 65 | - path: "/alternative" 66 | queryString: 67 | param4: another query string 68 | response: 69 | body: 'param4 request query string: {{request.queryString.param4}}' 70 | - path: "/alternative/template-file" 71 | method: GET 72 | queryString: 73 | param1: my Value 74 | param2: "{{anyValIntoVar}}" 75 | param3: "{{regEx 'prefix-(.+)-suffix' 'capturedVar'}}" 76 | response: 77 | headers: 78 | Content-Type: "application/json; charset=UTF-8" 79 | body: "@templates/4.json.hbs" 80 | status: 201 81 | - path: "/alternative/template-file" 82 | queryString: 83 | param4: another query string 84 | response: 85 | headers: 86 | Content-Type: "application/json; charset=UTF-8" 87 | body: "@templates/5.json.hbs" 88 | -------------------------------------------------------------------------------- /mockintosh/exceptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | .. module:: __init__ 6 | :synopsis: module that contains the exceptions. 7 | """ 8 | 9 | 10 | class UnrecognizedConfigFileFormat(Exception): 11 | """Raised in case of both JSON and YAML parser is failed for the configuration file. 12 | """ 13 | 14 | def __init__(self, message, filepath, yaml_error_msg): 15 | message += '\nFile path: %s' % filepath 16 | message += '\nYAML load error: %s' % yaml_error_msg 17 | # Call the base class constructor with the parameters it needs 18 | super().__init__(message) 19 | 20 | 21 | class CertificateLoadingError(Exception): 22 | """Raised in case of a certificate file is not found or in a forbidden path. 23 | """ 24 | 25 | def __init__(self, reason): 26 | super().__init__('\nCertificate loading error: %s' % reason) 27 | 28 | 29 | class RestrictedFieldError(Exception): 30 | """Raised in case of a restricted field is tried to be changed during config update. 31 | """ 32 | 33 | def __init__(self, field): 34 | super().__init__('%r field is restricted!' % field) 35 | 36 | 37 | class CommaInTagIsForbidden(Exception): 38 | """Raised in case of a comma is detected in a tag. 39 | """ 40 | 41 | def __init__(self, tag): 42 | super().__init__('Using comma is forbidden in tags: %s' % tag) 43 | 44 | 45 | class AsyncProducerListQueueMismatch(Exception): 46 | """Raised in case of values in 'queue' field differs in an async producer list. 47 | """ 48 | 49 | def __init__(self, actor_name): 50 | super().__init__('Producer actor \'%s\' has different queue values!' % actor_name) 51 | 52 | 53 | class AsyncProducerListHasNoPayloadsMatchingTags(Exception): 54 | """Raised in case of none of the payloads in an async producer list matches the given tag. 55 | """ 56 | 57 | def __init__(self, actor_name, tags): 58 | super().__init__('Producer actor \'%s\' has no payloads matching one of the tags: [%s]' % (actor_name, ', '.join(tags))) 59 | 60 | 61 | class AsyncProducerPayloadLoopEnd(Exception): 62 | """Raised in case of `multiPayloadsLooped` is `False` and the payload loop ends. 63 | """ 64 | 65 | def __init__(self, actor_name): 66 | super().__init__('Payload loop for producer actor \'%s\' is ended!' % actor_name) 67 | 68 | 69 | class AsyncProducerDatasetLoopEnd(Exception): 70 | """Raised in case of `datasetLooped` is `False` and the dataset loop ends. 71 | """ 72 | 73 | def __init__(self, actor_name): 74 | super().__init__('Dataset loop for producer actor \'%s\' is ended!' % actor_name) 75 | 76 | 77 | class InternalResourcePathCheckError(Exception): 78 | """Raised in case of a resource path check fails in `ManagementResourcesHandler`. 79 | """ 80 | 81 | def __init__(self): 82 | super().__init__(None) 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # --- GITIGNORE FOR PYTHON --- 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | .pybuild/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | mck/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # Environments 86 | .env 87 | .venv 88 | env/ 89 | venv/ 90 | ENV/ 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | .spyproject 95 | 96 | # Rope project settings 97 | .ropeproject 98 | 99 | # mkdocs documentation 100 | /site 101 | 102 | # mypy 103 | .mypy_cache/ 104 | 105 | 106 | # --- ADDITIONS --- 107 | 108 | # Editors / IDEs 109 | .vscode/ 110 | .idea/ 111 | 112 | # OS 113 | .DS_Store 114 | 115 | # Ignore the file that are created for development 116 | *dev.* 117 | 118 | # Copied Certificates 119 | tests/configs/json/hbs/management/cert.pem 120 | tests/configs/json/hbs/management/key.pem 121 | tests/configs/yaml/hbs/management/cert.pem 122 | tests/configs/yaml/hbs/management/key.pem 123 | tests/configs/yaml/hbs/core/cert.pem 124 | tests/configs/yaml/hbs/core/key.pem 125 | 126 | ## Kafka 127 | tests/configs/json/hbs/kafka/cert.pem 128 | tests/configs/json/hbs/kafka/key.pem 129 | tests/configs/yaml/hbs/kafka/cert.pem 130 | tests/configs/yaml/hbs/kafka/key.pem 131 | 132 | # Copied Images 133 | tests/configs/yaml/hbs/kafka/image.png 134 | tests/configs/json/hbs/core/imagex 135 | 136 | # Copied JSON schemas 137 | tests/configs/yaml/hbs/data_dir_override/body_schema.json 138 | tests/configs/yaml/hbs/data_dir_override/body_schema_error.json 139 | 140 | # AMQP 141 | tests/configs/yaml/hbs/amqp 142 | tests/configs/yaml/hbs/amqp/* 143 | 144 | # Redis 145 | tests/configs/yaml/hbs/redis 146 | tests/configs/yaml/hbs/redis/* 147 | 148 | # Google Cloud Pub/Sub 149 | tests/configs/yaml/hbs/gpubsub 150 | tests/configs/yaml/hbs/gpubsub/* 151 | 152 | # Amazon SQS 153 | tests/configs/yaml/hbs/amazonsqs 154 | tests/configs/yaml/hbs/amazonsqs/* 155 | 156 | # MQTT 157 | tests/configs/yaml/hbs/mqtt 158 | tests/configs/yaml/hbs/mqtt/* 159 | 160 | # Jekyll (Docs) 161 | docs/_site 162 | docs/.bundle 163 | docs/vendor 164 | /msi.cfg 165 | -------------------------------------------------------------------------------- /mockintosh/ssl/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | Bh6MSYSi5TXCt30QVSqvREkrf5S0Dw== 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /tests_integrated/subdir/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | UCsmGhuDpGhkUqUMHq6gy7mJakn+c/Y= 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /tests/configs/json/hbs/core/templates/faker.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "bothify": "{{ fake.bothify }}", 3 | "bothify_args": "{{ fake.bothify text="## ??" letters="ABCDE" }}", 4 | "hexify": "{{ fake.hexify }}", 5 | "hexify_args": "{{ fake.hexify text="MAC Address: ^^:^^:^^:^^:^^:^^" upper=true }}", 6 | "language_code": "{{ fake.language_code }}", 7 | "lexify": "{{ fake.lexify }}", 8 | "lexify_args": "{{ fake.lexify text="Random Identifier: ??????????" }}", 9 | "locale": "{{ fake.locale }}", 10 | "numerify": "{{ fake.numerify }}", 11 | "numerify_args": "{{ fake.numerify text="Intel Core i%-%%##K vs AMD Ryzen % %%##X" }}", 12 | "random_choices": "{{ fake.random_choices elements=( array 'a' 'b' 'c' 'd' 'e' ) }}", 13 | "random_digit": {{ fake.random_digit }}, 14 | "random_digit_not_null": {{ fake.random_digit_not_null }}, 15 | "random_digit_not_null_or_empty": "{{ fake.random_digit_not_null_or_empty }}", 16 | "random_digit_or_empty": "{{ fake.random_digit_or_empty }}", 17 | "random_element": "{{ fake.random_element elements=( array 'a' 'b' 'c' 'd' 'e' ) }}", 18 | "random_elements": {{ tojson ( fake.random_elements elements=( array 'a' 'b' 'c' 'd' 'e' ) length=3 unique=True ) }}, 19 | "random_int": {{ fake.random_int }}, 20 | "random_int_args": {{ fake.random_int min=10000 max=50000 step=500 }}, 21 | "random_letter": "{{ fake.random_letter }}", 22 | "random_letters": {{ tojson ( fake.random_letters ) }}, 23 | "random_letters_args": {{ tojson ( fake.random_letters length=32 ) }}, 24 | "random_lowercase_letter": "{{ fake.random_lowercase_letter }}", 25 | "random_number": {{ fake.random_number }}, 26 | "random_number_args": {{ fake.random_number digits=null fix_len=true }}, 27 | "random_sample": {{ tojson ( fake.random_sample elements=( array 'a' 'b' 'c' 'd' 'e' ) ) }}, 28 | "random_uppercase_letter": "{{ fake.random_uppercase_letter }}", 29 | "randomize_nb_elements": "{{ fake.randomize_nb_elements number=79 le=true ge=true min=80 }}", 30 | "first_name": "{{ fake.first_name }}", 31 | "first_name_female": "{{ fake.first_name_female }}", 32 | "first_name_male": "{{ fake.first_name_male }}", 33 | "first_name_nonbinary": "{{ fake.first_name_nonbinary }}", 34 | "language_name": "{{ fake.language_name }}", 35 | "last_name": "{{ fake.last_name }}", 36 | "last_name_female": "{{ fake.last_name_female }}", 37 | "last_name_male": "{{ fake.last_name_male }}", 38 | "last_name_nonbinary": "{{ fake.last_name_nonbinary }}", 39 | "name": "{{ fake.name }}", 40 | "name_female": "{{ fake.name_female }}", 41 | "name_male": "{{ fake.name_male }}", 42 | "name_nonbinary": "{{ fake.name_nonbinary }}", 43 | "prefix": "{{ fake.prefix }}", 44 | "prefix_female": "{{ fake.prefix_female }}", 45 | "prefix_male": "{{ fake.prefix_male }}", 46 | "prefix_nonbinary": "{{ fake.prefix_nonbinary }}", 47 | "suffix": "{{ fake.suffix }}", 48 | "suffix_female": "{{ fake.suffix_female }}", 49 | "suffix_male": "{{ fake.suffix_male }}", 50 | "suffix_nonbinary": "{{ fake.suffix_nonbinary }}", 51 | "address": "{{ replace ( fake.address ) old='\n' new='\\n' }}", 52 | "city": "{{ fake.city }}", 53 | "city_suffix": "{{ fake.city_suffix }}", 54 | "country": "{{ fake.country }}", 55 | "country_code": "{{ fake.country_code }}", 56 | "postcode": "{{ fake.postcode }}", 57 | "street_address": "{{ fake.street_address }}", 58 | "street_name": "{{ fake.street_name }}", 59 | "street_suffix": "{{ fake.street_suffix }}", 60 | "license_plate": "{{ fake.license_plate }}" 61 | } 62 | -------------------------------------------------------------------------------- /mockintosh/res/sample.yml: -------------------------------------------------------------------------------- 1 | services: # config requires at least one service to be configured 2 | - name: Demo Service # optional, used for visual reference 3 | port: 8888 # required option, on which port to serve HTTP traffic 4 | # ssl: true # uncomment to enable SSL, see also sslCertFile and sslKeyFile options 5 | # fallbackTo: https://httpbin.org # all unhandled requests will be forwarded to that address 6 | 7 | endpoints: 8 | # that's enough to serve empty response for curl -v http://localhost:8888/ 9 | - path: / 10 | 11 | # test with: curl -v http://localhost:8888/api/myURLParamValue123/action 12 | - path: /api/{{param}}/action # Handlebars expressions can be part of request URL 13 | response: "request URL contained {{param}}" # and can be referenced in response 14 | 15 | # the below example only works for complex request, tested like below: 16 | # curl -v "http://localhost:8888/someMoreFields?qName1=qValue&qName2=12345" \ 17 | # -X POST -H"X-Required-Header: someval" --data "payload" 18 | - path: /someMoreFields 19 | comment: endpoint comments are just for visual help in large configs 20 | method: POST 21 | queryString: 22 | qName1: qValue # will only match if query string parameter exists 23 | qName2: "{{regEx '\\d+'}}" # will require numeric value 24 | headers: 25 | x-required-header: someval # will cause only requests with specific header to work 26 | body: 27 | text: "{{regEx '.+'}}" # will require non-empty POST body 28 | 29 | response: 30 | status: 202 31 | body: "It worked!" 32 | headers: 33 | x-response-header: "{{random.uuid4}}" # a selection of random/dynamic functions is available 34 | x-query-string-value: "{{request.queryString.qName2}}" # request parts can be referenced in response 35 | 36 | # demo for variety of separately configured responses 37 | - path: /varyingResponses 38 | response: 39 | - "The response" 40 | - "can be different" 41 | - "each time." 42 | - body: "Drastically different!" 43 | headers: 44 | content-type: application/octet-stream 45 | status: 201 46 | 47 | - path: /withPerfProfile 48 | performanceProfile: allPossibleOptions # enables certain performance/chaos profile, see section below 49 | response: "Pay attention to status code" 50 | 51 | 52 | globals: # optional section 53 | performanceProfile: justSlow # for all endpoints, apply this performance profile 54 | headers: # for all endpoints, add these response headers 55 | content-type: text/plain # can be a single place to set application/json as default 56 | 57 | 58 | management: 59 | port: 9999 # enable the management API+UI on certain port, open in browser http://localhost:9999 to see it 60 | # ssl: true # same behavior as service's option 61 | 62 | performanceProfiles: 63 | justSlow: 64 | ratio: 1.0 # work 100% of time 65 | delay: 0.5 # introduce 0.5s delay 66 | 67 | allPossibleOptions: # will cause 40% of requests to fail with various reasons 68 | ratio: 0.5 # only affect half of the traffic 69 | delay: 2.5 # considerable delay 70 | faults: 71 | PASS: 0.2 # 20% of times, cause no failure 72 | RST: 0.2 # simulate connection reset 73 | FIN: 0.2 # simulate sudden connection shutdown 74 | 400: 0.2 75 | 500: 0.2 76 | -------------------------------------------------------------------------------- /tests/configs/stats_kafka.json: -------------------------------------------------------------------------------- 1 | { 2 | "global": { 3 | "request_counter": 62, 4 | "avg_resp_time": 0.0, 5 | "status_code_distribution": { 6 | "202": 36, 7 | "200": 26 8 | } 9 | }, 10 | "services": [ 11 | { 12 | "hint": "Asynchronous Mocks", 13 | "request_counter": 62, 14 | "avg_resp_time": 0.0, 15 | "status_code_distribution": { 16 | "202": 36, 17 | "200": 26 18 | }, 19 | "endpoints": [ 20 | { 21 | "hint": "PUT topic1 - 0", 22 | "request_counter": 1, 23 | "avg_resp_time": 0.0, 24 | "status_code_distribution": { 25 | "202": 1 26 | } 27 | }, 28 | { 29 | "hint": "GET topic2 - 1", 30 | "request_counter": 1, 31 | "avg_resp_time": 0.0, 32 | "status_code_distribution": { 33 | "200": 1 34 | } 35 | }, 36 | { 37 | "hint": "PUT topic3 - 2", 38 | "request_counter": 23, 39 | "avg_resp_time": 0.0, 40 | "status_code_distribution": { 41 | "202": 23 42 | } 43 | }, 44 | { 45 | "hint": "GET topic3 - 3", 46 | "request_counter": 23, 47 | "avg_resp_time": 0.0, 48 | "status_code_distribution": { 49 | "200": 23 50 | } 51 | }, 52 | { 53 | "hint": "GET topic4 - 4", 54 | "request_counter": 1, 55 | "avg_resp_time": 0.0, 56 | "status_code_distribution": { 57 | "200": 1 58 | } 59 | }, 60 | { 61 | "hint": "PUT topic5 - 4", 62 | "request_counter": 1, 63 | "avg_resp_time": 0.0, 64 | "status_code_distribution": { 65 | "202": 1 66 | } 67 | }, 68 | { 69 | "hint": "PUT topic6 - 5", 70 | "request_counter": 1, 71 | "avg_resp_time": 0.0, 72 | "status_code_distribution": { 73 | "202": 1 74 | } 75 | }, 76 | { 77 | "hint": "PUT topic7 - 6", 78 | "request_counter": 6, 79 | "avg_resp_time": 0.0, 80 | "status_code_distribution": { 81 | "202": 6 82 | } 83 | }, 84 | { 85 | "hint": "PUT topic8 - 7", 86 | "request_counter": 2, 87 | "avg_resp_time": 0.0, 88 | "status_code_distribution": { 89 | "202": 2 90 | } 91 | }, 92 | { 93 | "hint": "GET topic9 - 8", 94 | "request_counter": 0, 95 | "avg_resp_time": 0, 96 | "status_code_distribution": {} 97 | }, 98 | { 99 | "hint": "PUT templated-producer - 9", 100 | "request_counter": 2, 101 | "avg_resp_time": 0.0, 102 | "status_code_distribution": { 103 | "202": 2 104 | } 105 | }, 106 | { 107 | "hint": "GET topic10 - 10", 108 | "request_counter": 1, 109 | "avg_resp_time": 0.0, 110 | "status_code_distribution": { 111 | "200": 1 112 | } 113 | } 114 | ] 115 | }, 116 | { 117 | "hint": "http://service1.example.com:8001 - Mock for Service1", 118 | "request_counter": 0, 119 | "avg_resp_time": 0, 120 | "status_code_distribution": {}, 121 | "endpoints": [] 122 | } 123 | ] 124 | } 125 | -------------------------------------------------------------------------------- /tests/configs/json/j2/core/templates/faker.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "bothify": "{{ fake.bothify() }}", 3 | "bothify_args": "{{ fake.bothify(text="## ??", letters="ABCDE") }}", 4 | "hexify": "{{ fake.hexify() }}", 5 | "hexify_args": "{{ fake.hexify(text="MAC Address: ^^:^^:^^:^^:^^:^^", upper=True) }}", 6 | "language_code": "{{ fake.language_code() }}", 7 | "lexify": "{{ fake.lexify() }}", 8 | "lexify_args": "{{ fake.lexify(text="Random Identifier: ??????????") }}", 9 | "locale": "{{ fake.locale() }}", 10 | "numerify": "{{ fake.numerify() }}", 11 | "numerify_args": "{{ fake.numerify(text="Intel Core i%-%%##K vs AMD Ryzen % %%##X") }}", 12 | "random_choices": {{ fake.random_choices(elements=['a', 'b', 'c', 'd', 'e']) | tojson }}, 13 | "random_digit": {{ fake.random_digit() }}, 14 | "random_digit_not_null": {{ fake.random_digit_not_null() }}, 15 | "random_digit_not_null_or_empty": "{{ fake.random_digit_not_null_or_empty() }}", 16 | "random_digit_or_empty": "{{ fake.random_digit_or_empty() }}", 17 | "random_element": "{{ fake.random_element(elements=['a', 'b', 'c', 'd', 'e']) }}", 18 | "random_elements": {{ fake.random_elements(elements=['a', 'b', 'c', 'd', 'e'], length=3, unique=True) | tojson }}, 19 | "random_int": {{ fake.random_int() }}, 20 | "random_int_args": {{ fake.random_int(min=10000, max=50000, step=500) }}, 21 | "random_letter": "{{ fake.random_letter() }}", 22 | "random_letters": {{ fake.random_letters() | tojson }}, 23 | "random_letters_args": {{ fake.random_letters(length=32) | tojson }}, 24 | "random_lowercase_letter": "{{ fake.random_lowercase_letter() }}", 25 | "random_number": {{ fake.random_number() }}, 26 | "random_number_args": {{ fake.random_number(digits=None, fix_len=True) }}, 27 | "random_sample": {{ fake.random_sample(elements=['a', 'b', 'c', 'd', 'e']) | tojson }}, 28 | "random_uppercase_letter": "{{ fake.random_uppercase_letter() }}", 29 | "randomize_nb_elements": "{{ fake.randomize_nb_elements(number=79, le=true, ge=true, min=80) }}", 30 | "first_name": "{{ fake.first_name() }}", 31 | "first_name_female": "{{ fake.first_name_female() }}", 32 | "first_name_male": "{{ fake.first_name_male() }}", 33 | "first_name_nonbinary": "{{ fake.first_name_nonbinary() }}", 34 | "language_name": "{{ fake.language_name() }}", 35 | "last_name": "{{ fake.last_name() }}", 36 | "last_name_female": "{{ fake.last_name_female() }}", 37 | "last_name_male": "{{ fake.last_name_male() }}", 38 | "last_name_nonbinary": "{{ fake.last_name_nonbinary() }}", 39 | "name": "{{ fake.name() }}", 40 | "name_female": "{{ fake.name_female() }}", 41 | "name_male": "{{ fake.name_male() }}", 42 | "name_nonbinary": "{{ fake.name_nonbinary() }}", 43 | "prefix": "{{ fake.prefix() }}", 44 | "prefix_female": "{{ fake.prefix_female() }}", 45 | "prefix_male": "{{ fake.prefix_male() }}", 46 | "prefix_nonbinary": "{{ fake.prefix_nonbinary() }}", 47 | "suffix": "{{ fake.suffix() }}", 48 | "suffix_female": "{{ fake.suffix_female() }}", 49 | "suffix_male": "{{ fake.suffix_male() }}", 50 | "suffix_nonbinary": "{{ fake.suffix_nonbinary() }}", 51 | "address": "{{ fake.address() | replace('\n','\\n') }}", 52 | "city": "{{ fake.city() }}", 53 | "city_suffix": "{{ fake.city_suffix() }}", 54 | "country": "{{ fake.country() }}", 55 | "country_code": "{{ fake.country_code() }}", 56 | "postcode": "{{ fake.postcode() }}", 57 | "street_address": "{{ fake.street_address() }}", 58 | "street_name": "{{ fake.street_name() }}", 59 | "street_suffix": "{{ fake.street_suffix() }}", 60 | "license_plate": "{{ fake.license_plate() }}" 61 | } 62 | -------------------------------------------------------------------------------- /tests/test_exceptions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | .. module:: __init__ 6 | :synopsis: Contains classes that tests the exceptions thrown by the mock server. 7 | """ 8 | 9 | import sys 10 | import pytest 11 | from jsonschema.exceptions import ValidationError 12 | 13 | from mockintosh import get_schema 14 | from mockintosh.definition import Definition 15 | from mockintosh.services.http import ( 16 | HttpService 17 | ) 18 | from mockintosh.exceptions import ( 19 | UnrecognizedConfigFileFormat, 20 | CertificateLoadingError, 21 | CommaInTagIsForbidden 22 | ) 23 | from mockintosh.servers import HttpServer, TornadoImpl 24 | from mockintosh.helpers import _nostderr 25 | from mockintosh.templating import RenderingQueue 26 | from utilities import get_config_path 27 | 28 | schema = get_schema() 29 | 30 | 31 | class TestExceptions: 32 | 33 | def teardown_method(self): 34 | HttpService.services = [] 35 | 36 | def test_file_not_found_error(self): 37 | config = 'configs/not_existing_file' 38 | queue = RenderingQueue() 39 | with pytest.raises(FileNotFoundError, match=r"No such file or directory:"): 40 | Definition(get_config_path(config), schema, queue) 41 | 42 | @pytest.mark.parametrize(('config'), [ 43 | 'configs/empty.json', 44 | 'configs/empty.yaml' 45 | ]) 46 | def test_json_schema_validation_error(self, config): 47 | queue = RenderingQueue() 48 | with pytest.raises(ValidationError, match=r".*"): 49 | Definition(get_config_path(config), schema, queue) 50 | 51 | def test_unrecognized_config_file_format_error(self): 52 | config = 'configs/invalid' 53 | queue = RenderingQueue() 54 | with pytest.raises( 55 | UnrecognizedConfigFileFormat, 56 | match=r"Configuration file is neither a JSON file nor a YAML file!" 57 | ): 58 | Definition(get_config_path(config), schema, queue) 59 | 60 | def test_certificate_loading_error_1(self): 61 | config = 'configs/missing_ssl_cert_file.json' 62 | queue = RenderingQueue() 63 | with pytest.raises( 64 | CertificateLoadingError, 65 | match=r"Certificate loading error: File not found on path `missing_dir/cert.pem`" 66 | ): 67 | definition = Definition(get_config_path(config), schema, queue) 68 | HttpServer( 69 | definition, 70 | TornadoImpl() 71 | ) 72 | 73 | def test_certificate_loading_error_2(self): 74 | config = 'configs/inaccessible_ssl_cert_file.json' 75 | queue = RenderingQueue() 76 | with pytest.raises( 77 | CertificateLoadingError, 78 | match=r"Certificate loading error: Path `../../tests_integrated/subdir/cert.pem` is inaccessible!" 79 | ): 80 | definition = Definition(get_config_path(config), schema, queue) 81 | HttpServer( 82 | definition, 83 | TornadoImpl() 84 | ) 85 | 86 | def test_nostderr(self): 87 | with _nostderr(): 88 | sys.stderr.write('don\'t print this') 89 | 90 | def test_comma_in_tag_is_forbidden(self): 91 | config = 'configs/json/hbs/management/multiresponse_comma_tag.json' 92 | queue = RenderingQueue() 93 | with pytest.raises( 94 | CommaInTagIsForbidden, 95 | match=r"Using comma is forbidden in tags: firs,t" 96 | ): 97 | Definition(get_config_path(config), schema, queue) 98 | --------------------------------------------------------------------------------