Skip to content

Commit

Permalink
Merge pull request #59 from AO-StreetArt/FrameApi
Browse files Browse the repository at this point in the history
Frame API
  • Loading branch information
AO-StreetArt committed Apr 2, 2018
2 parents db16c45 + 688af42 commit a887154
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 43 deletions.
8 changes: 5 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ addons:
apt:
packages:
- nodejs
- python
- python-pip
- python3
- python3-pip
services:
- docker
before_install:
Expand All @@ -29,7 +29,7 @@ before_install:
- docker logs --tail 50 document-db
- docker logs --tail 50 graph-db
- npm install newman --global;
- pip install requests
- pip3 install requests --upgrade --user
install:
- gradle assemble
script:
Expand All @@ -38,6 +38,8 @@ script:
- sleep 60
- curl http://localhost:5885/health
- cd $TRAVIS_BUILD_DIR/src/test/resources && newman run AssetAPI.postman_collection.json -e AeselTest.postman_environment.json
- cd $TRAVIS_BUILD_DIR && python3 scripts/py/testUdp.py
- cd $TRAVIS_BUILD_DIR && python3 scripts/py/testFrameApi.py
after_success:
# Build and push the Docker image for Adrestia
- cd $TRAVIS_BUILD_DIR/scripts/linux && ./build_docker.sh $DOCKER_MAIL $DOCKER_UN $DOCKER_PW $TRAVIS_BRANCH
Expand Down
162 changes: 162 additions & 0 deletions scripts/py/testFrameApi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# The basic CLyman Flow performs a series of basic checks on the CLyman API
# It walks a single object through a full flow, step by step, and validates
# all of the fields on the object at each step of the way.

import logging
import sys
import json
import requests
import socket
import time

# Basic Config
aesel_addr = "http://127.0.0.1:5885"
log_file = 'logs/frameTest.log'
log_level = logging.DEBUG

# Test Scene Data
test_scene_data = {
"key":"",
"name":"frameFlow",
"latitude":124.0,
"longitude":122.0,
"distance":100.0,
"region":"basicFlowRegion",
"assets":["basicAsset"],
"tags":["basicTag"]
}

# The transforms we will track throughout the flow
# These get calculated by hand, and validate the transformations applied
# Current implementation applies LHS Matrix multiplication of translation,
# then euler rotation, then scale, in that order.
# Final Result can be found using http://matrix.reshish.com/multCalculation.php
# Translation Matrix:
# For a translation <x, y, z>, the corresponding matrix is:
# [1.0, 0.0, 0.0, x.0,
# 0.0, 1.0, 0.0, y.0,
# 0.0, 0.0, 1.0, z.0,
# 0.0, 0.0, 0.0, 1.0]
# Scale Matrix:
# For a scale <x, y, z>, the corresponding matrix is:
# [x.0, 0.0, 0.0, 0.0,
# 0.0, y.0, 0.0, 0.0,
# 0.0, 0.0, z.0, 0.0,
# 0.0, 0.0, 0.0, 1.0]
test_transform = [1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0]

updated_test_transform = [2.0, 0.0, 0.0, 1.0,
0.0, 2.0, 0.0, 1.0,
0.0, 0.0, 2.0, 1.0,
0.0, 0.0, 0.0, 1.0]

second_frame_transform = [2.0, 0.0, 0.0, 3.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 2.0, 1.0,
0.0, 0.0, 0.0, 1.0]

# Object data represented through each piece of the flow
test_data = {
"key": "",
"name": "frameTestObject",
"type": "basicTestType",
"subtype": "basicTestSubtype",
"owner": "basicTestOwner",
"scene": "frameFlow",
"frame": 0,
"translation": [0.0, 0.0, 0.0],
"euler_rotation": [0.0, 0.0, 0.0],
"scale": [1.0, 1.0, 1.0],
"assets": ["basicTestAsset"]
}

updated_test_data = {
"key": "",
"name": "frameTestObject",
"type": "Mesh",
"subtype": "Cube",
"owner": "Alex",
"scene": "frameFlow",
"frame": 0,
"translation": [1.0, 1.0, 1.0],
"euler_rotation": [0.0, 0.0, 0.0],
"scale": [2.0, 2.0, 2.0],
"assets": ["anotherAsset"]
}

second_frame_data = {
"key": "",
"name": "frameTestObject",
"type": "Mesh",
"subtype": "Cube",
"owner": "Alex",
"scene": "frameFlow",
"frame": 10,
"translation": [3.0, 0.0, 1.0],
"euler_rotation": [0.0, 0.0, 0.0],
"scale": [2.0, 2.0, 2.0],
"assets": ["anotherAsset"]
}

# Execute the actual tests
def execute_main():
# Grab the global pieces of data
global test_data
global test_transform
global updated_test_data
global updated_test_transform
global log_file
global log_level
global udp_ip
global udp_port
global aesel_addr

logging.basicConfig(filename=log_file, level=log_level)

# Connect to UDP Socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
logging.debug("Connected to UDP Socket")

