Skip to content

Commit

Permalink
bug fixes to downsample serivce and testing additions
Browse files Browse the repository at this point in the history
  • Loading branch information
dkleissa committed Apr 11, 2017
1 parent d913124 commit cf1934a
Show file tree
Hide file tree
Showing 6 changed files with 341 additions and 47 deletions.
10 changes: 10 additions & 0 deletions django/bosscore/test/setup_db.py
Expand Up @@ -125,6 +125,16 @@ def insert_iso_data(self):
self.add_experiment('col1', 'exp_iso', 'cf2iso', 8, 500, 1, hierarchy_method="isotropic")
self.add_channel('col1', 'exp_iso', 'channel1', 0, 0, 'uint8', 'image')

def insert_downsample_data(self):
"""Some resources for small downsample tests"""
self.add_coordinate_frame('cf_ds_aniso', 'Description for cf2', 0, 4069, 0, 4069, 0, 128, 4, 4, 35)
self.add_experiment('col1', 'exp_ds_aniso', 'cf_ds_aniso', 3, 500, 1)
self.add_channel('col1', 'exp_ds_aniso', 'channel1', 0, 0, 'uint8', 'image')

self.add_coordinate_frame('cf_ds_iso', 'Description for cf2', 0, 4069, 0, 4069, 0, 128, 6, 6, 6)
self.add_experiment('col1', 'exp_ds_iso', 'cf_ds_iso', 3, 500, 1, hierarchy_method="isotropic")
self.add_channel('col1', 'exp_ds_iso', 'channel1', 0, 0, 'uint8', 'image')

@staticmethod
def add_permissions(group, obj):
# Get the type of model
Expand Down
51 changes: 44 additions & 7 deletions django/bossingest/test/int_test_ingest_views.py
Expand Up @@ -177,14 +177,11 @@ def test_list_user_jobs(self):
response = self.client.delete(url)
assert (response.status_code == 204)

# Add a completed job
# Add another job
url = '/' + version + '/ingest/'
response = self.client.post(url, data=config_data, format='json')
assert (response.status_code == 201)
ingest_job_completed = response.json()
url = '/' + version + '/ingest/{}/complete'.format(ingest_job_completed['id'])
response = self.client.post(url)
assert(response.status_code == 204)
ingest_job_3 = response.json()

# List
url = '/' + version + '/ingest/'
Expand All @@ -193,8 +190,8 @@ def test_list_user_jobs(self):
self.assertEqual(2, len(result["ingest_jobs"]))
self.assertEqual(result["ingest_jobs"][0]['id'], ingest_job_2['id'])
self.assertEqual(result["ingest_jobs"][0]['status'], 0)
self.assertEqual(result["ingest_jobs"][1]['id'], ingest_job_completed['id'])
self.assertEqual(result["ingest_jobs"][1]['status'], 2)
self.assertEqual(result["ingest_jobs"][1]['id'], ingest_job_3['id'])
self.assertEqual(result["ingest_jobs"][1]['status'], 0)

def test_list_admin_jobs(self):
""" Test listing ALL jobs as the admin user"""
Expand Down Expand Up @@ -228,6 +225,25 @@ def test_list_admin_jobs(self):
ingest_job_completed = response.json()
url = '/' + version + '/ingest/{}/complete'.format(ingest_job_completed['id'])
response = self.client.post(url)
# Can't complete until it is done
assert(response.status_code == 400)

# Wait for job to complete
for cnt in range(0, 30):
# Try joining to kick the status
url = '/' + version + '/ingest/{}/'.format(ingest_job_completed['id'])
self.client.get(url)

url = '/' + version + '/ingest/{}/status'.format(ingest_job_completed['id'])
response = self.client.get(url)
if response.json()["status"] == 1:
break

time.sleep(10)

# Complete the job
url = '/' + version + '/ingest/{}/complete'.format(ingest_job_completed['id'])
response = self.client.post(url)
assert(response.status_code == 204)

# Log in as the admin and create a job
Expand Down Expand Up @@ -278,6 +294,26 @@ def test_complete_ingest_job(self):
assert(response.json()['ingest_job']['id'] == ingest_job['id'])
assert("credentials" in response.json())

# Complete the job
url = '/' + version + '/ingest/{}/complete'.format(ingest_job['id'])
response = self.client.post(url)

# Can't complete until it is done
assert(response.status_code == 400)

# Wait for job to complete
for cnt in range(0, 30):
# Try joining to kick the status
url = '/' + version + '/ingest/{}/'.format(ingest_job['id'])
self.client.get(url)

url = '/' + version + '/ingest/{}/status'.format(ingest_job['id'])
response = self.client.get(url)
if response.json()["status"] == 1:
break

time.sleep(10)

# Complete the job
url = '/' + version + '/ingest/{}/complete'.format(ingest_job['id'])
response = self.client.post(url)
Expand Down Expand Up @@ -324,6 +360,7 @@ def test_job_status(self):

