def test_can_get_image_when_auth_okay(self): config = webapp.get_debug_config("kdu") config["authorizer"] = {"impl": "loris.authorizer.NullAuthorizer"} app = webapp.Loris(config) client = Client(application=webapp.Loris(config), response_wrapper=BaseResponse) resp = client.get("/%s/full/full/0/default.jpg" % self.test_jpeg_id) assert resp.status_code == 200
def test_cannot_get_info_when_auth_required(self): config = webapp.get_debug_config("kdu") config["authorizer"] = {"impl": "loris.authorizer.NooneAuthorizer"} app = webapp.Loris(config) client = Client(application=webapp.Loris(config), response_wrapper=BaseResponse) resp = client.get("/%s/info.json" % self.test_jpeg_id) assert resp.status_code == 401
def test_can_edit_embedded_color_profile(self): # By default, LorisTest uses the Kakadu transformer. Switch to the # OPENJPEG transformer before we get the reference image. config = get_debug_config('opj') self.build_client_from_config(config) self._assert_can_edit_embedded_color_profile( ident=self.test_jp2_with_embedded_profile_id, transformer='jp2', debug_config='opj')
def test_hung_process_gets_terminated(self): config = get_debug_config('opj') config['transforms']['jp2']['opj_decompress'] = '/dev/null' config['transforms']['jp2']['timeout'] = 1 self.build_client_from_config(config) ident = self.test_jp2_color_id request_path = '/%s/full/full/0/default.jpg' % ident response = self.client.get(request_path) assert response.status_code == 500 assert 'JP2 transform process timed out' in response.data.decode( 'utf8')
def test_kdu_expand_error(self): config = get_debug_config('kdu') config['transforms']['jp2']['kdu_expand'] = 'lorisrandomzzz/kdu_expand' config['transforms']['jp2']['timeout'] = 1 self.build_client_from_config(config) ident = self.test_jp2_color_id request_path = '/%s/full/full/0/default.jpg' % ident response = self.client.get(request_path) assert response.status_code == 500 assert 'Server Side Error: error generating derivative image: see log (500)' in response.data.decode( 'utf8')
def test_respects_pil_max_image_pixels(self): default_max_pixels = Image.MAX_IMAGE_PIXELS try: config = get_debug_config('kdu') config['transforms']['pil_max_image_pixels'] = 1 self.build_client_from_config(config) with pytest.raises(Image.DecompressionBombError): request_path = '/%s/full/300,300/0/default.jpg' % self.ident self.request_image_from_client(request_path) finally: # Because we have to mutate a value in an external library # it must be reset at the end of this test Image.MAX_IMAGE_PIXELS = default_max_pixels
def test_editing_embedded_color_profile_failure_is_not_error(self): ident = self.test_jpeg_with_embedded_cmyk_profile_id request_path = '/%s/full/full/0/default.jpg' % ident image_orig = self.request_image_from_client(request_path) # Set up an instance of the client with color profile editing. # We need to disable caching so the new request doesn't pick up # the cached image. config = get_debug_config('kdu') config['transforms']['jpg']['map_profile_to_srgb'] = True config['transforms']['jpg']['srgb_profile_fp'] = self.srgb_color_profile_fp config['loris.Loris']['enable_caching'] = False self.build_client_from_config(config) image_converted = self.request_image_from_client(request_path) # Now fetch the image, and check that it remains unmodified. self.assertEqual(image_orig.histogram(), image_converted.histogram())
def test_sends_content_disposition_header_for_image(self): config = webapp.get_debug_config("kdu") app = webapp.Loris(config) client = Client(application=webapp.Loris(config), response_wrapper=BaseResponse) jpg_resp = client.get("/%s/full/full/0/default.jpg" % self.test_jpeg_id) expected_filename = os.path.relpath(self.test_jpeg_fp, self.test_img_dir) assert jpg_resp.headers["Content-Disposition"] == ( "filename*=utf-8''%s" % expected_filename) png_resp = client.get("/%s/full/full/0/default.png" % self.test_jpeg_id) assert png_resp.headers["Content-Disposition"] == ( "filename*=utf-8''%s.png" % expected_filename)
def _assert_can_edit_embedded_color_profile(self, ident, transformer, debug_config='kdu'): request_path = '/%s/full/full/0/default.jpg' % ident image_orig = self.request_image_from_client(request_path) # Set up an instance of the client with color profile editing. # We need to disable caching so the new request doesn't pick up # the cached image. config = get_debug_config(debug_config) config['transforms'][transformer]['map_profile_to_srgb'] = True config['transforms'][transformer]['srgb_profile_fp'] = self.srgb_color_profile_fp config['loris.Loris']['enable_caching'] = False self.build_client_from_config(config) image_converted = self.request_image_from_client(request_path) # Now check that the image pixels have been edited -- this means # that the color profile has changed. Because image conversion # isn't stable across platforms, this is the best we can do for now. # TODO: Maybe try image hashing here? self.assertNotEqual(image_orig.histogram(), image_converted.histogram())
def setUp(self): self.URI_BASE = 'http://localhost' #for SimpleHTTPResolver self.SRC_IMAGE_CACHE = '/tmp/loris/cache/src_images' # create an instance of the app here that we can use in tests # see http://werkzeug.pocoo.org/docs/test/ config = get_debug_config('kdu') config['logging']['log_level'] = 'INFO' self.build_client_from_config(config) # constant info about test images. self.test_img_dir = path.join(path.abspath(path.dirname(__file__)), 'img') self.test_img_dir2 = path.join(path.abspath(path.dirname(__file__)), 'img2') test_json_dir = path.join(path.abspath(path.dirname(__file__)), 'json') test_icc_dir = path.join(path.abspath(path.dirname(__file__)), 'icc') self.test_jp2_color_fp = path.join(self.test_img_dir,'01','02','0001.jp2') self.test_jp2_color_info_fp = path.join(test_json_dir,'01','02','0001.jp2','info.json') self.test_jp2_color_fmt = 'jp2' self.test_jp2_color_id = '01%2F02%2F0001.jp2' self.test_jp2_color_uri = '%s/%s' % (self.URI_BASE, self.test_jp2_color_id) self.test_jp2_color_dims = (5906,7200) self.test_jp2_color_levels = 6 self.test_jp2_color_tiles = [ { "width": 256, "scaleFactors": [1,2,4,8,16,32,64] } ] self.test_jp2_color_sizes = [ { "height": 113, "width": 93 }, { "height": 225, "width": 185 }, { "height": 450, "width": 370 }, { "height": 900, "width": 739 }, { "height": 1800, "width": 1477 }, { "height": 3600, "width": 2953 }, { "height": 7200, "width": 5906 } ] self.test_jp2_gray_fp = path.join(self.test_img_dir,'01','02','gray.jp2') self.test_jp2_gray_fmt = 'jp2' self.test_jp2_gray_id = '01%2F02%2Fgray.jp2' self.test_jp2_gray_uri = '%s/%s' % (self.URI_BASE,self.test_jp2_gray_id) self.test_jp2_gray_dims = (2477,3200) # w,h self.test_jp2_gray_sizes = [ { "height": 50, "width": 39 }, { "height": 100, "width": 78 }, { "height": 200, "width": 155 }, { "height": 400, "width": 310 }, { "height": 800, "width": 620 }, { "height": 1600, "width": 1239 }, { "height": 3200, "width": 2477 } ] self.test_jp2_gray_tiles = [ { "width": 256, "scaleFactors": [1,2,4,8,16,32,64] } ] self.test_jpeg_fp = path.join(self.test_img_dir,'01','03','0001.jpg') self.test_jpeg_fmt = 'jpg' self.test_jpeg_id = '01%2F03%2F0001.jpg' self.test_jpeg_uri = '%s/%s' % (self.URI_BASE,self.test_jpeg_id) self.test_jpeg_dims = (3600,2987) # w,h self.test_jpeg_sizes = [] self.test_jpeg_grid_fp = path.join(self.test_img_dir, 'black_white_grid.jpg') self.test_jpeg_grid_id = 'black_white_grid.jpg' self.test_jpeg_grid_dims = (120, 120) self.test_tiff_fp = path.join(self.test_img_dir,'01','04','0001.tif') self.test_tiff_fmt = 'tif' self.test_tiff_id = '01%2F04%2F0001.tif' self.test_tiff_uri = '%s/%s' % (self.URI_BASE,self.test_tiff_id) self.test_tiff_dims = (839,1080) self.test_tiff_sizes = [] self.test_png_fp = path.join(self.test_img_dir,'henneken.png') self.test_png_fp2 = path.join(self.test_img_dir2,'henneken.png') self.test_png_fmt = 'png' self.test_png_id = 'henneken.png' self.test_png_uri = '%s/%s' % (self.URI_BASE,self.test_png_id) self.test_png_dims = (504,360) # w,h self.test_png_sizes = [] self.test_altpng_id = 'foo.png' self.test_altpng_fp = path.join(self.test_img_dir2,'foo.png') self.test_jp2_with_embedded_profile_id = '47102787.jp2' self.test_jp2_with_embedded_profile_fp = path.join(self.test_img_dir,self.test_jp2_with_embedded_profile_id) self.test_jp2_embedded_profile_copy_fp = path.join(test_icc_dir,'profile.icc') self.test_jp2_with_embedded_profile_fmt = 'jp2' self.test_jp2_with_embedded_profile_uri = '%s/%s' % (self.URI_BASE,self.test_jp2_with_embedded_profile_id) # A copy of 47102787.jp2, with the embedded color profile converted # to sRGB and saved as JPG. self.test_jp2_with_embedded_profile_to_srgb_jpg_fp = path.join( self.test_img_dir, '47102787_to_srgb.jpg' ) self.test_jpeg_with_embedded_profile_id = 'jpeg_with_p3_profile.jpg' self.test_jpeg_with_embedded_profile_fp = path.join(self.test_img_dir, self.test_jpeg_with_embedded_profile_id) # A JPEG with an embedded CMYK profile. Public domain image downloaded # from https://commons.wikimedia.org/wiki/File:Frog_logo_CMYK.jpg self.test_jpeg_with_embedded_cmyk_profile_id = 'jpeg_with_cmyk_profile.jpg' self.test_jp2_with_precincts_id = 'sul_precincts.jp2' self.test_jp2_with_precincts_fp = path.join(self.test_img_dir,self.test_jp2_with_precincts_id) self.test_jp2_with_precincts_fmt = 'jp2' self.test_jp2_with_precincts_uri = '%s/%s' % (self.URI_BASE,self.test_jp2_with_precincts_id) self.test_jp2_with_precincts_sizes = [ { "height": 93, "width": 71 }, { "height": 186, "width": 141 }, { "height": 372, "width": 281 }, { "height": 743, "width": 561 }, { "height": 1486, "width": 1122 }, { "height": 2972, "width": 2244 }, { "height": 5944, "width": 4488 } ] self.test_jp2_with_precincts_tiles = [ { "width": 128, "scaleFactors": [1,2,4,8,16] }, { "width": 256, "scaleFactors": [32,64] } ] # An ICC v2 sRGB color profile. # Downloaded from http://www.color.org/srgbprofiles.xalter self.srgb_color_profile_fp = path.join(test_icc_dir, 'sRGB2014.icc')
def test_invalid_tmp_dir_is_configerror(self): config = get_debug_config('kdu') config["loris.Loris"]["tmp_dp"] = "/dev/null/tmp" with pytest.raises(ConfigError, match="Error creating tmp_dp /dev/null/tmp:"): Loris(config)
def test_can_be_configured_with_authorizer(self): config = webapp.get_debug_config("kdu") config["authorizer"] = {"impl": "loris.authorizer.NullAuthorizer"} app = webapp.Loris(config) assert isinstance(app.authorizer, NullAuthorizer)
def test_can_be_configured_without_authorizer_impl(self): config = webapp.get_debug_config("kdu") del config["authorizer"]["impl"] app = webapp.Loris(config) assert app.authorizer is None
def test_debug_config_gives_openjpeg_transformer(self): config = webapp.get_debug_config('opj') app = webapp.Loris(config) assert isinstance(app.transformers['jp2'], OPJ_JP2Transformer)
def test_debug_config_gives_kakadu_transformer(self): config = webapp.get_debug_config('kdu') app = webapp.Loris(config) assert isinstance(app.transformers['jp2'], KakaduJP2Transformer)
def test_unrecognized_debug_config_is_configerror(self): with pytest.raises(ConfigError) as err: webapp.get_debug_config('no_such_jp2_transformer') assert 'Unrecognized debug JP2 transformer' in str(err.value)
def setUp(self): self.URI_BASE = 'http://localhost' #for SimpleHTTPResolver self.SRC_IMAGE_CACHE = '/tmp/loris/cache/src_images' # create an instance of the app here that we can use in tests # see http://werkzeug.pocoo.org/docs/test/ config = get_debug_config('kdu') config['logging']['log_level'] = 'INFO' self.app = Loris(config) self.client = Client(self.app, BaseResponse) # constant info about test images. self.test_img_dir = path.join(path.abspath(path.dirname(__file__)), 'img') self.test_img_dir2 = path.join(path.abspath(path.dirname(__file__)), 'img2') test_json_dir = path.join(path.abspath(path.dirname(__file__)), 'json') test_icc_dir = path.join(path.abspath(path.dirname(__file__)), 'icc') self.test_jp2_color_fp = path.join(self.test_img_dir, '01', '02', '0001.jp2') self.test_jp2_color_info_fp = path.join(test_json_dir, '01', '02', '0001.jp2', 'info.json') self.test_jp2_color_fmt = 'jp2' self.test_jp2_color_id = '01%2F02%2F0001.jp2' self.test_jp2_color_uri = '%s/%s' % (self.URI_BASE, self.test_jp2_color_id) self.test_jp2_color_dims = (5906, 7200) self.test_jp2_color_levels = 6 self.test_jp2_color_tiles = [{ "width": 256, "scaleFactors": [1, 2, 4, 8, 16, 32, 64] }] self.test_jp2_color_sizes = [{ "height": 113, "width": 93 }, { "height": 225, "width": 185 }, { "height": 450, "width": 370 }, { "height": 900, "width": 739 }, { "height": 1800, "width": 1477 }, { "height": 3600, "width": 2953 }, { "height": 7200, "width": 5906 }] self.test_jp2_gray_fp = path.join(self.test_img_dir, '01', '02', 'gray.jp2') self.test_jp2_gray_fmt = 'jp2' self.test_jp2_gray_id = '01%2F02%2Fgray.jp2' self.test_jp2_gray_uri = '%s/%s' % (self.URI_BASE, self.test_jp2_gray_id) self.test_jp2_gray_dims = (2477, 3200) # w,h self.test_jp2_gray_sizes = [{ "height": 50, "width": 39 }, { "height": 100, "width": 78 }, { "height": 200, "width": 155 }, { "height": 400, "width": 310 }, { "height": 800, "width": 620 }, { "height": 1600, "width": 1239 }, { "height": 3200, "width": 2477 }] self.test_jp2_gray_tiles = [{ "width": 256, "scaleFactors": [1, 2, 4, 8, 16, 32, 64] }] self.test_jpeg_fp = path.join(self.test_img_dir, '01', '03', '0001.jpg') self.test_jpeg_fmt = 'jpg' self.test_jpeg_id = '01%2F03%2F0001.jpg' self.test_jpeg_uri = '%s/%s' % (self.URI_BASE, self.test_jpeg_id) self.test_jpeg_dims = (3600, 2987) # w,h self.test_jpeg_sizes = [] self.test_tiff_fp = path.join(self.test_img_dir, '01', '04', '0001.tif') self.test_tiff_fmt = 'tif' self.test_tiff_id = '01%2F04%2F0001.tif' self.test_tiff_uri = '%s/%s' % (self.URI_BASE, self.test_tiff_id) self.test_tiff_dims = (839, 1080) self.test_tiff_sizes = [] self.test_png_fp = path.join(self.test_img_dir, 'henneken.png') self.test_png_fp2 = path.join(self.test_img_dir2, 'henneken.png') self.test_png_fmt = 'png' self.test_png_id = 'henneken.png' self.test_png_uri = '%s/%s' % (self.URI_BASE, self.test_png_id) self.test_png_dims = (504, 360) # w,h self.test_png_sizes = [] self.test_altpng_id = 'foo.png' self.test_altpng_fp = path.join(self.test_img_dir2, 'foo.png') self.test_jp2_with_embedded_profile_id = '47102787.jp2' self.test_jp2_with_embedded_profile_fp = path.join( self.test_img_dir, self.test_jp2_with_embedded_profile_id) self.test_jp2_embedded_profile_copy_fp = path.join( test_icc_dir, 'profile.icc') self.test_jp2_with_embedded_profile_fmt = 'jp2' self.test_jp2_with_embedded_profile_uri = '%s/%s' % ( self.URI_BASE, self.test_jp2_with_embedded_profile_id) self.test_jp2_with_precincts_id = 'sul_precincts.jp2' self.test_jp2_with_precincts_fp = path.join( self.test_img_dir, self.test_jp2_with_precincts_id) self.test_jp2_with_precincts_fmt = 'jp2' self.test_jp2_with_precincts_uri = '%s/%s' % ( self.URI_BASE, self.test_jp2_with_precincts_id) self.test_jp2_with_precincts_sizes = [{ "height": 93, "width": 71 }, { "height": 186, "width": 141 }, { "height": 372, "width": 281 }, { "height": 743, "width": 561 }, { "height": 1486, "width": 1122 }, { "height": 2972, "width": 2244 }, { "height": 5944, "width": 4488 }] self.test_jp2_with_precincts_tiles = [{ "width": 128, "scaleFactors": [1, 2, 4, 8, 16] }, { "width": 256, "scaleFactors": [32, 64] }]