Added features for append/error_malformed, delete/list_order, insert/error_malformed and insert/list_order. Updated append/error_unprocessable and resolve conflicts in list/success.

This commit is contained in:
Héctor Hurtado
2019-08-20 10:36:24 +02:00
14 changed files with 221 additions and 144 deletions
+14 -5
View File
@@ -306,13 +306,16 @@ def delete_route(app):
########################################################################
async def run_init_script(app, scripts):
async def run_init_script(app, scripts, interactive):
"""
Run the init script if given, then wait for the shell to finish.
"""
if not scripts:
# No script given
if not interactive:
return
else:
cmd = "/bin/bash"
else:
def build_filenames():
@@ -320,7 +323,10 @@ async def run_init_script(app, scripts):
yield shlex.quote(filename)
yield "<(echo)"
filenames = " ".join(build_filenames())
if interactive:
cmd = f"/bin/bash --init-file <(cat {filenames})"
else:
cmd = f"/bin/bash <(cat {filenames})"
shell_task = await asyncio.create_subprocess_shell(
cmd,
@@ -330,16 +336,17 @@ async def run_init_script(app, scripts):
})
await shell_task.wait()
if interactive:
await app.cleanup()
os._exit(shell_task.returncode)
async def start_background_tasks(app):
global loop
app["debug_tasks"] = loop.create_task(run_init_script(app, app["scripts"]))
app["debug_tasks"] = loop.create_task(run_init_script(app, app["scripts"], app["interactive"]))
async def start_kapow_server(bind, scripts, certfile=None, keyfile=None):
async def start_kapow_server(bind, scripts, certfile=None, interactive=False, keyfile=None):
user_app = web.Application(client_max_size=1024**3)
user_runner = web.AppRunner(user_app)
await user_runner.setup()
@@ -366,6 +373,7 @@ async def start_kapow_server(bind, scripts, certfile=None, keyfile=None):
web.put('/handlers/{id}/{field:.*}', set_field),
])
control_app["scripts"] = scripts
control_app["interactive"] = interactive
control_app.on_startup.append(start_background_tasks)
control_runner = web.AppRunner(control_app)
@@ -391,12 +399,13 @@ def kapow(ctx):
@click.option("--certfile", default=None)
@click.option("--keyfile", default=None)
@click.option("--bind", default="0.0.0.0:8080")
@click.option("-i", "--interactive", is_flag=True)
@click.argument("scripts", nargs=-1)
def server(certfile, keyfile, bind, scripts):
def server(certfile, keyfile, bind, interactive, scripts):
if bool(certfile) ^ bool(keyfile):
print("For SSL both 'certfile' and 'keyfile' should be provided.")
sys.exit(1)
loop.run_until_complete(start_kapow_server(bind, scripts, certfile, keyfile))
loop.run_until_complete(start_kapow_server(bind, scripts, certfile, interactive, keyfile))
loop.run_forever()
@kapow.group()
+3 -3
View File
@@ -12,8 +12,8 @@
"Scenario": 2,
"Background": 2,
"given": 4,
"when": 6,
"then": 6,
"when": 4,
"then": 4,
"and": 6,
"but": 6,
"example": 2,
@@ -24,7 +24,7 @@
"new-line-at-eof": ["on", "yes"],
"no-multiple-empty-lines": "on",
"no-scenario-outlines-without-examples": "on",
"name-length": ["on", {"Feature": 50}],
"name-length": ["on", {"Feature": 80}],
"no-restricted-tags": ["on", {"tags": ["@watch", "@wip"]}],
"use-and": "on",
"no-duplicate-tags": "on",
+3 -1
View File
@@ -1,3 +1,5 @@
test:
gherkin-lint
pipenv run behave --no-capture
pipenv run behave --no-capture --stop
catalog:
pipenv run behave --steps-catalog
@@ -12,8 +12,8 @@ Feature: Kapow! server reject responses with semantic errors.
When I append the route:
| entrypoint | command |
| /bin/sh -c | ls -la / \| response /body |
Then I get unprocessable entity as response code
And I get "Missing Mandatory Field" as response phrase
Then I get 422 as response code
And I get "Missing Mandatory Field" as response reason phrase
And I get the following entity as response body:
| missing_mandatory_fields |
| "url_pattern", "method" |
@@ -26,8 +26,8 @@ Feature: Kapow! server reject responses with semantic errors.
When I append the route:
| method | url_pattern | entrypoint | command |
| GET | +123-- | /bin/sh -c | ls -la / \| response /body |
Then I get unprocessable entity as response code
And I get "Invalid Route Spec" as response phrase
Then I get 422 as response code
And I get "Invalid Route Spec" as response reason phrase
And I get an empty response body
Scenario: Error because of wrong method value.
@@ -38,6 +38,6 @@ Feature: Kapow! server reject responses with semantic errors.
When I append the route:
| method | url_pattern | entrypoint | command |
| AVECES | +123-- | /bin/sh -c | ls -la / \| response /body |
Then I get unprocessable entity as response code
And I get "Invalid Data Type" as response phrase
Then I get 422 as response code
And I get "Invalid Data Type" as response reason phrase
And I get an empty response body
@@ -11,8 +11,8 @@ Feature: Append new routes in Kapow! server.
When I append the route:
| method | url_pattern | entrypoint | command |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body |
Then I get created as response code
And I get "Created" as response phrase
Then I get 201 as response code
And I get "Created" as response reason phrase
And I get the following entity as response body:
| method | url_pattern | entrypoint | command | index | id |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * |
@@ -28,8 +28,8 @@ Feature: Append new routes in Kapow! server.
When I append the route:
| method | url_pattern | entrypoint | command |
| GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body |
Then I get created as response code
And I get "Created" as response phrase
Then I get 201 as response code
And I get "Created" as response reason phrase
And I get the following entity as response body:
| method | url_pattern | entrypoint | command | index | id |
| GET | /listEtcDir | /bin/sh -c | ls -la /etc \| response /body | 2 | * |
@@ -8,6 +8,6 @@ Feature: Fail to delete a route in Kapow! server.
Given I have a just started Kapow! server
When I delete the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"
Then I get not found as response code
And I get "Not Found" as response phrase
Then I get 404 as response code
And I get "Not Found" as response reason phrase
And I get an empty response body
@@ -8,6 +8,6 @@ Feature: Delete routes in Kapow! server.
Given I have a running Kapow! server
And It has a route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"
When I delete the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"
Then I get ok as response code
And I get "OK" as response phrase
Then I get 200 as response code
And I get "OK" as response reason phrase
And I get an empty response body
@@ -11,8 +11,8 @@ Feature: Kapow! server reject insert responses with semantic errors.
When I insert the route:
| entrypoint | command |
| /bin/sh -c | ls -la / \| response /body |
Then I get unprocessable entity as response code
And I get "Missing Mandatory Field" as response phrase
Then I get 422 as response code
And I get "Missing Mandatory Field" as response reason phrase
And I get the following entity as response body:
| missing_mandatory_fields |
| "url_pattern", "method" |
@@ -25,8 +25,8 @@ Feature: Kapow! server reject insert responses with semantic errors.
When I insert the route:
| method | url_pattern | entrypoint | command | index |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 |
Then I get unprocessable entity as response code
And I get "Invalid Route Spec" as response phrase
Then I get 422 as response code
And I get "Invalid Route Spec" as response reason phrase
And I get an empty response body
Scenario: Error because of wrong method value.
@@ -37,6 +37,6 @@ Feature: Kapow! server reject insert responses with semantic errors.
When I insert the route:
| method | url_pattern | entrypoint | command | index |
| AVECES | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 |
Then I get unprocessable entity as response code
And I get "Invalid Data Type" as response phrase
Then I get 422 as response code
And I get "Invalid Data Type" as response reason phrase
And I get an empty response body
@@ -16,8 +16,8 @@ Feature: Insert new routes in Kapow! server.
When I insert the route:
| method | url_pattern | entrypoint | command | index |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 |
Then I get ok as response code
And I get "OK" as response phrase
Then I get 200 as response code
And I get "OK" as response reason phrase
And I get the following entity as response body:
| method | url_pattern | entrypoint | command | index | id |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 0 | * |
@@ -30,8 +30,8 @@ Feature: Insert new routes in Kapow! server.
When I insert the route:
| method | url_pattern | entrypoint | command | index |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 1 |
Then I get ok as response code
And I get "OK" as response phrase
Then I get 200 as response code
And I get "OK" as response reason phrase
And I get the following entity as response body:
| method | url_pattern | entrypoint | command | index | id |
| GET | /listRootDir | /bin/sh -c | ls -la / \| response /body | 1 | * |
+69 -3
View File
@@ -1,8 +1,11 @@
import subprocess
from time import sleep
import shlex
import socket
from contextlib import suppress
import requests
from environconfig import EnvironConfig, StringVar
from environconfig import EnvironConfig, StringVar, IntVar
class Env(EnvironConfig):
@@ -15,16 +18,31 @@ class Env(EnvironConfig):
#: Where the Data API is
KAPOW_DATAAPI_URL = StringVar(default="http://localhost:8080")
KAPOW_BOOT_TIMEOUT = IntVar(default=10)
@given('I have a just started Kapow! server')
@given('I have a running Kapow! server')
def step_impl(context):
context.server = subprocess.Popen(
Env.KAPOW_SERVER_CMD,
shlex.split(Env.KAPOW_SERVER_CMD),
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
shell=True)
shell=False)
# Check process is running with reachable APIs
open_ports = False
for _ in range(Env.KAPOW_BOOT_TIMEOUT):
is_running = context.server.poll() is None
assert is_running, "Server is not running!"
with suppress(requests.exceptions.ConnectionError):
open_ports = (
requests.head(Env.KAPOW_CONTROLAPI_URL, timeout=1).status_code
and requests.head(Env.KAPOW_DATAAPI_URL, timeout=1).status_code)
if open_ports:
break
sleep(1)
assert open_ports, "API is unreachable after KAPOW_BOOT_TIMEOUT"
@when('I request a routes listing')
@@ -69,3 +87,51 @@ def step_impl(context):
assert header in entry, f"Response does not contain the key {header}"
if row[header] != '*':
assert entry[header] == row[header], f"Values mismatch"
#
#
#
@when('I append the route')
def step_impl(context):
if not hasattr(context, 'table'):
raise RuntimeError("A table must be set for this step.")
for row in context.table:
response = requests.post(f"{Env.KAPOW_CONTROLAPI_URL}/routes",
json={h: row[h] for h in row.headings})
response.raise_for_status()
@then('I get {code} as response code')
def step_impl(context, code):
raise NotImplementedError('STEP: Then I get unprocessable entity as response code')
@then('I get "{reason}" as response reason phrase')
def step_impl(context, reason):
raise NotImplementedError('STEP: Then I get "Missing Mandatory Field" as response phrase')
@then('I get the following entity as response body')
def step_impl(context):
raise NotImplementedError('STEP: Then I get the following entity as response body')
@then('I get an empty response body')
def step_impl(context):
raise NotImplementedError('STEP: Then I get an empty response body')
@when('I delete the route with id "{id}"')
def step_impl(context, id):
raise NotImplementedError('STEP: When I delete the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"')
@given('It has a route with id "{id}"')
def step_impl(context, id):
raise NotImplementedError('STEP: Given It has a route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx"')
@when('I insert the route')
def step_impl(context):
raise NotImplementedError('STEP: When I insert the route')