time.sleep(10)

url = '/' + version + '/ingest/{}/status'.format(ingest_job['id'])
response = self.client.get(url)
status = response.json()
self.assertEqual(status["status"], 1)
Expand Down
1 change: 1 addition & 0 deletions django/bossspatialdb/test/__init__.py
@@ -1,3 +1,4 @@
from .cutout_view_uint8 import CutoutInterfaceViewUint8TestMixin
from .cutout_view_uint16 import CutoutInterfaceViewUint16TestMixin
from .cutout_view_uint64 import CutoutInterfaceViewUint64TestMixin
from .test_downsample_view import DownsampleInterfaceViewMixin
180 changes: 180 additions & 0 deletions django/bossspatialdb/test/int_test_downsample_view.py
@@ -0,0 +1,180 @@
# Copyright 2016 The Johns Hopkins University Applied Physics Laboratory
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from django.conf import settings

from rest_framework.test import APITestCase, APIRequestFactory
from rest_framework.test import force_authenticate
from rest_framework import status

from bossspatialdb.views import Downsample
from bossspatialdb.test import DownsampleInterfaceViewMixin
from bossspatialdb.views import Cutout

from bosscore.test.setup_db import DjangoSetupLayer


from bosscore.test.setup_db import SetupTestDB
from bosscore.error import BossError
import json
from unittest.mock import patch
import time
import redis
import bossutils
import blosc
import numpy as np

version = settings.BOSS_VERSION

_global_mocked_config_data = bossutils.configuration.BossConfig()


def mock_boss_cfg():
return _global_mocked_config_data


@patch('bossutils.configuration.BossConfig', mock_boss_cfg)
class TestIntegrationDownsampleInterfaceView(DownsampleInterfaceViewMixin, APITestCase):
layer = DjangoSetupLayer

def test_start_downsample_get_status_and_check_data(self):
"""A large complex test that verifies all the pluming for downsample.
Does not validate data short of existing."""

self.dbsetup.insert_downsample_data()

# Post some data to the channel
test_mat = np.random.randint(1, 254, (16, 1024, 1024))
test_mat = test_mat.astype(np.uint8)
h = test_mat.tobytes()
bb = blosc.compress(h, typesize=8)

factory = APIRequestFactory()
request = factory.post('/' + version + '/cutout/col1/exp_ds_aniso/channel1/0/0:1024/0:1024/0:16/', bb,
content_type='application/blosc')
# log in user
force_authenticate(request, user=self.user)

# Make request
response = Cutout.as_view()(request, collection='col1', experiment='exp_ds_aniso', channel='channel1',
resolution='0', x_range='0:1024', y_range='0:1024', z_range='0:16', t_range=None)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)

# Wait for data to be written
request = factory.get('/' + version + '/cutout/col1/exp_ds_aniso/channel1/0/0:1024/0:1024/0:16/',
accepts='application/blosc')

# log in user
force_authenticate(request, user=self.user)

# Make request
response = Cutout.as_view()(request, collection='col1', experiment='exp_ds_aniso', channel='channel1',
resolution='0', x_range='0:1024', y_range='0:1024',
z_range='0:16', t_range=None).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)

# Trigger downsample
factory = APIRequestFactory()
request = factory.post('/' + version + '/downsample/col1/exp_ds_aniso/channel1/',
content_type='application/json')
# log in user
force_authenticate(request, user=self.user)

# Make request
response = Downsample.as_view()(request, collection='col1', experiment='exp_ds_aniso',
channel='channel1')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)

# Make Sure status has changed
factory = APIRequestFactory()
request = factory.get('/' + version + '/downsample/col1/exp_ds_aniso/channel1/',
content_type='application/json')
# log in user
force_authenticate(request, user=self.user)

# Make request
response = Downsample.as_view()(request, collection='col1', experiment='exp_ds_aniso',
channel='channel1').render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["num_hierarchy_levels"], 3)
self.assertEqual(response.data["status"], "IN_PROGRESS")

for _ in range(0, 30):
# Make request
response = Downsample.as_view()(request, collection='col1', experiment='exp_ds_aniso',
channel='channel1').render()
self.assertEqual(response.status_code, status.HTTP_200_OK)

if response.data["status"] != "IN_PROGRESS":
break

time.sleep(2)

# Verify now downsampled
response = Downsample.as_view()(request, collection='col1', experiment='exp_ds_aniso',
channel='channel1').render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["num_hierarchy_levels"], 3)
self.assertEqual(response.data["status"], "DOWNSAMPLED")

# Get data at res 1 and verify it's non-zero
request = factory.get('/' + version + '/cutout/col1/exp_ds_aniso/channel1/1/0:512/0:512/0:16/',
accepts='application/blosc')

# log in user
force_authenticate(request, user=self.user)

