def test_normcase_registration(self): # create an empty working set for a clean-slate test. cwd = utils.mkdtemp(self) mock_ws = WorkingSet([]) dist_ = Distribution(cwd, project_name='pkg', version='1.0') dist_.egg_info = cwd # just lazy registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) # case sensitive test; have to patch the normcase at artifact # module with the nt version from ntpath import normcase as nt_normcase utils.stub_item_attr_value(self, artifact, 'normcase', nt_normcase) # using named case for case sensitivity test. c1 = EntryPoint.parse('case.js = dummy_builder:builder1') c1.dist = dist_ c2 = EntryPoint.parse('Case.js = dummy_builder:builder2') c2.dist = dist_ # use the error one ct = join(cwd, 'calmjs_artifacts', 'Case.js') with pretty_logging(stream=mocks.StringIO()) as stream: registry.register_entry_point(c1) registry.register_entry_point(c2) log = stream.getvalue() self.assertIn( "entry point 'Case.js = dummy_builder:builder2' from package " "'pkg 1.0' resolves to the path '%s' which was already " "registered to entry point 'case.js = dummy_builder:builder1'; " "conflicting entry point registration will be ignored." % ct, log) self.assertIn( "the file mapping error is caused by this platform's case-" "insensitive filename", log)
def test_conflict_registration(self): # create an empty working set for a clean-slate test. cwd = utils.mkdtemp(self) mock_ws = WorkingSet([]) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) # using named case for case sensitivity test. st = join(cwd, 'calmjs_artifacts', 'Simple.js') dist_ = Distribution(cwd, project_name='pkg', version='1.0') dist_.egg_info = cwd # just lazy s1 = EntryPoint.parse('Simple.js = dummy_builder:builder1') s1.dist = dist_ s2 = EntryPoint.parse('Simple.js = dummy_builder:builder2') s2.dist = dist_ with pretty_logging(stream=mocks.StringIO()) as stream: registry.register_entry_point(s1) # normal registry usage shouldn't be able to do this. registry.register_entry_point(s2) log = stream.getvalue() self.assertIn( "entry point 'Simple.js = dummy_builder:builder2' from package " "'pkg 1.0' resolves to the path '%s' which was already " "registered to entry point 'Simple.js = dummy_builder:builder1'; " "conflicting entry point registration will be ignored." % st, log )
def test_iter_builders_side_effect(self): # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.complete = generic_builder self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'artifact.js = calmjs_testing_dummy:complete', ])), ), 'app', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) registry.update_artifact_metadata('app', {}) root = join(working_dir, 'app-1.0.egg-info', 'calmjs_artifacts') self.assertFalse(exists(root)) ep, toolchain, spec = next(registry.iter_builders_for('app')) self.assertFalse(exists(root)) # directory only created after the toolchain is executed toolchain(spec) self.assertTrue(exists(root))
def test_iter_builders_side_effect(self): # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.complete = generic_builder self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'artifact.js = calmjs_testing_dummy:complete', ])), ), 'app', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) registry.update_artifact_metadata('app', {}) root = join(working_dir, 'app-1.0.egg-info', 'calmjs_artifacts') self.assertFalse(exists(root)) ep, toolchain, spec = next(registry.iter_builders_for('app')) self.assertFalse(exists(root)) # directory only created after the toolchain is executed toolchain(spec) self.assertTrue(exists(root))
def test_iter_builders_side_effect_build_issue(self): mod = ModuleType('calmjs_testing_dummy') mod.complete = generic_builder self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'artifact.js = calmjs_testing_dummy:complete', ])), ), 'app', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) registry.update_artifact_metadata('app', {}) root = join(working_dir, 'app-1.0.egg-info', 'calmjs_artifacts') # clog the build directory so build cannot happen with open(join(root), 'w'): pass ep, toolchain, spec = next(registry.iter_builders_for('app')) check = [] spec.advise('after_prepare', check.append, True) with pretty_logging(stream=mocks.StringIO()) as stream: with self.assertRaises(ToolchainAbort): toolchain(spec) self.assertIn( "an advice in group 'before_prepare' triggered an abort", stream.getvalue()) # should have stopped at before_prepare self.assertFalse(check)
def test_update_artifact_metadata(self): # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.complete = generic_builder self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ 'calmjs', ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'artifact.js = calmjs_testing_dummy:complete', ])), ), 'app', '1.0', working_dir=working_dir) # mock a version of calmjs within that environment too utils.make_dummy_dist(self, ( ('entry_points.txt', ''), ), 'calmjs', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) registry.update_artifact_metadata('app', {}) self.assertTrue(exists(registry.metadata.get('app'))) with pretty_logging(stream=mocks.StringIO()) as s: registry.update_artifact_metadata('calmjs', {}) self.assertIn( "package 'calmjs' has not declare any artifacts", s.getvalue())
def test_normcase_registration(self): # create an empty working set for a clean-slate test. cwd = utils.mkdtemp(self) mock_ws = WorkingSet([]) dist_ = Distribution(cwd, project_name='pkg', version='1.0') dist_.egg_info = cwd # just lazy registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) # case sensitive test; have to patch the normcase at artifact # module with the nt version from ntpath import normcase as nt_normcase utils.stub_item_attr_value(self, artifact, 'normcase', nt_normcase) # using named case for case sensitivity test. c1 = EntryPoint.parse('case.js = dummy_builder:builder1') c1.dist = dist_ c2 = EntryPoint.parse('Case.js = dummy_builder:builder2') c2.dist = dist_ # use the error one ct = join(cwd, 'calmjs_artifacts', 'Case.js') with pretty_logging(stream=mocks.StringIO()) as stream: registry.register_entry_point(c1) registry.register_entry_point(c2) log = stream.getvalue() self.assertIn( "entry point 'Case.js = dummy_builder:builder2' from package " "'pkg 1.0' resolves to the path '%s' which was already " "registered to entry point 'case.js = dummy_builder:builder1'; " "conflicting entry point registration will be ignored." % ct, log ) self.assertIn( "the file mapping error is caused by this platform's case-" "insensitive filename", log )
def test_denormalized_package_names(self): working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', ])), ), 'de_normal_name', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) # stub the default working set in calmjs.dist for the resolver # to work. utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) # still specify the working set. registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) self.assertEqual( 1, len(list(registry.iter_records_for('de_normal_name')))) # also test internal consistency self.assertIn('de_normal_name', registry.compat_builders['full']) self.assertIn('de_normal_name', registry.packages) default = registry.get_artifact_filename('de_normal_name', 'full.js') normal = registry.get_artifact_filename(safe_name('de_normal_name'), 'full.js') self.assertEqual(default, normal)
def test_iter_builders_side_effect_build_issue(self): mod = ModuleType('calmjs_testing_dummy') mod.complete = generic_builder self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'artifact.js = calmjs_testing_dummy:complete', ])), ), 'app', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) registry.update_artifact_metadata('app', {}) root = join(working_dir, 'app-1.0.egg-info', 'calmjs_artifacts') # clog the build directory so build cannot happen with open(join(root), 'w'): pass ep, toolchain, spec = next(registry.iter_builders_for('app')) check = [] spec.advise('after_prepare', check.append, True) with pretty_logging(stream=mocks.StringIO()) as stream: with self.assertRaises(ToolchainAbort): toolchain(spec) self.assertIn("an advice in group 'before_prepare' triggered an abort", stream.getvalue()) # should have stopped at before_prepare self.assertFalse(check)
def test_conflict_registration(self): # create an empty working set for a clean-slate test. cwd = utils.mkdtemp(self) mock_ws = WorkingSet([]) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) # using named case for case sensitivity test. st = join(cwd, 'calmjs_artifacts', 'Simple.js') dist_ = Distribution(cwd, project_name='pkg', version='1.0') dist_.egg_info = cwd # just lazy s1 = EntryPoint.parse('Simple.js = dummy_builder:builder1') s1.dist = dist_ s2 = EntryPoint.parse('Simple.js = dummy_builder:builder2') s2.dist = dist_ with pretty_logging(stream=mocks.StringIO()) as stream: registry.register_entry_point(s1) # normal registry usage shouldn't be able to do this. registry.register_entry_point(s2) log = stream.getvalue() self.assertIn( "entry point 'Simple.js = dummy_builder:builder2' from package " "'pkg 1.0' resolves to the path '%s' which was already " "registered to entry point 'Simple.js = dummy_builder:builder1'; " "conflicting entry point registration will be ignored." % st, log)
def test_update_artifact_metadata(self): # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.complete = generic_builder self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ 'calmjs', ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'artifact.js = calmjs_testing_dummy:complete', ])), ), 'app', '1.0', working_dir=working_dir) # mock a version of calmjs within that environment too utils.make_dummy_dist(self, (('entry_points.txt', ''), ), 'calmjs', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) registry.update_artifact_metadata('app', {}) self.assertTrue(exists(registry.metadata.get('app'))) with pretty_logging(stream=mocks.StringIO()) as s: registry.update_artifact_metadata('calmjs', {}) self.assertIn("package 'calmjs' has not declare any artifacts", s.getvalue())
def test_denormalized_package_names(self): working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', ])), ), 'de_normal_name', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) # stub the default working set in calmjs.dist for the resolver # to work. utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) # still specify the working set. registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) self.assertEqual( 1, len(list(registry.iter_records_for('de_normal_name')))) # also test internal consistency self.assertIn('de_normal_name', registry.compat_builders['full']) self.assertIn('de_normal_name', registry.packages) default = registry.get_artifact_filename('de_normal_name', 'full.js') normal = registry.get_artifact_filename( safe_name('de_normal_name'), 'full.js') self.assertEqual(default, normal)
def test_calmjs_artifact_declarations(self): from calmjs.registry import _inst # the actual implementations this is supporting from calmjs.artifact import build_calmjs_artifacts from calmjs.artifact import ArtifactRegistry working_dir = mkdtemp(self) make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.registry]', 'calmjs.artifacts = calmjs.artifact:ArtifactsRegistry', ])), ), 'calmjs', '1.0', working_dir=working_dir) make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'example.js = example:builder', ])), ), 'some.package', '1.0', working_dir=working_dir) mock_ws = pkg_resources.WorkingSet([working_dir]) registry_id = 'calmjs.artifacts' registry = ArtifactRegistry(registry_id, _working_set=mock_ws) # cleanup the about to be injected version. self.addCleanup(_inst.records.pop, registry_id, None) _inst.records['calmjs.artifacts'] = registry # construct a command for the declaration check. cmd = build_calmjs_artifacts(dist=distutils_dist.Distribution( attrs={'name': 'some.package'})) self.assertTrue(calmjs_dist.has_calmjs_artifact_declarations(cmd)) cmd = build_calmjs_artifacts(dist=distutils_dist.Distribution( attrs={'name': 'missing.package'})) self.assertFalse(calmjs_dist.has_calmjs_artifact_declarations(cmd)) cmd = build_calmjs_artifacts(dist=distutils_dist.Distribution( attrs={'name': 'calmjs'})) self.assertFalse(calmjs_dist.has_calmjs_artifact_declarations(cmd))
class ArtifactRegistryBuildFailureTestCase(unittest.TestCase): """ Test out various build failure cases. """ def setUp(self): # bad dummy builder def bad_builder(): "Wrong function signature" # produces wrong output def malformed_builder(package_names, export_target): "does not produce an artifact" return NullToolchain() def blank_spec(package_names, export_target): "does not produce an artifact" return NullToolchain(), Spec() # nothing dummy builder def nothing_builder(package_names, export_target): "does not produce an artifact" return NullToolchain(), Spec(export_target=export_target) # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.bad_builder = bad_builder mod.nothing_builder = nothing_builder mod.malformed_builder = malformed_builder mod.blank_spec = blank_spec self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'not_exist.js = calmjs_testing_dummy:not_exist', 'bad.js = calmjs_testing_dummy:bad_builder', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'app', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'bad.js = calmjs_testing_dummy:bad_builder', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'bad', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'malformed.js = calmjs_testing_dummy:malformed_builder', ])), ), 'malformed', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'blank.js = calmjs_testing_dummy:blank_spec', ])), ), 'blank', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'nothing', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) self.registry = ArtifactRegistry( 'calmjs.artifacts', _working_set=mock_ws) def test_build_artifacts_logs_and_failures(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('app') log = stream.getvalue() self.assertIn( "unable to import the target builder for the entry point " "'not_exist.js = calmjs_testing_dummy:not_exist' from package " "'app 1.0'", log ) self.assertIn( "the builder referenced by the entry point " "'bad.js = calmjs_testing_dummy:bad_builder' from package " "'app 1.0' has an incompatible signature", log ) # try again using the artifact builder from calmjs.registry import _inst _inst.records.pop('calmjs.artifacts', None) self.addCleanup(_inst.records.pop, 'calmjs.artifacts') _inst.records['calmjs.artifacts'] = self.registry builder = ArtifactBuilder('calmjs.artifacts') with pretty_logging(stream=mocks.StringIO()) as stream: self.assertFalse(builder(['app'])) log = stream.getvalue() self.assertIn( "unable to import the target builder for the entry point " "'not_exist.js = calmjs_testing_dummy:not_exist' from package " "'app 1.0'", log ) def test_existing_removed(self): # force an existing file target = self.registry.records[('app', 'nothing.js')] os.mkdir(dirname(target)) with open(target, 'w'): pass with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('app') log = stream.getvalue() self.assertIn( "package 'app' has declared 3 entry points for the " "'calmjs.artifacts' registry for artifact construction", log ) log = stream.getvalue() self.assertIn("removing existing export target at ", log) self.assertFalse(exists(target)) def test_grandparent_not_removed(self): with open(dirname(self.registry.records[('bad', 'bad.js')]), 'w'): pass with self.assertRaises(ToolchainAbort): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('bad') log = stream.getvalue() self.assertIn("its dirname does not lead to a directory", log) def test_malformed_builder_handling(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('malformed') log = stream.getvalue() self.assertIn("failed to produce a valid toolchain", log) def test_spec_missing_export_path_handling(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('blank') log = stream.getvalue() self.assertIn( "failed to produce a spec with the expected export_target", log) def test_artifact_generation_failure(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('nothing') log = stream.getvalue() self.assertIn( "the entry point " "'nothing.js = calmjs_testing_dummy:nothing_builder' from package " "'nothing 1.0' failed to generate an artifact", log ) def test_no_declaration(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('undeclared') log = stream.getvalue() self.assertIn( "package 'undeclared' has not declared any entry points for the " "'calmjs.artifacts' registry for artifact construction", log ) def test_artifact_metadata_malformed(self): with open(self.registry.metadata.get('app'), 'w') as fd: fd.write('{{{invalidjson') self.assertEqual({}, self.registry.get_artifact_metadata('app'))
def test_build_artifacts_success(self): # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.extra = generic_builder mod.complete = generic_builder mod.partial = generic_builder self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ 'calmjs', ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'artifact.js = calmjs_testing_dummy:complete', 'partial.js = calmjs_testing_dummy:partial', ])), ), 'app', '1.0', working_dir=working_dir) # mock a version of calmjs within that environment too utils.make_dummy_dist(self, (('entry_points.txt', ''), ), 'calmjs', '1.0', working_dir=working_dir) def version(bin_path, version_flag='-v', kw={}): return '0.0.0' mock_ws = WorkingSet([working_dir]) utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) utils.stub_item_attr_value(self, artifact, 'get_bin_version_str', version) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) # quick check of the artifact metadata beforehand self.assertEqual({}, registry.get_artifact_metadata('app')) registry.process_package('app') complete = list( registry.resolve_artifacts_by_builder_compat(['app'], 'complete')) partial = list( registry.resolve_artifacts_by_builder_compat(['app'], 'partial')) self.assertEqual(len(complete), 1) self.assertEqual(len(partial), 1) self.assertEqual(basename(complete[0]), 'artifact.js') self.assertEqual(basename(partial[0]), 'partial.js') with open(complete[0]) as fd: self.assertEqual(fd.read(), 'app') with open(partial[0]) as fd: self.assertEqual(fd.read(), 'app') self.assertEqual( { 'calmjs_artifacts': { 'artifact.js': { 'builder': 'calmjs_testing_dummy:complete', 'toolchain_bases': [{ 'calmjs.testing.artifact:ArtifactToolchain': { 'project_name': 'calmjs', 'version': '1.0', } }, { 'calmjs.toolchain:NullToolchain': { 'project_name': 'calmjs', 'version': '1.0', } }, { 'calmjs.toolchain:Toolchain': { 'project_name': 'calmjs', 'version': '1.0', } }], 'toolchain_bin': ['artifact', '0.0.0'], }, 'partial.js': { 'builder': 'calmjs_testing_dummy:partial', 'toolchain_bases': [{ 'calmjs.testing.artifact:ArtifactToolchain': { 'project_name': 'calmjs', 'version': '1.0' } }, { 'calmjs.toolchain:NullToolchain': { 'project_name': 'calmjs', 'version': '1.0', } }, { 'calmjs.toolchain:Toolchain': { 'project_name': 'calmjs', 'version': '1.0', } }], 'toolchain_bin': ['artifact', '0.0.0'], } }, 'versions': [ 'app 1.0', 'calmjs 1.0', ] }, registry.get_artifact_metadata('app')) # test that the 'calmjs_artifacts' listing only grows - the only # way to clean this is to remove and rebuild egg-info directly. utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'extra.js = calmjs_testing_dummy:extra', ])), ), 'app', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) utils.stub_item_attr_value(self, artifact, 'get_bin_version_str', version) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) registry.process_package('app') self.assertEqual( 3, len(registry.get_artifact_metadata('app')['calmjs_artifacts'])) self.assertIn( 'extra.js', registry.get_artifact_metadata('app')['calmjs_artifacts']) # try again using the artifact builder from calmjs.registry import _inst _inst.records.pop('calmjs.artifacts', None) self.addCleanup(_inst.records.pop, 'calmjs.artifacts') _inst.records['calmjs.artifacts'] = registry builder = ArtifactBuilder('calmjs.artifacts') self.assertTrue(builder(['app']))
def test_build_artifacts_success(self): # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.extra = generic_builder mod.complete = generic_builder mod.partial = generic_builder self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ 'calmjs', ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'artifact.js = calmjs_testing_dummy:complete', 'partial.js = calmjs_testing_dummy:partial', ])), ), 'app', '1.0', working_dir=working_dir) # mock a version of calmjs within that environment too utils.make_dummy_dist(self, ( ('entry_points.txt', ''), ), 'calmjs', '1.0', working_dir=working_dir) def version(bin_path, version_flag='-v', kw={}): return '0.0.0' mock_ws = WorkingSet([working_dir]) utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) utils.stub_item_attr_value( self, artifact, 'get_bin_version_str', version) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) # quick check of the artifact metadata beforehand self.assertEqual({}, registry.get_artifact_metadata('app')) registry.process_package('app') complete = list(registry.resolve_artifacts_by_builder_compat( ['app'], 'complete')) partial = list(registry.resolve_artifacts_by_builder_compat( ['app'], 'partial')) self.assertEqual(len(complete), 1) self.assertEqual(len(partial), 1) self.assertEqual(basename(complete[0]), 'artifact.js') self.assertEqual(basename(partial[0]), 'partial.js') with open(complete[0]) as fd: self.assertEqual(fd.read(), 'app') with open(partial[0]) as fd: self.assertEqual(fd.read(), 'app') self.assertEqual({ 'calmjs_artifacts': { 'artifact.js': { 'builder': 'calmjs_testing_dummy:complete', 'toolchain_bases': [ {'calmjs.testing.artifact:ArtifactToolchain': { 'project_name': 'calmjs', 'version': '1.0', }}, {'calmjs.toolchain:NullToolchain': { 'project_name': 'calmjs', 'version': '1.0', }}, {'calmjs.toolchain:Toolchain': { 'project_name': 'calmjs', 'version': '1.0', }} ], 'toolchain_bin': ['artifact', '0.0.0'], }, 'partial.js': { 'builder': 'calmjs_testing_dummy:partial', 'toolchain_bases': [ {'calmjs.testing.artifact:ArtifactToolchain': { 'project_name': 'calmjs', 'version': '1.0'}}, {'calmjs.toolchain:NullToolchain': { 'project_name': 'calmjs', 'version': '1.0', }}, {'calmjs.toolchain:Toolchain': { 'project_name': 'calmjs', 'version': '1.0', }} ], 'toolchain_bin': ['artifact', '0.0.0'], } }, 'versions': [ 'app 1.0', 'calmjs 1.0', ] }, registry.get_artifact_metadata('app')) # test that the 'calmjs_artifacts' listing only grows - the only # way to clean this is to remove and rebuild egg-info directly. utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'extra.js = calmjs_testing_dummy:extra', ])), ), 'app', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) utils.stub_item_attr_value( self, artifact, 'get_bin_version_str', version) registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) registry.process_package('app') self.assertEqual(3, len(registry.get_artifact_metadata('app')[ 'calmjs_artifacts'])) self.assertIn('extra.js', registry.get_artifact_metadata('app')[ 'calmjs_artifacts']) # try again using the artifact builder from calmjs.registry import _inst _inst.records.pop('calmjs.artifacts', None) self.addCleanup(_inst.records.pop, 'calmjs.artifacts') _inst.records['calmjs.artifacts'] = registry builder = ArtifactBuilder('calmjs.artifacts') self.assertTrue(builder(['app']))
def setUp(self): # bad dummy builder def bad_builder(): "Wrong function signature" # produces wrong output def malformed_builder(package_names, export_target): "does not produce an artifact" return NullToolchain() def blank_spec(package_names, export_target): "does not produce an artifact" return NullToolchain(), Spec() # nothing dummy builder def nothing_builder(package_names, export_target): "does not produce an artifact" return NullToolchain(), Spec(export_target=export_target) # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.bad_builder = bad_builder mod.nothing_builder = nothing_builder mod.malformed_builder = malformed_builder mod.blank_spec = blank_spec self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'not_exist.js = calmjs_testing_dummy:not_exist', 'bad.js = calmjs_testing_dummy:bad_builder', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'app', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'bad.js = calmjs_testing_dummy:bad_builder', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'bad', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'malformed.js = calmjs_testing_dummy:malformed_builder', ])), ), 'malformed', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'blank.js = calmjs_testing_dummy:blank_spec', ])), ), 'blank', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'nothing', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) self.registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws)
class ArtifactRegistryBuildFailureTestCase(unittest.TestCase): """ Test out various build failure cases. """ def setUp(self): # bad dummy builder def bad_builder(): "Wrong function signature" # produces wrong output def malformed_builder(package_names, export_target): "does not produce an artifact" return NullToolchain() def blank_spec(package_names, export_target): "does not produce an artifact" return NullToolchain(), Spec() # nothing dummy builder def nothing_builder(package_names, export_target): "does not produce an artifact" return NullToolchain(), Spec(export_target=export_target) # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.bad_builder = bad_builder mod.nothing_builder = nothing_builder mod.malformed_builder = malformed_builder mod.blank_spec = blank_spec self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'not_exist.js = calmjs_testing_dummy:not_exist', 'bad.js = calmjs_testing_dummy:bad_builder', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'app', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'bad.js = calmjs_testing_dummy:bad_builder', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'bad', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'malformed.js = calmjs_testing_dummy:malformed_builder', ])), ), 'malformed', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'blank.js = calmjs_testing_dummy:blank_spec', ])), ), 'blank', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, (('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'nothing', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) self.registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) def test_build_artifacts_logs_and_failures(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('app') log = stream.getvalue() self.assertIn( "unable to import the target builder for the entry point " "'not_exist.js = calmjs_testing_dummy:not_exist' from package " "'app 1.0'", log) self.assertIn( "the builder referenced by the entry point " "'bad.js = calmjs_testing_dummy:bad_builder' from package " "'app 1.0' has an incompatible signature", log) # try again using the artifact builder from calmjs.registry import _inst _inst.records.pop('calmjs.artifacts', None) self.addCleanup(_inst.records.pop, 'calmjs.artifacts') _inst.records['calmjs.artifacts'] = self.registry builder = ArtifactBuilder('calmjs.artifacts') with pretty_logging(stream=mocks.StringIO()) as stream: self.assertFalse(builder(['app'])) log = stream.getvalue() self.assertIn( "unable to import the target builder for the entry point " "'not_exist.js = calmjs_testing_dummy:not_exist' from package " "'app 1.0'", log) def test_existing_removed(self): # force an existing file target = self.registry.records[('app', 'nothing.js')] os.mkdir(dirname(target)) with open(target, 'w'): pass with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('app') log = stream.getvalue() self.assertIn( "package 'app' has declared 3 entry points for the " "'calmjs.artifacts' registry for artifact construction", log) log = stream.getvalue() self.assertIn("removing existing export target at ", log) self.assertFalse(exists(target)) def test_grandparent_not_removed(self): with open(dirname(self.registry.records[('bad', 'bad.js')]), 'w'): pass with self.assertRaises(ToolchainAbort): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('bad') log = stream.getvalue() self.assertIn("its dirname does not lead to a directory", log) def test_malformed_builder_handling(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('malformed') log = stream.getvalue() self.assertIn("failed to produce a valid toolchain", log) def test_spec_missing_export_path_handling(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('blank') log = stream.getvalue() self.assertIn( "failed to produce a spec with the expected export_target", log) def test_artifact_generation_failure(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('nothing') log = stream.getvalue() self.assertIn( "the entry point " "'nothing.js = calmjs_testing_dummy:nothing_builder' from package " "'nothing 1.0' failed to generate an artifact", log) def test_no_declaration(self): with pretty_logging(stream=mocks.StringIO()) as stream: self.registry.process_package('undeclared') log = stream.getvalue() self.assertIn( "package 'undeclared' has not declared any entry points for the " "'calmjs.artifacts' registry for artifact construction", log) def test_artifact_metadata_malformed(self): with open(self.registry.metadata.get('app'), 'w') as fd: fd.write('{{{invalidjson') self.assertEqual({}, self.registry.get_artifact_metadata('app'))
def setUp(self): # bad dummy builder def bad_builder(): "Wrong function signature" # produces wrong output def malformed_builder(package_names, export_target): "does not produce an artifact" return NullToolchain() def blank_spec(package_names, export_target): "does not produce an artifact" return NullToolchain(), Spec() # nothing dummy builder def nothing_builder(package_names, export_target): "does not produce an artifact" return NullToolchain(), Spec(export_target=export_target) # inject dummy module and add cleanup mod = ModuleType('calmjs_testing_dummy') mod.bad_builder = bad_builder mod.nothing_builder = nothing_builder mod.malformed_builder = malformed_builder mod.blank_spec = blank_spec self.addCleanup(sys.modules.pop, 'calmjs_testing_dummy') sys.modules['calmjs_testing_dummy'] = mod working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'not_exist.js = calmjs_testing_dummy:not_exist', 'bad.js = calmjs_testing_dummy:bad_builder', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'app', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'bad.js = calmjs_testing_dummy:bad_builder', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'bad', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'malformed.js = calmjs_testing_dummy:malformed_builder', ])), ), 'malformed', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'blank.js = calmjs_testing_dummy:blank_spec', ])), ), 'blank', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'nothing.js = calmjs_testing_dummy:nothing_builder', ])), ), 'nothing', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) self.registry = ArtifactRegistry( 'calmjs.artifacts', _working_set=mock_ws)
def test_basic(self): working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', 'base.lib.js = calmjs_testbuild:lib', ])), ), 'base', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ 'base', ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', 'lib1.lib.js = calmjs_testbuild:lib', ])), ), 'lib1', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ 'base', ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', 'lib2.lib.js = calmjs_testbuild_extended:lib', ])), ), 'lib2', '1.0', working_dir=working_dir) utils.make_dummy_dist( self, ( ('requires.txt', '\n'.join([ 'lib1', 'lib2', ])), ( 'entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', # this one doesn't provided a standalone library ])), ), 'app1', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) # stub the default working set in calmjs.dist for the resolver # to work. utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) # still specify the working set. registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) self.assertNotEqual(len(list(registry.iter_records())), 0) self.assertEqual( normcase( join(working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'lib1.lib.js')), normcase(registry.get_artifact_filename('lib1', 'lib1.lib.js')), ) self.assertEqual([], list( registry.resolve_artifacts_by_builder_compat( ['no_such_package'], 'full'))) self.assertEqual([], list( registry.resolve_artifacts_by_builder_compat( ['lib1'], 'no_such_rule'))) self.assertPathsEqual([ join(working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'full.js'), ], list(registry.resolve_artifacts_by_builder_compat(['lib1'], 'full'))) self.assertPathsEqual([ join(working_dir, 'base-1.0.egg-info', 'calmjs_artifacts', 'base.lib.js'), join(working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'lib1.lib.js'), ], list( registry.resolve_artifacts_by_builder_compat( ['lib1'], 'lib', dependencies=True))) self.assertPathsEqual([ join(working_dir, 'base-1.0.egg-info', 'calmjs_artifacts', 'base.lib.js'), join(working_dir, 'lib2-1.0.egg-info', 'calmjs_artifacts', 'lib2.lib.js'), join(working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'lib1.lib.js'), ], list( registry.resolve_artifacts_by_builder_compat( ['lib2', 'lib1'], 'lib', dependencies=True))) self.assertPathsEqual([ join(working_dir, 'base-1.0.egg-info', 'calmjs_artifacts', 'base.lib.js'), join(working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'lib1.lib.js'), join(working_dir, 'lib2-1.0.egg-info', 'calmjs_artifacts', 'lib2.lib.js'), ], list( registry.resolve_artifacts_by_builder_compat( ['app1'], 'lib', dependencies=True))) entry_point = registry.belongs_to( join( working_dir, 'base-1.0.egg-info', 'calmjs_artifacts', 'base.lib.js', )) self.assertEqual('base', entry_point.dist.project_name) self.assertEqual('base.lib.js', entry_point.name)
def test_basic(self): working_dir = utils.mkdtemp(self) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', 'base.lib.js = calmjs_testbuild:lib', ])), ), 'base', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ 'base', ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', 'lib1.lib.js = calmjs_testbuild:lib', ])), ), 'lib1', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ 'base', ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', 'lib2.lib.js = calmjs_testbuild_extended:lib', ])), ), 'lib2', '1.0', working_dir=working_dir) utils.make_dummy_dist(self, ( ('requires.txt', '\n'.join([ 'lib1', 'lib2', ])), ('entry_points.txt', '\n'.join([ '[calmjs.artifacts]', 'full.js = calmjs_testbuild:full', # this one doesn't provided a standalone library ])), ), 'app1', '1.0', working_dir=working_dir) mock_ws = WorkingSet([working_dir]) # stub the default working set in calmjs.dist for the resolver # to work. utils.stub_item_attr_value(self, dist, 'default_working_set', mock_ws) # still specify the working set. registry = ArtifactRegistry('calmjs.artifacts', _working_set=mock_ws) self.assertNotEqual(len(list(registry.iter_records())), 0) self.assertEqual( normcase(join( working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'lib1.lib.js' )), normcase(registry.get_artifact_filename('lib1', 'lib1.lib.js')), ) self.assertEqual([], list(registry.resolve_artifacts_by_builder_compat( ['no_such_package'], 'full'))) self.assertEqual([], list(registry.resolve_artifacts_by_builder_compat( ['lib1'], 'no_such_rule'))) self.assertPathsEqual([ join(working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'full.js'), ], list(registry.resolve_artifacts_by_builder_compat( ['lib1'], 'full'))) self.assertPathsEqual([ join(working_dir, 'base-1.0.egg-info', 'calmjs_artifacts', 'base.lib.js'), join(working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'lib1.lib.js'), ], list(registry.resolve_artifacts_by_builder_compat( ['lib1'], 'lib', dependencies=True))) self.assertPathsEqual([ join(working_dir, 'base-1.0.egg-info', 'calmjs_artifacts', 'base.lib.js'), join(working_dir, 'lib2-1.0.egg-info', 'calmjs_artifacts', 'lib2.lib.js'), join(working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'lib1.lib.js'), ], list(registry.resolve_artifacts_by_builder_compat( ['lib2', 'lib1'], 'lib', dependencies=True))) self.assertPathsEqual([ join(working_dir, 'base-1.0.egg-info', 'calmjs_artifacts', 'base.lib.js'), join(working_dir, 'lib1-1.0.egg-info', 'calmjs_artifacts', 'lib1.lib.js'), join(working_dir, 'lib2-1.0.egg-info', 'calmjs_artifacts', 'lib2.lib.js'), ], list(registry.resolve_artifacts_by_builder_compat( ['app1'], 'lib', dependencies=True))) entry_point = registry.belongs_to(join( working_dir, 'base-1.0.egg-info', 'calmjs_artifacts', 'base.lib.js', )) self.assertEqual('base', entry_point.dist.project_name) self.assertEqual('base.lib.js', entry_point.name)