def test_publisher_auth(self): example1_dir = op.join(self.get_examples_dir(), "example1") # Bad token should fail with self.assertRaises(ZenodoError) as e: bosh(["publish", op.join(example1_dir, "example1_docker.json"), "--sandbox", "-y", "-v", "--zenodo-token", "12345"]) self.assertTrue("Cannot authenticate to Zenodo" in str(e.exception)) # No token should fail with self.assertRaises(ZenodoError) as e: bosh(["publish", op.join(example1_dir, "example1_docker.json"), "--sandbox", "-y", "-v"]) self.assertTrue("Cannot authenticate to Zenodo" in str(e.exception)) # Right token should work self.assertTrue(bosh, ["publish", op.join(example1_dir, "example1_docker.json"), "--sandbox", "-y", "-v", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJ" "i8i2hnN8r"]) # Now no token should work (config file must have been updated) self.assertTrue(bosh, ["publish", op.join(example1_dir, "example1_docker.json"), "--sandbox", "-y", "-v"])
def test_publish_nexus_no_token_fail(self, mock_dir, mock_cred): cleanup() setup() with self.assertRaises(NexusError) as e: bosh(["data", "publish", "-y", "--nexus", "--sandbox"]) self.assertIn("Cannot find Nexus credentials.", str(e.exception))
def test_publication_errors(self): # Update an already published descriptor (wrong id) with self.assertRaises(ZenodoError) as e: wrong_id = bosh([ "publish", "whatever.json", "--sandbox", "-y", "-v", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJ" "i8i2hnN8r", "--id", "this_is_a_wrong_id" ]) self.assertTrue( "Zenodo ID must be prefixed by 'zenodo'" in str(e.exception)) # Publish a descriptor that doesn't have an author good_desc = op.join(self.get_examples_dir(), "good.json") temp_descriptor = tempfile.NamedTemporaryFile(suffix=".json") shutil.copyfile(good_desc, temp_descriptor.name) with self.assertRaises(ZenodoError) as e: no_author = bosh([ "publish", temp_descriptor.name, "--sandbox", "-y", "-v", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJ" "i8i2hnN8r" ]) self.assertTrue( "Tool must have an author to be published." in str(e.exception)) # Publish a descriptor that doesn't have a container image good_desc = op.join(self.get_examples_dir(), "no_container.json") temp_descriptor = tempfile.NamedTemporaryFile(suffix=".json") shutil.copyfile(good_desc, temp_descriptor.name) with self.assertRaises(ZenodoError) as e: no_container = bosh([ "publish", temp_descriptor.name, "--sandbox", "-y", "-v", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJ" "i8i2hnN8r" ]) self.assertTrue("Tool must have a container image to be published." in str(e.exception)) # Update a descriptor that doesn't have a DOI example1_dir = op.join(self.get_examples_dir(), "example1") example1_desc = op.join(example1_dir, "example1_docker.json") temp_descriptor = tempfile.NamedTemporaryFile(suffix=".json") shutil.copyfile(example1_desc, temp_descriptor.name) # Make sure that example1.json doesn't have a DOI yet with open(temp_descriptor.name, 'r') as fhandle: descriptor = json.load(fhandle) self.assertIsNone(descriptor.get('doi')) # Try to update it with self.assertRaises(ZenodoError) as e: doi = bosh([ "publish", temp_descriptor.name, "--sandbox", "-y", "-v", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r", "--replace" ]) self.assertTrue("To publish an updated version of a previously " "published descriptor, the descriptor must" " contain a DOI" in str(e.exception))
def test_publish_bulk(self, mock_dir, mock_get, mock_post): cleanup() setup() bosh(["data", "publish", "-y", "--sandbox", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrCPWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r"]) self.assertEqual(len(os.listdir(os.path.join(mock_get_data_cache()))), 2)
def test_pull_missing_raises_exception(self, mock_urlretrieve): good1 = "zenodo." + str(example_boutiques_tool.id) good2 = "zenodo.2587160" bad1 = "zenodo.9999990" with self.assertRaises(ZenodoError) as e: bosh(["pull", good1, bad1, good2]) self.assertIn( "Descriptor \"{0}\" not found".format(bad1.split(".")[1]), str(e.exception))
def test_invocation(self): descriptor = os.path.join( os.path.split(bfile)[0], "schema/examples/good.json") invocation = os.path.join( os.path.split(bfile)[0], "schema/examples/good_invocation.json") self.assertFalse( bosh(["invocation", descriptor, "-i", invocation, "-w"])) self.assertFalse( bosh(["invocation", descriptor, "-i", invocation, "-w"]))
def test_publish_nexus_no_organization_fail(self, mock_dir, mock_cred): cleanup() setup() with self.assertRaises(NexusError) as e: bosh(["data", "publish", "-y", "--nexus", "--sandbox", "--nexus-token", "hAaW2wSBZMskxpfigTYHcuDrCPWr2"]) self.assertIn("Cannot find Nexus organization.", str(e.exception))
def test_pull(self, mock_urlretrieve): bosh(["pull", "zenodo." + str(example_boutiques_tool.id)]) cache_dir = os.path.join(os.path.expanduser('~'), ".cache", "boutiques") self.assertTrue( os.path.exists( os.path.join( cache_dir, "zenodo-" + str(example_boutiques_tool.id) + ".json")))
def test_publication(self, mock_get, mock_post, mock_put, mock_delete): example1_dir = op.join(self.get_examples_dir(), "example1") example1_desc = op.join(example1_dir, "example1_docker.json") temp_descriptor = tempfile.NamedTemporaryFile(suffix=".json") shutil.copyfile(example1_desc, temp_descriptor.name) # Make sure that example1.json doesn't have a DOI yet with open(temp_descriptor.name, 'r') as fhandle: descriptor = json.load(fhandle) assert (descriptor.get('doi') is None) # Test publication of a descriptor that doesn't have a DOI doi = bosh([ "publish", temp_descriptor.name, "--sandbox", "-y", "-v", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r" ]) assert (doi) # Now descriptor should have a DOI with open(temp_descriptor.name, 'r') as fhandle: descriptor = json.load(fhandle) assert (descriptor.get('doi') == doi) # Test publication of a descriptor that already has a DOI with self.assertRaises(ZenodoError) as e: bosh([ "publish", temp_descriptor.name, "--sandbox", "-y", "-v", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r" ]) self.assertTrue("Descriptor already has a DOI" in str(e.exception)) # Test publication of an updated version of the same descriptor example1_desc_updated = op.join(example1_dir, "example1_docker_updated.json") temp_descriptor_updated = tempfile.NamedTemporaryFile(suffix=".json") shutil.copyfile(example1_desc_updated, temp_descriptor_updated.name) with open(temp_descriptor_updated.name, 'r') as fhandle: descriptor_updated = json.load(fhandle) # Publish the updated version new_doi = bosh([ "publish", temp_descriptor_updated.name, "--sandbox", "-y", "-v", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r" ]) assert (new_doi) # Updated version of descriptor should have a new DOI with open(temp_descriptor_updated.name, 'r') as fhandle: descriptor_updated = json.load(fhandle) assert (descriptor_updated.get('doi') == new_doi) assert (descriptor_updated.get('doi') != doi)
def test_success_argparser(self): parser = ArgumentParser(description="my tool description") parser.add_argument('myarg1', action="store", help="my help 1", type=list) parser.add_argument('myarg2', action="store", help="my help 2", type=int) parser.add_argument("--myarg3", "-m", action="store", help="my help 3") subparser = parser.add_subparsers(help="the choices you will make", dest="mysubparser") sb1 = subparser.add_parser("option1", help="the first value") sb1.add_argument("suboption1", help="the first sub option option") sb1.add_argument("suboption2", help="the first sub option option", choices=['hello', 'goodbye'], default="hello") sb1 = subparser.add_parser("option2", help="the second value") sb1.add_argument("suboption1", help="the first sub option option") sb1.add_argument("suboption3", help="the second sub option option") sb1.add_argument("--suboptionflag1", "-s", help="the bool opt flag") sb1.add_argument("--suboptionflag2", "-d", action="store_true", help="the second sub option flag") sb1.add_argument("--suboptlistflag", "-l", nargs="+", help="listy flag") creatorObj = bc.CreateDescriptor(parser, execname='/path/to/myscript.py', verbose=True, tags={ "purpose": "testing-creator", "foo": "bar" }) fil = './test-created-argparse-descriptor.json' creatorObj.save(fil) invof = './test-created-argparse-inputs.json' args = parser.parse_args([['val1', 'val2'], '2', 'option2', 'subval1', 'subval3', '--suboptionflag1', 't1', '--suboptionflag2']) invo = creatorObj.createInvocation(args) with open(invof, 'w') as fhandle: fhandle.write(json.dumps(invo, indent=4)) self.assertIsNone(bosh(['validate', fil])) self.assertIsNone(bosh(['invocation', fil, '-i', invof]))
def test_publish_nexus_invalid_endpoint(self, mock_dir, mock_endpoint): cleanup() setup() with self.assertRaises(NexusError) as e: bosh(["data", "publish", "-y", "--nexus", "--sandbox", "--nexus-token", "hAaW2wSBZMskxpfigTYHcuDrCPWr2", "--nexus-org", "boutiques", "--nexus-project", "test"]) self.assertIn("Cannot access Nexus endpoint", str(e.exception))
def test_publish_nexus_invalid_token(self, mock_dir): cleanup() setup() with self.assertRaises(NexusError) as e: bosh(["data", "publish", "-y", "--nexus", "--sandbox", "--nexus-token", "INVALIDTOKEN", "--nexus-org", "boutiques", "--nexus-project", "test"]) self.assertIn("Cannot authenticate to Nexus API, check " "your access token", str(e.exception))
def test_publish_nexus_success( self, mock_create_file, mock_fetch_project, mock_save_inputs, mock_dir): cleanup() setup() try: bosh(["data", "publish", "-y", "--nexus", "--sandbox", "--nexus-token", "hAaW2wSBZMskxpfigTYHcuDrCPWr2", "--nexus-org", "test", "--nexus-project", "test", "-v"]) except Exception as e: self.fail("Unexpected exception raised: " + str(e))
def test_publish_single(self, mock_dir, mock_get, mock_post): cleanup() setup() # Publish a record that does not exist with self.assertRaises(ValueError) as e: bosh(["data", "publish", "-f", "bad-filename", "--sandbox", "-y"]) self.assertIn("File bad-filename does not exist in the data cache", str(e.exception)) # Publish a record with a correct descriptor-doi bosh(["data", "publish", "-f", "tool1_123.json", "-y", "--sandbox", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrCPWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r"]) self.assertFalse(os.path.isfile( os.path.join(mock_get_data_cache(), "tool1-123"))) # Publish a record without a descriptor-doi bosh(["data", "publish", "-f", "tool2_123.json", "-y", "--sandbox", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrCPWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r"]) self.assertTrue(os.path.isfile( os.path.join(mock_get_data_cache(), "tool2_123.json"))) self.assertTrue(os.path.isfile( os.path.join(mock_get_data_cache(), "descriptor_tool2_123.json"))) # Publish a record without a descriptor-doi but descriptor is published bosh(["data", "publish", "-f", "tool3_123.json", "-y", "--sandbox", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrCPWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r"]) self.assertFalse(os.path.isfile( os.path.join(mock_get_data_cache(), "tool3-123"))) self.assertFalse(os.path.isfile( os.path.join(mock_get_data_cache(), "descriptor-tool3-123")))
def test_publisher_auth_no_permission(self, mock_get, mock_post): example1_dir = op.join(self.get_examples_dir(), "example1") # Trying to update a tool published by a different # user should inform the user that they do not # have permission to publish an update. with self.assertRaises(ZenodoError) as e: bosh([ "publish", op.join(example1_dir, "example1_docker.json"), "--sandbox", "--id", "zenodo.12345", "-y", "-v", "--zenodo-token", "12345" ]) self.assertIn("You do not have permission to access this " "resource.", str(e.exception))
def test_search_sorts_by_num_downloads(self, mock_get): results = bosh(["search"]) downloads = [] for r in results: downloads.append(r["DOWNLOADS"]) assert (all(downloads[i] >= downloads[i + 1] for i in range(len(downloads) - 1)))
def test_publication_replace_no_id(self, mock_get, mock_post, mock_put, mock_delete): example1_dir = op.join(self.get_examples_dir(), "example1") example1_desc = op.join(example1_dir, "example1_docker_with_doi.json") temp_descriptor = tempfile.NamedTemporaryFile(suffix=".json") shutil.copyfile(example1_desc, temp_descriptor.name) # Make sure that descriptor has a DOI with open(temp_descriptor.name, 'r') as fhandle: descriptor = json.load(fhandle) self.assertIsNotNone(descriptor.get('doi')) old_doi = descriptor['doi'] # Publish an updated version of an already published descriptor doi = bosh([ "publish", temp_descriptor.name, "--sandbox", "-y", "-v", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r", "--replace" ]) self.assertTrue(doi) # Now descriptor should have a DOI which should be different # than the old DOI with open(temp_descriptor.name, 'r') as fhandle: descriptor = json.load(fhandle) self.assertNotEqual(doi, old_doi) self.assertEqual(descriptor.get('doi'), doi)
def test_search_truncates_long_text(self, mymockget): mymockget.side_effect = lambda *args, **kwargs:\ mock_get("boutiques", False, *args, **kwargs) results = bosh(["search"]) for r in results: for k, v in r.items(): self.assertLessEqual(len(str(v)), 43)
def test_search_exact_match(self, mock_get): results = bosh(["search", "Example Tool 5", "--exact"]) print(results) assert (len(results) > 0) assert (any(d['TITLE'] == 'Example Tool 5' for d in results)) assert (not any(d['TITLE'] == 'foo-Example Tool 5' for d in results)) assert (not any(d['TITLE'] == 'Example Tool 5-bar' for d in results))
def test_failing_simulate(self): example1_dir = os.path.join(self.get_examples_dir(), "example1") self.assertRaises(SystemExit, bosh, [ "exec", "simulate", os.path.join(example1_dir, "fake.json"), "-i", os.path.join(example1_dir, "invocation.json") ]) self.assertRaises(SystemExit, bosh, [ "exec", "simulate", os.path.join(example1_dir, "example1.json"), "-i", os.path.join(example1_dir, "fake.json") ]) self.assertRaises(SystemExit, bosh, [ "exec", "simulate", os.path.join(example1_dir, "example1.json"), "-i", os.path.join(example1_dir, "exampleTool1.py") ]) self.assertRaises(SystemExit, bosh, [ "exec", "simulate", os.path.join(example1_dir, "example1.json"), "-r", "-2" ]) self.assertFalse( bosh([ "exec", "simulate", os.path.join(example1_dir, "example1.json"), "-r", "1" ])) self.assertRaises(SystemExit, bosh, [ "exec", "simulate", os.path.join(example1_dir, "example1.json"), "-r", "1", "-i", os.path.join(example1_dir, "invocation.json") ]) self.assertRaises( SystemExit, bosh, ["exec", "simulate", os.path.join(example1_dir, "example1.json")])
def test_search_verbose(self): results = bosh(["search", "-v"]) assert(len(results) > 0) assert(list(results[0].keys()) == ["ID", "TITLE", "DESCRIPTION", "AUTHOR", "VERSION", "DOI", "SCHEMA VERSION", "CONTAINER", "TAGS"])
def test_search_all(self, mymockget): mymockget.side_effect = lambda *args, **kwargs:\ mock_get("", False, *args, **kwargs) results = bosh(["search"]) self.assertGreater(len(results), 0) self.assertEqual(list(results[0].keys()), ["ID", "TITLE", "DESCRIPTION", "DOWNLOADS"])
def test_search_exact_match(self, mymockget): mymockget.side_effect = lambda *args, **kwargs:\ mock_get("Example Tool 5", True, *args, **kwargs) results = bosh(["search", "Example Tool 5", "--exact"]) self.assertGreater(len(results), 0) self.assertIn('Example Tool 5', [d['TITLE'] for d in results]) self.assertNotIn('foo-Example Tool 5', [d['TITLE'] for d in results]) self.assertNotIn('Example Tool 5-bar', [d['TITLE'] for d in results])
def test_search_sorts_by_num_downloads(self, mymockget): mymockget.side_effect = lambda *args, **kwargs:\ mock_get("boutiques", False, *args, **kwargs) results = bosh(["search"]) downloads = [] for r in results: downloads.append(r["DOWNLOADS"]) self.assertEqual(sorted(downloads, reverse=True), downloads)
def test_deprecate(self, *args): new_doi = bosh([ "deprecate", "--verbose", "--by", "zenodo.12345", "zenodo." + str(example_boutiques_tool.id), "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r" ]) self.assertTrue(new_doi)
def test_deprecate_by_inexistent(self, *args): with self.assertRaises(DeprecateError) as e: new_doi = bosh([ "deprecate", "--verbose", "--by", "zenodo.00000", "zenodo." + str(example_boutiques_tool.id), "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r" ]) self.assertTrue("Tool does not exist" in str(e.exception))
def test_search_verbose(self, mymockget): mymockget.side_effect = lambda *args, **kwargs:\ mock_get("", False, *args, **kwargs) results = bosh(["search", "-v"]) self.assertGreater(len(results), 0) self.assertEqual(list(results[0].keys()), [ "ID", "TITLE", "DESCRIPTION", "DOWNLOADS", "AUTHOR", "VERSION", "DOI", "SCHEMA VERSION", "CONTAINER", "TAGS" ])
def test_deprecate_previous_version(self, *args): with self.assertRaises(DeprecateError) as e: new_doi = bosh([ "deprecate", "--verbose", "zenodo.22222", "--zenodo-token", "hAaW2wSBZMskxpfigTYHcuDrC" "PWr2VeQZgBLErKbfF5RdrKhzzJi8i2hnN8r" ]) self.assertTrue( "Tool zenodo.22222 has a newer version" in str(e.exception))
def test_publisher_auth(self, mock_get): example1_dir = op.join(self.get_examples_dir(), "example1") # Bad token should fail with self.assertRaises(ZenodoError) as e: bosh([ "publish", op.join(example1_dir, "example1_docker.json"), "--sandbox", "-y", "-v", "--zenodo-token", "12345" ]) self.assertIn("Cannot authenticate to Zenodo", str(e.exception)) # No token should fail with self.assertRaises(ZenodoError) as e: bosh([ "publish", op.join(example1_dir, "example1_docker.json"), "--sandbox", "-y", "-v" ]) self.assertIn("Cannot authenticate to Zenodo", str(e.exception))
def test_success_template_camel_case(self): template = './boutiques/templates/basic.json' fil = 'creator_output.json' bosh(['create', fil, '--camel-case']) self.assertIsNone(bosh(['validate', fil])) desc = loadJson(fil) template = loadJson(template) # Check "_" in all instances of input indices (inputs + groups) for inp, camelInp in zip(template['inputs'], desc['inputs']): self.assertTrue("_" in inp['id']) self.assertFalse("_" in camelInp['id']) for mbrs, camelMbrs in [ (grp['members'], camelGrp['members']) for grp, camelGrp in zip(template['groups'], desc['groups']) ]: self.assertTrue(all([("_" in mbr) for mbr in mbrs])) self.assertFalse(all([("_" in camelMbr) for camelMbr in camelMbrs]))