Skip to content

Commit

Permalink
test fix and extension
Browse files Browse the repository at this point in the history
  • Loading branch information
KissPeter committed Feb 8, 2020
1 parent 217ac1d commit ead9cfd
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 25 deletions.
10 changes: 4 additions & 6 deletions apifuzzer/fuzzer_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ def format_pycurl_query_param(self, url, query_params):
self.logger.exception(e)
self.logger.debug('{} Problem adding ({}) as query param. Issue was:{}'.format(iteration, k, e))
if len(v):
self.logger.debug('Removing last character from query param, current length: %s', len(v))
v = v[:-1]
self.logger.debug('Removing first character from query param, current length: %s', len(v))
v = v[1:]
else:
self.logger.info('The whole query param was removed, using empty string instead')
_tmp_query_params[_query_param_name] = ""
Expand Down Expand Up @@ -281,14 +281,12 @@ def transmit(self, **kwargs):
_curl.setopt(pycurl.POSTFIELDS, urllib.parse.urlencode(kwargs.get('data', {})))
_curl.setopt(pycurl.HEADERFUNCTION, resp_buff_hdrs.write)
_curl.setopt(pycurl.WRITEFUNCTION, resp_buff_body.write)
for retries in reversed(range(3)):
for retries in reversed(range(0, 3)):
try:
_curl.perform()
except Exception as e:
# pycurl.error usually
self.logger.error('{}: {}'.format(e.__class__.__name__, e))
if retries:
self.logger.error('Retrying... ({})'.format(retries))
self.logger.error('Retrying... ({}) because {}'.format(retries, e))
else:
raise e
_return = Return()
Expand Down
10 changes: 4 additions & 6 deletions fuzzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@

import argparse
import json
import sys

from logging import _nameToLevel as levelNames
import signal
import sys
import tempfile

from logging import _nameToLevel as levelNames

from kitty.interfaces import WebInterface
from kitty.model import GraphModel

from apifuzzer.swagger_template_generator import SwaggerTemplateGenerator
from apifuzzer.fuzzer_target import FuzzerTarget
from apifuzzer.server_fuzzer import OpenApiServerFuzzer
from apifuzzer.swagger_template_generator import SwaggerTemplateGenerator
from apifuzzer.utils import set_logger


Expand Down Expand Up @@ -119,7 +117,7 @@ def json_data(arg_string):
required=False,
help='Use basic output for logging (useful if running in jenkins). Example --basic_output=True',
dest='basic_output',
default=False) # Useful if running in jenkins.
default=False)
parser.add_argument('--headers',
type=json_data,
required=False,
Expand Down
70 changes: 58 additions & 12 deletions test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def fuzz(self, api_resources):
alternate_url=self.test_app_url,
test_result_dst=None,
log_level='Debug',
basic_output=False,
auth_headers={}
)
prog.prepare()
Expand All @@ -64,25 +65,70 @@ def get_last_report_file(self):
with open("{}/{}".format(self.report_dir, self.report_files[0]), mode='r', encoding='utf-8') as f:
return json.loads(f.read())

def test_integer_status_code(self):
api_endpoint_to_test = self.swagger['paths']['/exception/{integer_id}']
print('API to test: {}'.format(api_endpoint_to_test))
def fuzz_and_get_last_call(self, api_path, api_def):
self.swagger.pop('paths')
self.swagger['paths'] = {}
self.swagger['paths']['/exception/{integer_id}'] = api_endpoint_to_test
self.swagger['paths'][api_path] = api_def
self.fuzz(self.swagger)
last_call = self.query_last_call()
# last_call field:
# "req_path": "/exception/\u001f/\u001c\u007f\u0000N@",
last_value_sent = last_call['req_path'].replace('/exception/', '')
assert not isinstance(last_value_sent, int), last_value_sent
assert last_call['resp_status'] == 500, last_call['resp_status'] + "Received"
# report file test
required_report_fields = ['status', 'sub_reports', 'name', 'request_body', 'request_headers', 'state',
'request_method', 'reason', 'request_url', 'response', 'test_number']
assert last_call['resp_status'] == 500, '{} received, full response: {}'.format(last_call['resp_status'],
last_call)
print('api_path: {}, api_def: {} \nlast_call: {}'.format(api_path, api_def, last_call))
return last_call

def repot_basic_check(self):
required_report_fields = ['status', 'sub_reports', 'name', 'request_headers', 'state', 'request_method',
'reason', 'request_url', 'response', 'test_number']
last_report = self.get_last_report_file()
assert_msg = json.dumps(last_report, sort_keys=True, indent=2)
for field in required_report_fields:
assert field in last_report.keys(), assert_msg
if last_report.get('parsed_status_code') is not None:
assert last_report['parsed_status_code'] == 500, assert_msg

def test_single_path_parameter(self):
test_url = '/path_param'
api_path = "/".join([test_url, '{integer_id}'])
api_def = {
"get": {
"parameters": [
{
"name": "integer_id",
"in": "path",
"required": True,
"type": "number",
"format": "double"
}

]
}
}
last_call = self.fuzz_and_get_last_call(api_path, api_def)
# last_call test field sample:
# "req_path": "/path_param/\u001f/\u001c\u007f\u0000N@",
last_value_sent = last_call['req_path'].replace(test_url, '')
assert not isinstance(last_value_sent, int), last_value_sent
self.repot_basic_check()

def test_single_query_string(self):
api_path = '/query'
api_def = {
"get": {
"parameters": [
{
"name": "integer_id",
"in": "query",
"required": True,
"type": "number",
"format": "double"
}

]
}
}
# last_call test field sample:
# 'http://127.0.0.1:5000/query?integer_id=%10'
last_call = self.fuzz_and_get_last_call(api_path, api_def)
_, last_value_sent = last_call['req_url'].split("=")
assert not isinstance(last_value_sent, int), last_call['req_url']
self.repot_basic_check()
8 changes: 7 additions & 1 deletion test/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,18 @@ def extract(d):
last_request_data = LastRequestData()


@app.route('/exception/<integer_id>', methods=['GET'])
@app.route('/path_param/<integer_id>', methods=['GET'])
@catch_custom_exception
def transform(integer_id):
return 'ID: {}'.format(int(integer_id))


@app.route('/query')
@catch_custom_exception
def data():
return 'ID: {}'.format(int(request.args.get('integer_id')))


@app.route('/last_call', methods=['GET'])
def last_call():
_return = last_request_data.get_data()
Expand Down

0 comments on commit ead9cfd

Please sign in to comment.