# Make request
response = Cutout.as_view()(request, collection='col1', experiment='exp_ds_aniso', channel='channel1',
resolution='1', x_range='0:512', y_range='0:512',
z_range='0:16', t_range=None).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
raw_data = blosc.decompress(response.content)
data_mat = np.fromstring(raw_data, dtype=np.uint8)
data_mat = np.reshape(data_mat, (16, 512, 512), order='C')

# Make sure not blank
self.assertGreater(data_mat.sum(), 100)

def setUp(self):
""" Copy params from the Layer setUpClass
"""
# Setup config
self.kvio_config = self.layer.kvio_config
self.state_config = self.layer.state_config
self.object_store_config = self.layer.object_store_config
self.user = self.layer.user

_global_mocked_config_data["aws"]["cuboid_bucket"] = self.object_store_config["cuboid_bucket"]
_global_mocked_config_data["aws"]["s3-index-table"] = self.object_store_config["s3_index_table"]
_global_mocked_config_data["aws"]["id-index-table"] = self.object_store_config["id_index_table"]

# Log Django User in
self.client.force_login(self.user)

# Flush cache between tests
client = redis.StrictRedis(host=self.kvio_config['cache_host'],
port=6379, db=1, decode_responses=False)
client.flushdb()
client = redis.StrictRedis(host=self.state_config['cache_state_host'],
port=6379, db=1, decode_responses=False)
client.flushdb()

# Populate DB
self.dbsetup = self.layer.django_setup_helper
self.dbsetup.insert_iso_data()

def tearDown(self):
# Stop mocking
pass
73 changes: 41 additions & 32 deletions django/bossspatialdb/test/test_downsample_view.py
Expand Up @@ -23,33 +23,18 @@
from bosscore.test.setup_db import SetupTestDB
from bosscore.error import BossError
import json
from unittest.mock import patch


version = settings.BOSS_VERSION

#@patch('redis.StrictRedis', mock_strict_redis_client)
#def mock_init_(self, kv_conf, state_conf, object_store_conf):
# print("init mocker")
# self.kv_config = kv_conf
# self.state_conf = state_conf
# self.object_store_config = object_store_conf
#
# # Threshold number of cuboids for using lambda on reads
# self.read_lambda_threshold = 600 # Currently high since read lambda not implemented
# # Number of seconds to wait for dirty cubes to get clean
# self.dirty_read_timeout = 60
#
# if not _test_globals['cache']:
# kv_conf["cache_db"] = 1
# state_conf["cache_state_db"] = 1
# print(kv_conf)
# print(state_conf)
# _test_globals['cache'] = RedisKVIO(kv_conf)
# _test_globals['state'] = CacheStateDB(state_conf)
#
# self.kvio = _test_globals['cache']
# self.cache_state = _test_globals['state']
# self.objectio = AWSObjectStore(object_store_conf)

def mock_sfn_status(a, b):
return "RUNNING"


def mock_sfn_execute(a, b, c):
return "ARN:abc123"


class DownsampleInterfaceViewMixin(object):
Expand Down Expand Up @@ -198,8 +183,36 @@ def test_get_aniso_properties_iso(self):
self.assertEqual(response.data["cuboid_size"]['3'], [512, 512, 16])
self.assertEqual(response.data["cuboid_size"]['5'], [512, 512, 16])

def test_start_downsample_aniso(self):
self.dbsetup.insert_downsample_data()

#@patch('spdb.spatialdb.SpatialDB.__init__', mock_init_)
factory = APIRequestFactory()
request = factory.post('/' + version + '/downsample/col1/exp_ds_aniso/channel1/',
content_type='application/json')
# log in user
force_authenticate(request, user=self.user)

# Make request
response = Downsample.as_view()(request, collection='col1', experiment='exp_ds_aniso',
channel='channel1')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)

# Make Sure status has changed
factory = APIRequestFactory()
request = factory.get('/' + version + '/downsample/col1/exp_ds_aniso/channel1/',
content_type='application/json')
# log in user
force_authenticate(request, user=self.user)

# Make request
response = Downsample.as_view()(request, collection='col1', experiment='exp_ds_aniso',
channel='channel1').render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["num_hierarchy_levels"], 3)
self.assertEqual(response.data["status"], "IN_PROGRESS")

@patch('bossutils.aws.sfn_status', mock_sfn_status)
@patch('bossutils.aws.sfn_execute', mock_sfn_execute)
class TestDownsampleInterfaceView(DownsampleInterfaceViewMixin, APITestCase):

def setUp(self):
Expand All @@ -208,13 +221,9 @@ def setUp(self):
:return:
"""
# Create a user
dbsetup = SetupTestDB()
self.user = dbsetup.create_user('testuser')
self.dbsetup = SetupTestDB()
self.user = self.dbsetup.create_user('testuser')

# Populate DB
dbsetup.insert_spatialdb_test_data()
dbsetup.insert_iso_data()

def tearDown(self):
# Stop mocking
pass
self.dbsetup.insert_spatialdb_test_data()
self.dbsetup.insert_iso_data()

0 comments on commit cf1934a

Please sign in to comment.