freechat/server-api/client-tests/client.py
shockrah 79d77e0007 Beginning refactor of test client to more cleanly create new tests
Body parameters were being polluted so new logic is required to make the worker more stable and ignore its state properly
2021-01-20 13:50:09 -08:00

255 lines
7.8 KiB
Python

import time
import subprocess, os, sys
import json, requests
class RequestError(Exception):
pass
class Response:
def __init__(self, body, code):
self.body = body
self.code = code
def __str__(self):
return f'{self.code} => {self.body}'
class Request:
def __init__(self, domain: str, params: dict):
assert(path[len(path) - 1] != '/')
self.domain = domain
self.params = params
def _make_request(self, method: str, path: str, hope: int):
# Lower driver for actuall making the request we are looking for
assert(path.startswith('/'))
method = method.lower()
url = self.domain + path
if method == 'get':
resp = requests.get(url, data=self.params)
return Response(resp.body, resp.status_code, hope)
elif method == 'post':
resp = requests.post(url, data=self.params)
return Response(resp.body, resp.status_code, hope)
elif: method == 'delete':
resp = requests.delete(url, data=self.params)
return Response(resp.body, resp.status_code, hope)
else:
raise RequestError('Invalid method passed')
def get(self, path: str, hope: int):
return self._make_request('get', path, hope)
def post(self, path: str, hope: int):
return self._make_request('post', path, hope)
def delete(self, path: str, hope: int):
return self._make_request('delete', path, hope)
class Test:
def __init__(self, base='http://localhost:8888', create_admin=False, admin=None, init_verbose=False):
'''
@opt:base = base url string
@opt:create_admin = creates admin account directly off cargo -c <NAME>
@opt:admin = optionally pass in dictionary with some admin credentials
potentially from another instance to run multiple tests at once
'''
self.test_count = 0
self.out = sys.stdout # changed before worker runtime
if create_admin:
self.body = Test.__create_admin()
self.id = self.body['id']
self.secret = self.body['secret']
if init_verbose:
print(f'TESTBOT Using => {self.body}')
elif admin is not None:
self.body = body
self.id = self.body['id']
self.secret = self.body['secret']
else:
# for now we use this because my dev server has this fake ass acc on it
self.secret = 'mH7DfAfSLHhVbo9OW4dmqTbzzLnFaZQLxoZFIlKvKHm4NfpLyZsZrYdf12aACZXyEQxELOlBTe2rc36vTPVd8A==',
self.id = 2
# Required params
self.body = {
'name': 'owner sama uwu',
'joindate': 69,
'status': 0,
'permissions': 18446744073709551615
}
self.default_body = {}
# deep copy of body to prevent side-channel writes
for k in self.body: self.default_body[k] = self.body[k]
self.base = base
def stdout_to_stderr(self):
self.out = sys.stderr
@staticmethod
def __create_admin():
# /home/$user/.cargo/bin/cargo <- normally
# prolly some awful shit on pipes
CARGO_BIN = os.getenv('CARGO_BIN')
proc = subprocess.run(f'{CARGO_BIN} run --release -- -c dev-test'.split(), text=True, capture_output=True)
try:
return json.loads(proc.stdout)
except:
import sys
print('TESTBOT UNABLE TO LOAD JSON DATA FROM -c flag', file=sys.stderr)
exit(1)
def log(self, params: dict, url: str, method: str, request: requests.Response, body=True):
f = sys.stdout
print(f'TESTBOT {method} {url} {request.status_code}', file=self.out)
print(f'TESTBOT\t\t[Parameters]: {params}', file=self.out)
if body:
print(f'TESTBOT\t\t[Body]: {request.text}\n', file=self.out)
def _build_req_body(self, **options):
_map = self.default_body
for key in options:
_map[key] = options[key]
return json.dumps(_map)
def post(self, url, jwt=False, **opts):
'''
@returns text of response
'''
options = opts
if jwt is False:
options['id'] = self.id
if isinstance(self.secret, tuple):
options['secret'] = self.secret[0]
else:
options['secret'] = self.secret
else:
options['jwt'] = jwt
body = self._build_req_body(**options)
r = requests.post(self.base + url, data=body)
self.log(opts, self.base + url, 'POST', r)
return r.text
def get(self, url, jwt=False, **opts):
'''
@returns text of response
'''
options = opts
if jwt is False:
options['id'] = self.id
if isinstance(self.secret, tuple):
options['secret'] = self.secret[0]
else:
options['secret'] = self.secret
else:
options['jwt'] = jwt
body = self._build_req_body(**options)
r = requests.get(self.base + url, data=body)
self.log(opts, self.base + url, 'GET', r)
return r.text
def delete(self, url, jwt=False, **opts):
'''
@returns text of response
'''
options = opts
if jwt is False:
options['id'] = self.id
if isinstance(self.secret, tuple):
options['secret'] = self.secret[0]
else:
options['secret'] = self.secret
else:
options['jwt'] = jwt
body = self._build_req_body(**options)
r = requests.delete(self.base + url, data=body)
self.log(opts, self.base + url, 'DELETE', r)
return r.text
def creds(self):
return self.body
def spam_messages(channel, jwt, worker):
for _ in range(15):
worker.post('/message/send', jwt=jwt, channel=channel, content='dummy post')
def run(worker):
VOICE_CHAN = 1
TEXT_CHAN = 2
worker.stdout_to_stderr()
# the first two are sanity checks and should not faill
worker.get('/channels/list') # Should 400 or something since we're not sending the right keys
jwt_response = worker.post('/login', jwt=False)
jwt = json.loads(jwt_response)['jwt']
worker.get('/channels/list', jwt=jwt) # maybe now we'll 200?
# now for some things that may/may not fail or something idk
cname = time.time()
# pass 200
newchannel = worker.post('/channels/create', jwt=jwt, name=f'{cname}', kind=2, description='some description')
newchannel = json.loads(newchannel)
# fail 400 or something
worker.post('/channels/create', jwt=jwt, name=f'{cname}', kind=VOICE_CHAN, description='some description')
# ez pass
worker.get('/channels/list', jwt=jwt)
# pass 200
worker.post('/message/send', jwt=jwt, channel=newchannel['id'], content='some bullshit message')
# pass 200
worker.delete('/channels/delete', jwt=jwt, channel_id=newchannel['id'])
# fail 400
worker.post('/channels/create', jwt=False, name=f'succ', kind=2)
# pass 200
worker.get('/meta', jwt=jwt)
# Getting messages now
# pass 200
send_chan = worker.post('/channels/create', jwt=jwt, name=f'{cname}', kind=2, description='some description')
send_chan = json.loads(send_chan)
# pass 200(all)
spam_messages(send_chan['id'], jwt, worker)
now = time.time()
messages = json.loads(worker.get('/message/get_range', jwt=jwt, **{
'start-time': int(now - 15),
'end-time': int(now + 1),
'channel': send_chan['id']
}))
# 200 pass
from_id = worker.get('/message/from_id', jwt=jwt, **{
'channel': send_chan['id'],
'start': messages['messages'][0]['id']
})
print('done')
if __name__ == '__main__':
worker = Test(create_admin=False, init_verbose=True)
run(worker)