# Create a Scene and Object
r = requests.post(aesel_addr + '/v1/scene/' + test_scene_data['name'], json=test_scene_data)
assert(r.status_code == requests.codes.ok)
response_json = r.json()
test_scene_data['key'] = response_json['key']
r = requests.post(aesel_addr + '/v1/scene/' + test_scene_data['name'] + "/object/" + test_data['name'], json=test_data)
assert(r.status_code == requests.codes.ok)
response_json = r.json()
test_data['key'] = response_json['key']
updated_test_data['key'] = response_json['key']

# Send in an update on another frame
payload = {"frame": 10}
r = requests.post(aesel_addr + '/v1/scene/' + test_scene_data['name'] + "/object/" + test_data['name'],
json=second_frame_data, params=payload)

# Validate that the update went through correctly
r = requests.get(aesel_addr + '/v1/scene/' + test_scene_data['name'] + '/object/' + updated_test_data['name'], params=payload)
assert(r.status_code == requests.codes.ok)
parsed_json = r.json()
if parsed_json is not None:
for i in range(0,16):
logging.debug("Validating Transform element: %s" % i)
assert(parsed_json["transform"][i] - second_frame_transform[i] < 0.01)
else:
assert(False)

# Delete the Object
r = requests.delete(aesel_addr + '/v1/scene/' + test_scene_data['name'] + '/object/' + updated_test_data['name'])
assert(r.status_code == requests.codes.ok)

# Validate that the delete went through correctly
r = requests.get(aesel_addr + '/v1/scene/' + test_scene_data['name'] + '/object/' + updated_test_data['name'])
assert(r.status_code != requests.codes.ok)

if __name__ == "__main__":
if len(sys.argv) > 1:
execute_main(sys.argv[1])
else:
execute_main()
2 changes: 1 addition & 1 deletion scripts/py/testUdp.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
def execute_udp_flow(sock, udp_ip, udp_port, aesel_addr, test_data,
test_transform, updated_test_data, updated_test_transform):
# Send the UDP Message
sock.sendto(json.dumps(updated_test_data), (udp_ip, udp_port))
sock.sendto(bytes(json.dumps(updated_test_data), 'UTF-8'), (udp_ip, udp_port))
time.sleep(1)
# Validate that the update went through correctly
r = requests.get(aesel_addr + '/v1/scene/' + test_scene_data['name'] + '/object/' + updated_test_data['name'])
Expand Down
77 changes: 52 additions & 25 deletions src/main/java/adrestia/controller/obj3/ObjectController.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ private ObjectList saveObject(ObjectDocument inpDoc, boolean docExists) {
}
}

// Query Clyman
private ObjectList objectQuery(String sceneName, String objName, int objFrame) {
// Execute a query against Clyman
ObjectDocument queryObj = new ObjectDocument();
queryObj.setName(objName);
queryObj.setScene(sceneName);
queryObj.setFrame(objFrame);
return objData.query(queryObj);
}

