def test_api_update_reference_007(server): """Update one reference with PUT request. Try to update resource ``uuid`` attribute with PUT /references/{id}. This must not work because the ``uuid`` attribute cannot be changed by client. """ storage = { 'data': [ Storage.gitlog ] } request_body = { 'data': { 'type': 'reference', 'attributes': { 'links': storage['data'][0]['links'], 'uuid': '11111111-1111-1111-1111-111111111111' } } } expect_headers_p3 = {'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '1120'} expect_headers_p2 = {'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '1159'} expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': 'json media validation failed' }] } result = testing.TestClient(server.server.api).simulate_put( path='/api/snippy/rest/references/5c2071094dbfaa33', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_400 assert result.headers in (expect_headers_p2, expect_headers_p3) Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_update_reference_003(server): """Update one reference with PUT request. Try to send PUT /references/{id} to update resource with ``id`` in URI path that is not found. """ storage = { 'data': [ Storage.gitlog ] } request_body = { 'data': { 'type': 'snippet', 'attributes': { 'links': Request.regexp['links'], } } } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '377' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '404', 'statusString': '404 Not Found', 'module': 'snippy.testing.testing:123', 'title': 'cannot find content with content identity: 101010101010101' }] } result = testing.TestClient(server.server.api).simulate_put( path='/api/snippy/rest/references/101010101010101', headers={'accept': 'application/json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_404 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_create_solution_006(server): """Try to create solution with resource id. Try to send POST /solutions/{id} to create a new resource with resource ID in URL. The POST method is not overriden with custom ``X-HTTP-Method-Override`` header. """ request_body = { 'data': [{ 'type': 'solution', 'attributes': Request.dnginx }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '403' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': 'cannot create resource with id, use x-http-method-override to override the request' }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/solutions/53908d68425c61dc', headers={'accept': 'application/json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_400 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(None)
def test_api_create_solution_010(server): """Try to create two solutions. Try to send POST /solutions to create two new resources. The second resource contains an empty mandatory attribute ``data``. The HTTP request must be rejected with an error. """ request_body = { 'data': [{ 'type': 'solution', 'attributes': Request.dnginx }, { 'type': 'solution', 'attributes':{ 'data': [] } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '367' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': 'mandatory attribute data for solution is empty' }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/solutions', headers={'accept': 'application/json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_400 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(None)
def test_api_create_snippet_010(server): """Try to create snippet with malformed JSON request. Try to send POST /snippets to create new a resource with client generated ``id``. This is not supported and it will generate error. """ request_body = { 'data': [{ 'type': 'snippet', 'id': Snippet.REMOVE_DIGEST, 'attributes': Request.remove }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '387' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '403', 'statusString': '403 Forbidden', 'module': 'snippy.testing.testing:123', 'title': 'client generated resource id is not supported, remove member data.id' }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/snippets', headers={'accept': 'application/json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_403 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(None)
def test_api_update_solution_008(server): """Update one solution with PUT request. Try to update solution ``uuid`` attribute by sending PUT /solutions. This must not work because the ``uuid`` cannot be changed by client. """ storage = { 'data': [ Storage.ebeats ] } request_body = { 'data': { 'type': 'solution', 'attributes': { 'data': storage['data'][0]['data'], 'uuid': '11111111-1111-1111-1111-111111111111' } } } expect_headers_p3 = {'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '3813'} expect_headers_p2 = {'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '3905'} expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': 'json media validation failed' }] } result = testing.TestClient(server.server.api).simulate_put( path='/api/snippy/rest/solutions/4346ba4c79247430', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_400 assert result.headers in (expect_headers_p2, expect_headers_p3) Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_search_groups_004(server): """Get specific content based on ``groups`` attribute. Try to call GET /groups/docker,python and limit search to content categories defined in plural forms. This must not work because only the singular formats for the content category ``--scat`` option are supported. """ expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '551' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': "content categories: ('snippets', 'solutions') :are not a subset of: ('snippet', 'solution', 'reference')" }, { 'status': '404', 'statusString': '404 Not Found', 'module': 'snippy.testing.testing:123', 'title': 'cannot find resources' }] } result = testing.TestClient(server.server.api).simulate_get( path='/api/snippy/rest/groups/docker,python', headers={'accept': 'application/vnd.api+json'}, query_string='sall=test&limit=20&sort=brief&scat=snippets,solutions' ) assert result.status == falcon.HTTP_400 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body)
def test_api_delete_snippet_002(server): """Try to delete snippet. Try to send DELETE /snippet{id} with a ``id`` in URI that does not exist. """ content = { 'data': [ Storage.remove, Storage.forced, Storage.netcat, ] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '370' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '404', 'statusString': '404 Not Found', 'module': 'snippy.testing.testing:123', 'title': 'cannot find content with content identity: beefbeef' }] } result = testing.TestClient(server.server.api).simulate_delete( path='/api/snippy/rest/snippets/beefbeef', headers={'accept': 'application/json'}) assert result.status == falcon.HTTP_404 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(content)
def test_api_update_solution_004(server): """Try to update solution with malformed request. Try to send PUT /solutions/{id} to update resource with malformed JSON request. """ storage = { 'data': [ Storage.ebeats ] } request_body = { 'data': Const.NEWLINE.join(Request.dnginx['data']), 'brief': Request.dnginx['brief'], 'groups': Request.dnginx['groups'], 'tags': Const.DELIMITER_TAGS.join(Request.dnginx['tags']), 'links': Const.DELIMITER_LINKS.join(Request.dnginx['links']) } expect_headers_p3 = {'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '5090'} expect_headers_p2 = {'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '4975'} expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': 'json media validation failed' }] } result = testing.TestClient(server.server.api).simulate_put( path='/api/snippy/rest/solutions/4346ba4c79247430', headers={'accept': 'application/json'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_400 assert result.headers in (expect_headers_p2, expect_headers_p3) Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)
def test_api_search_groups_008(server): """Get specific content based on ``groups`` attribute. Try to call GET /groups/docker to get all content from the docker group. In this case one of the scat search keywords defining the category is not correct and error must be returned. """ expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '563' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': "content categories: ('reference', 'snippet', 'solutions') :are not a subset of: ('snippet', 'solution', 'reference')" }, { 'status': '404', 'statusString': '404 Not Found', 'module': 'snippy.testing.testing:123', 'title': 'cannot find resources' }] } result = testing.TestClient(server.server.api).simulate_get( path='/api/snippy/rest/groups/docker', headers={'accept': 'application/vnd.api+json'}, query_string='scat=snippet,solutions,reference&uuid=1') assert result.status == falcon.HTTP_400 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body)
def test_api_hello_api_009(caplog): """Test server hello response. Send GET /api/snippy/rest to get server hello response. In this case the server host is changed from the default with command line option. """ expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '246' } expect_body = {'meta': Content.get_api_meta()} server = Snippy( ['snippy', 'server', '--server-host', 'localhost:8081', '--debug']) server.run() result = testing.TestClient( server.server.api).simulate_get('/api/snippy/rest') assert 'server_host=localhost:8081' in caplog.text assert result.status == falcon.HTTP_200 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) server.release() Content.delete()
def test_api_create_solution_008(server): """Create one solution from API. Try to send POST /solutions to create new a resource with an empty resource ``data`` attribute. """ request_body = { 'data': [{ 'type': 'solution', 'attributes': { 'data': [], } }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '367' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': 'mandatory attribute data for solution is empty' }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/solutions', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_400 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(None)
def test_api_hello_api_017(caplog, osenviron): """Test server configuration. Send GET /api/snippy/rest/v3 to get server hello response. In this case the server options are configured with environment variables and command line options. The command line option has higher precedence and they must be used. """ osenviron.setenv('SNIPPY_SERVER_BASE_PATH_REST', '/api/snippy/rest/v2') osenviron.setenv('SNIPPY_SERVER_HOST', '127.0.0.1:8081') osenviron.setenv('SNIPPY_SERVER_MINIFY_JSON', 'False') osenviron.setenv('SNIPPY_LOG_MSG_MAX', '100') osenviron.setenv('SNIPPY_LOG_JSON', '0') # Must be mapped to False. expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '202' } expect_body = {'meta': Content.get_api_meta()} server = Snippy(['snippy', 'server', '--server-host', 'localhost:8080', '--server-base-path-rest', '/api/snippy/rest/v3', '--server-minify-json', '--log-msg-max', '20', '--debug']) # noqa pylint: disable=line-too-long server.run() result = testing.TestClient( server.server.api).simulate_get('/api/snippy/rest/v3') assert 'server_base_path_rest=/api/snippy/rest/v3' in caplog.text assert 'server_host=localhost:8080' in caplog.text assert 'server_minify_json=True' in caplog.text assert 'storage_type=sqlite' in caplog.text assert 'log_msg_max=20' in caplog.text # Debug log settings are twice and both parsing must be correct. assert 'log msg max: 20' in caplog.text # Debug log settings are twice and both parsing must be correct. assert 'log_json=False' in caplog.text # Debug log settings are twice and both parsing must be correct. assert 'json logs: False' in caplog.text # Debug log settings are twice and both parsing must be correct. assert result.status == falcon.HTTP_200 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) server.release() Content.delete()
def test_api_search_reference_field_017(server): """Get resource attribute. Try to send GET /snippets/{id}/notexist for non existing snippet with invalid attribute. """ expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '536' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': 'resource field does not exist: notexist' }, { 'status': '404', 'statusString': '404 Not Found', 'module': 'snippy.testing.testing:123', 'title': 'content identity: 0101010101 was not unique and matched to: 0 resources' }] } result = testing.TestClient(server.server.api).simulate_get( path='/api/snippy/rest/references/0101010101/notexist', headers={'accept': 'application/vnd.api+json'}) assert result.status == falcon.HTTP_400 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body)
def test_api_create_reference_008(server_db, used_database): """Try to create a Reference resource. Try to POST new resource when database throws an unique constraint violation error from the ``uuid`` attribute. In this case there is no stored resources and digest in generated error message cannot filled fromi database. The database tries to insert the content twice once batched and then one by one. Both of the inserts result same unique constraint violation. """ request_body = { 'data': [{ 'type': 'reference', 'attributes': Request.gitlog }] } expect_headers = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '583' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '500', 'statusString': '500 Internal Server Error', 'module': 'snippy.testing.testing:123', 'title': 'internal error when searching content possibly violating database unique constraints' }, { 'status': '500', 'statusString': '500 Internal Server Error', 'module': 'snippy.testing.testing:123', 'title': 'content: uuid :already exist with digest: not found' }] } server = server_db[0] db_connect = server_db[1] if used_database in (Helper.DB_SQLITE, Helper.DB_IN_MEMORY): db_connect.return_value.commit.side_effect = [ sqlite3.IntegrityError( 'UNIQUE constraint failed: contents.uuid'), sqlite3.IntegrityError( 'UNIQUE constraint failed: contents.uuid') ] elif used_database == Helper.DB_POSTGRESQL: db_connect.return_value.commit.side_effect = [ sqlite3.IntegrityError( 'duplicate key value violates unique constraint "contents_data_key"\n' + 'DETAIL: Key (uuid)=11cd5827-b6ef-4067-b5ac-3ceac07dde9f already exists.' ), sqlite3.IntegrityError( 'duplicate key value violates unique constraint "contents_data_key"\n' + 'DETAIL: Key (uuid)=11cd5827-b6ef-4067-b5ac-3ceac07dde9f already exists.' ), ] result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/references', headers={'accept': 'application/vnd.api+json; charset=UTF-8'}, body=json.dumps(request_body)) assert result.status == falcon.HTTP_500 assert result.headers == expect_headers Content.assert_restapi(result.json, expect_body) Content.assert_storage(None)
def test_api_create_snippet_015(server): """Update snippet with POST that maps to PATCH. Send POST /snippets with the ``X-HTTP-Method-Override`` header to update a resource. All resource attributes are tried to be updated. This must generate HTTP error because it is not possible to update for example the ``uuid`` attribute by client. """ storage = {'data': [Storage.forced]} request_body = { 'data': { 'type': 'snippet', 'attributes': { 'categeory': 'solution', 'data': 'data row1\ndata row2', 'brief': 'brief description', 'description': 'long description', 'name': 'runme', 'groups': 'solution', 'tags': 'tag1,tag2', 'links': 'link1\nlink2', 'source': 'http://testing/snippets.html', 'versions': 'version==1.1', 'filename': 'filename.txt', 'created': 'invalid time', 'updated': 'invalid time', 'uuid': Snippet.EXITED_UUID, 'digest': 'invalid digest' } } } expect_headers_p3 = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '1784' } expect_headers_p2 = { 'content-type': 'application/vnd.api+json; charset=UTF-8', 'content-length': '1875' } expect_body = { 'meta': Content.get_api_meta(), 'errors': [{ 'status': '400', 'statusString': '400 Bad Request', 'module': 'snippy.testing.testing:123', 'title': 'json media validation failed' }] } result = testing.TestClient(server.server.api).simulate_post( path='/api/snippy/rest/snippets/53908d68425c61dc', headers={ 'accept': 'application/vnd.api+json', 'X-HTTP-Method-Override': 'PATCH' }, body=json.dumps(request_body)) assert result.status == falcon.HTTP_400 assert result.headers in (expect_headers_p2, expect_headers_p3) Content.assert_restapi(result.json, expect_body) Content.assert_storage(storage)