// Query Clyman
private ObjectList objectQuery(String sceneName, String objName) {
// Execute a query against Clyman
Expand All @@ -98,17 +108,21 @@ private boolean isSuccessResponse(ObjectList clymanResponse) {
/**
* Object Retrieval.
* Object name & object name input as path variables, no Request Parameters accepted.
* Add New Query Parameter for frame, 0 by default. Include frame in
* CLyman messages
*/
@RequestMapping(path = "scene/{scn_name}/object/{obj_name}", method = RequestMethod.GET)
public ResponseEntity<ObjectDocument> getObject(@PathVariable("scn_name") String sceneName,
@PathVariable("obj_name") String objName) {
@PathVariable("obj_name") String objName,
@RequestParam(value = "frame", defaultValue = "0") int frame)
{
logger.info("Responding to Object Get Request");
// Set up our response objects
ObjectDocument returnObj = new ObjectDocument();
HttpStatus returnCode = HttpStatus.OK;

// Retrieve the object requested
ObjectList clymanResponse = objectQuery(sceneName, objName);
ObjectList clymanResponse = objectQuery(sceneName, objName, frame);

// If we have a successful response, then we pull the first value and
// the error code
Expand Down Expand Up @@ -136,19 +150,22 @@ public ResponseEntity<ObjectDocument> getObject(@PathVariable("scn_name") String
* Object Create/Update.
* Object Name & Object name input as path variable, no Request Parameters accepted.
* POST Data read in with Object data.
* If we are updating, update only the doc with a matching frame.
* if we don't have a frame, set to frame 0
*/
@RequestMapping(path = "scene/{scn_name}/object/{obj_name}",
headers = "Content-Type=application/json",
method = RequestMethod.POST)
public ResponseEntity<ObjectDocument> updateObject(
@PathVariable("scn_name") String sceneName,
@PathVariable("obj_name") String objName,
@RequestParam(value = "frame", defaultValue = "0") int frame,
@RequestBody ObjectDocument inpObject) {
logger.info("Responding to Object Save Request");
ObjectDocument returnObj = new ObjectDocument();

// See if we can find the Object requested
ObjectList clymanResponse = objectQuery(sceneName, objName);
ObjectList clymanResponse = objectQuery(sceneName, objName, frame);

// If we have a successful response, then the Object exists
boolean objectExists = false;
Expand All @@ -166,6 +183,7 @@ public ResponseEntity<ObjectDocument> updateObject(
// Update the Object
inpObject.setName(objName);
inpObject.setScene(sceneName);
inpObject.setFrame(frame);
ObjectList updateResponse = saveObject(inpObject, objectExists);

// If we have a successful response, then we pull the first value
Expand Down Expand Up @@ -230,35 +248,39 @@ public ResponseEntity<ObjectDocument> overwriteObject(
method = RequestMethod.DELETE)
public ResponseEntity<ObjectDocument> deleteObject(
@PathVariable("scn_name") String sceneName,
@PathVariable("obj_name") String objName) {
@PathVariable("obj_name") String objName,
@RequestParam(value = "frame", defaultValue = "-1") int frame) {
logger.info("Responding to Object Delete Request");
ObjectDocument returnObj = new ObjectDocument();
HttpStatus returnCode = HttpStatus.OK;

// See if we can find the Object requested
ObjectList clymanResponse = objectQuery(sceneName, objName);
ObjectList clymanResponse;
if (frame == -1) {
clymanResponse = objectQuery(sceneName, objName);
} else {
clymanResponse = objectQuery(sceneName, objName, frame);
}

// If we have a successful response, then the Object exists
boolean objectExists = false;
// If we have a successful response, then the Object(s) exist
if (isSuccessResponse(clymanResponse)) {
objectExists = true;
logger.debug("Existing Object found in Clyman");
// Set the key on the input Object to the key from the response
String clymanRespKey = clymanResponse.getDocuments()[0].getKey();
if (clymanRespKey != null && !clymanRespKey.isEmpty()) {
logger.debug("Clyman Response Key: " + clymanRespKey);
ObjectList deleteResponse = objData.destroy(clymanRespKey);
returnCode = utils.translateDvsError(deleteResponse.getErrorCode());
// If we have a successful response, then set a success code
if (isSuccessResponse(deleteResponse)) {
returnObj = deleteResponse.getDocuments()[0];
for (int i = 0; i < clymanResponse.getDocuments().length; i++) {
String clymanRespKey = clymanResponse.getDocuments()[i].getKey();
if (clymanRespKey != null && !clymanRespKey.isEmpty()) {
logger.debug("Clyman Response Key: " + clymanRespKey);
ObjectList deleteResponse = objData.destroy(clymanRespKey);
returnCode = utils.translateDvsError(deleteResponse.getErrorCode());
// If we have a successful response, then set a success code
if (isSuccessResponse(deleteResponse)) {
returnObj = deleteResponse.getDocuments()[0];
} else {
logger.debug("Failure Registered. Clyman Response Error Code and Length:");
logger.debug(deleteResponse.getNumRecords());
logger.debug(deleteResponse.getErrorCode());
}
} else {
logger.debug("Failure Registered. Clyman Response Error Code and Length:");
logger.debug(deleteResponse.getNumRecords());
logger.debug(deleteResponse.getErrorCode());
logger.error("Unable to find key in clyman response");
}
} else {
logger.error("Unable to find key in clyman response");
}
} else {
// Delete request for non-existing object
Expand All @@ -285,7 +307,8 @@ public ResponseEntity<ObjectList> queryObject(
@PathVariable("scn_name") String sceneName,
@RequestParam(value = "type", defaultValue = "") String type,
@RequestParam(value = "subtype", defaultValue = "") String subtype,
@RequestParam(value = "owner", defaultValue = "") String owner) {
@RequestParam(value = "owner", defaultValue = "") String owner,
@RequestParam(value = "frame", defaultValue = "-9999") int frame) {
logger.info("Responding to Object Query");
ObjectDocument returnObj = new ObjectDocument();

Expand All @@ -301,6 +324,9 @@ public ResponseEntity<ObjectList> queryObject(
if (!(owner.isEmpty())) {
queryObj.setOwner(owner);
}
if (frame != -9999) {
queryObj.setFrame(frame);
}
ObjectList clymanResponse = objData.query(queryObj);

// Update our HTTP Response based on the Clyman response
Expand All @@ -325,10 +351,11 @@ private ResponseEntity<ObjectDocument> lockTransaction(String sceneName,
ObjectDocument returnObj = new ObjectDocument();
HttpStatus returnCode = HttpStatus.OK;

// Execute a query against Clyman
// Execute a query against Clyman with a frame of 9.
ObjectDocument queryObj = new ObjectDocument();
queryObj.setScene(sceneName);
queryObj.setName(objName);
queryObj.setFrame(0);
ObjectList clymanResponse = objData.query(queryObj);

if (isSuccessResponse(clymanResponse)) {
Expand Down

0 comments on commit a887154

Please sign in to comment.