def from_upload(cls, upload, addon, platforms, send_signal=True, source=None, is_beta=False): from olympia.addons.models import AddonFeatureCompatibility data = utils.parse_addon(upload, addon) try: license = addon.versions.latest().license_id except Version.DoesNotExist: license = None v = cls.objects.create( addon=addon, version=data['version'], license_id=license, source=source ) log.info('New version: %r (%s) from %r' % (v, v.id, upload)) # Update the add-on e10s compatibility since we're creating a new # version that may change that. e10s_compatibility = data.get('e10s_compatibility') if e10s_compatibility is not None: feature_compatibility = ( AddonFeatureCompatibility.objects.get_or_create(addon=addon)[0] ) feature_compatibility.update(e10s=e10s_compatibility) AV = ApplicationsVersions for app in data.get('apps', []): AV(version=v, min=app.min, max=app.max, application=app.id).save() if addon.type == amo.ADDON_SEARCH: # Search extensions are always for all platforms. platforms = [amo.PLATFORM_ALL.id] else: platforms = cls._make_safe_platform_files(platforms) for platform in platforms: File.from_upload(upload, v, platform, parse_data=data, is_beta=is_beta) v.disable_old_files() # After the upload has been copied to all platforms, remove the upload. storage.delete(upload.path) if send_signal: version_uploaded.send(sender=v) # Track the time it took from first upload through validation # (and whatever else) until a version was created. upload_start = utc_millesecs_from_epoch(upload.created) now = datetime.datetime.now() now_ts = utc_millesecs_from_epoch(now) upload_time = now_ts - upload_start log.info('Time for version {version} creation from upload: {delta}; ' 'created={created}; now={now}' .format(delta=upload_time, version=v, created=upload.created, now=now)) statsd.timing('devhub.version_created_from_upload', upload_time) return v
def test_version_is_not_allowed_upload_full(self): version = Version.objects.get(pk=81551) version.files.all().delete() for platform in [amo.PLATFORM_LINUX.id, amo.PLATFORM_WIN.id, amo.PLATFORM_MAC.id]: file = File(platform=platform, version=version) file.save() # The transform don't know bout my new files. version = Version.objects.get(pk=81551) assert not version.is_allowed_upload()
def _extra_version_and_file(self, status): version = Version.objects.get(id=81551) version_two = Version(addon=self.addon, license=version.license, version='1.2.3') version_two.save() file_two = File(status=status, version=version_two) file_two.save() return version_two, file_two
def create_file(self, **kwargs): addon = Addon() addon.save() ver = Version(version='0.1') ver.addon = addon ver.save() f = File(**kwargs) f.version = ver f.save() return f
def from_upload(cls, upload, addon, platforms, send_signal=True, source=None, is_beta=False): data = utils.parse_addon(upload, addon) try: license = addon.versions.latest().license_id except Version.DoesNotExist: license = None max_len = cls._meta.get_field_by_name('_developer_name')[0].max_length developer = data.get('developer_name', '')[:max_len] v = cls.objects.create( addon=addon, version=data['version'], license_id=license, _developer_name=developer, source=source ) log.info('New version: %r (%s) from %r' % (v, v.id, upload)) AV = ApplicationsVersions for app in data.get('apps', []): AV(version=v, min=app.min, max=app.max, application=app.id).save() if addon.type == amo.ADDON_SEARCH: # Search extensions are always for all platforms. platforms = [amo.PLATFORM_ALL.id] else: platforms = cls._make_safe_platform_files(platforms) for platform in platforms: File.from_upload(upload, v, platform, parse_data=data, is_beta=is_beta) v.disable_old_files() # After the upload has been copied to all platforms, remove the upload. storage.delete(upload.path) if send_signal: version_uploaded.send(sender=v) # Track the time it took from first upload through validation # (and whatever else) until a version was created. upload_start = utc_millesecs_from_epoch(upload.created) now = datetime.datetime.now() now_ts = utc_millesecs_from_epoch(now) upload_time = now_ts - upload_start log.info('Time for version {version} creation from upload: {delta}; ' 'created={created}; now={now}' .format(delta=upload_time, version=v, created=upload.created, now=now)) statsd.timing('devhub.version_created_from_upload', upload_time) return v
def test_version_is_not_allowed_upload_after_review(self): version = Version.objects.get(pk=81551) version.files.all().delete() for platform in [amo.PLATFORM_LINUX.id, amo.PLATFORM_WIN.id, amo.PLATFORM_BSD.id]: file = File(platform=platform, version=version) file.save() version = Version.objects.get(pk=81551) assert version.is_allowed_upload() version.files.all()[0].update(status=amo.STATUS_PUBLIC) # The review has started so no more uploads now. version = Version.objects.get(pk=81551) assert not version.is_allowed_upload()
def fake_file_object(self, obj, data): file_ = File( id=data['id'], created=self.handle_date(data['created']), hash=data['hash'], filename=data['filename'], is_webextension=data.get('is_webextension'), is_mozilla_signed_extension=data.get( 'is_mozilla_signed_extension'), is_restart_required=data.get('is_restart_required', False), platform=data['platform'], size=data['size'], status=data['status'], strict_compatibility=data.get('strict_compatibility', False), version=obj) file_.webext_permissions_list = data.get('webext_permissions_list', []) return file_
def test_trusted_lite_to_lite(self): upload = self.upload('extension') d = parse_addon(upload.path) self.addon.update(status=amo.STATUS_LITE, trusted=True) assert self.addon.status == amo.STATUS_LITE f = File.from_upload(upload, self.version, self.platform, parse_data=d) assert f.status == amo.STATUS_LITE
def test_trusted_public_to_public(self): upload = self.upload('extension') d = parse_addon(upload.path) self.addon.update(status=amo.STATUS_PUBLIC, trusted=True) eq_(self.addon.status, amo.STATUS_PUBLIC) f = File.from_upload(upload, self.version, self.platform, parse_data=d) eq_(f.status, amo.STATUS_PUBLIC)
def test_extract(self): upload = self.get_upload('webextension_no_id.xpi') parsed_data = parse_addon(upload, user=mock.Mock()) # Remove the permissions from the parsed data so they aren't added. pdata_permissions = parsed_data.pop('permissions') pdata_cscript = parsed_data.pop('content_scripts') file_ = File.from_upload(upload, self.version, self.platform, parsed_data=parsed_data) assert WebextPermission.objects.count() == 0 assert file_.webext_permissions_list == [] call_command('extract_permissions') file_ = File.objects.get(id=file_.id) assert WebextPermission.objects.get(file=file_) permissions_list = file_.webext_permissions_list assert len(permissions_list) == 8 assert permissions_list == [ # first 5 are 'permissions' u'http://*/*', u'https://*/*', 'bookmarks', 'made up permission', 'https://google.com/', # last 3 are 'content_scripts' matches we treat the same '*://*.mozilla.org/*', '*://*.mozilla.com/*', 'https://*.mozillians.org/*'] assert permissions_list[0:5] == pdata_permissions assert permissions_list[5:8] == [x for y in [ cs['matches'] for cs in pdata_cscript] for x in y]
def test_public_to_unreviewed(self): upload = self.upload('extension') d = parse_addon(upload.path) self.addon.update(status=amo.STATUS_PUBLIC) assert self.addon.status == amo.STATUS_PUBLIC f = File.from_upload(upload, self.version, self.platform, parse_data=d) assert f.status == amo.STATUS_AWAITING_REVIEW
def test_search_extension(self): upload = self.upload('search.xml') data = parse_addon(upload.path) file_ = File.from_upload(upload, self.version, self.platform, parsed_data=data) assert file_.filename.endswith('.xml') assert file_.no_restart
def test_public_to_unreviewed(self): upload = self.upload('extension') d = parse_addon(upload.path) self.addon.update(status=amo.STATUS_PUBLIC) eq_(self.addon.status, amo.STATUS_PUBLIC) f = File.from_upload(upload, self.version, self.platform, parse_data=d) eq_(f.status, amo.STATUS_UNREVIEWED)
def test_lite_to_unreviewed(self): upload = self.upload('extension') d = parse_addon(upload.path) self.addon.update(status=amo.STATUS_LITE) assert self.addon.status == amo.STATUS_LITE f = File.from_upload(upload, self.version, self.platform, parse_data=d) assert f.status == amo.STATUS_UNREVIEWED
def test_beta_version_non_public(self): # Only public add-ons can get beta versions. upload = self.upload('beta-extension') d = parse_addon(upload.path) self.addon.update(status=amo.STATUS_LITE) assert self.addon.status == amo.STATUS_LITE f = File.from_upload(upload, self.version, self.platform, parse_data=d) assert f.status == amo.STATUS_UNREVIEWED
def test_mozilla_signed_extension(self): upload = self.upload('webextension_signed_already') file_ = File.from_upload( upload, self.version, parsed_data={'is_mozilla_signed_extension': True}, ) assert file_.is_mozilla_signed_extension
def test_not_mozilla_signed_extension(self): upload = self.upload('webextension.xpi') file_ = File.from_upload( upload, self.version, parsed_data={'is_mozilla_signed_extension': False}, ) assert not file_.is_mozilla_signed_extension
def test_webextension(self): self.create_switch('webextensions') upload = self.upload('webextension') file_ = File.from_upload(upload, self.version, self.platform, parse_data={'is_webextension': True}) assert file_.is_webextension
def test_file_is_copied_to_current_path_at_upload(self): upload = self.upload('webextension') file_ = File.from_upload(upload, self.version, parsed_data={'is_webextension': True}) assert os.path.exists(file_.file_path) assert not os.path.exists(file_.guarded_file_path) assert os.path.exists(file_.current_file_path)
def test_optional_permissions(self): upload = self.upload('webextension_no_id.xpi') parsed_data = parse_addon(upload, user=user_factory()) assert len(parsed_data['optional_permissions']) == 2 file_ = File.from_upload(upload, self.version, parsed_data=parsed_data) permissions_list = file_.optional_permissions assert len(permissions_list) == 2 assert permissions_list == parsed_data['optional_permissions']
def test_beta_version_non_public(self): # Only public add-ons can get beta versions. upload = self.upload('beta-extension') d = parse_addon(upload.path) self.addon.update(status=amo.STATUS_LITE) eq_(self.addon.status, amo.STATUS_LITE) f = File.from_upload(upload, self.version, self.platform, parse_data=d) eq_(f.status, amo.STATUS_UNREVIEWED)
def test_public_to_beta(self): upload = self.upload('beta-extension') d = parse_addon(upload.path) self.addon.update(status=amo.STATUS_PUBLIC) assert self.addon.status == amo.STATUS_PUBLIC f = File.from_upload(upload, self.version, self.platform, is_beta=True, parse_data=d) assert f.status == amo.STATUS_BETA
def test_file_validation(self): upload = self.upload('jetpack') file = File.from_upload(upload, self.version, self.platform) fv = FileValidation.objects.get(file=file) eq_(json.loads(fv.validation), json.loads(upload.validation)) eq_(fv.valid, True) eq_(fv.errors, 0) eq_(fv.warnings, 1) eq_(fv.notices, 2)
def test_litenominated_to_unreviewed(self): upload = self.upload('extension') d = parse_addon(upload.path) with mock.patch('olympia.addons.models.Addon.update_status'): # mock update_status because it doesn't like Addons without files. self.addon.update(status=amo.STATUS_LITE_AND_NOMINATED) assert self.addon.status == amo.STATUS_LITE_AND_NOMINATED f = File.from_upload(upload, self.version, self.platform, parse_data=d) assert f.status == amo.STATUS_UNREVIEWED
def test_file_validation(self): upload = self.upload('jetpack') file = File.from_upload(upload, self.version, self.platform) fv = FileValidation.objects.get(file=file) assert json.loads(fv.validation) == json.loads(upload.validation) assert fv.valid assert fv.errors == 0 assert fv.warnings == 1 assert fv.notices == 2
def fake_file_object(self, obj, data): file_ = File(id=data['id'], created=self.handle_date(data['created']), hash=data['hash'], filename=data['filename'], is_webextension=data.get('is_webextension'), is_mozilla_signed_extension=data.get( 'is_mozilla_signed_extension'), is_restart_required=data.get('is_restart_required', False), platform=data['platform'], size=data['size'], status=data['status'], strict_compatibility=data.get('strict_compatibility', False), version=obj) file_.webext_permissions_list = data.get('webext_permissions_list', []) return file_
def test_file_validation(self): upload = self.upload('webextension.xpi') file = File.from_upload(upload, self.version, parsed_data={}) fv = FileValidation.objects.get(file=file) assert json.loads(fv.validation) == json.loads(upload.validation) assert fv.valid assert fv.errors == 0 assert fv.warnings == 1 assert fv.notices == 2
def fake_file_object(self, obj, data): file_ = File( id=data['id'], created=self.handle_date(data['created']), hash=data['hash'], filename=data['filename'], is_webextension=True, is_mozilla_signed_extension=data.get('is_mozilla_signed_extension'), size=data['size'], status=data['status'], strict_compatibility=data.get('strict_compatibility', False), version=obj, ) file_.permissions = data.get( 'permissions', data.get('webext_permissions_list', []) ) file_.optional_permissions = data.get('optional_permissions', []) return file_
def test_file_is_copied_to_current_path_at_upload_if_disabled(self): self.addon.update(disabled_by_user=True) upload = self.upload('webextension') file_ = File.from_upload( upload, self.version, parsed_data={'is_webextension': True} ) assert not os.path.exists(file_.file_path) assert os.path.exists(file_.guarded_file_path) assert os.path.exists(file_.current_file_path)
def _save_file(self, version): data = self.cleaned_data xpi = data['xpi'] hash = hashlib.sha256() f = File(version=version, platform=amo.PLATFORM_DICT[data['platform']].id, size=xpi.size) filename = f.generate_filename() path = os.path.join(user_media_path('addons'), str(version.addon.id)) with storage.open(os.path.join(path, filename), 'wb') as destination: for chunk in xpi.chunks(): hash.update(chunk) destination.write(chunk) f.hash = 'sha256:%s' % hash.hexdigest() f.save() return f
def test_public_to_unreviewed(self): upload = self.upload('extension') data = parse_addon(upload.path) self.addon.update(status=amo.STATUS_PUBLIC) assert self.addon.status == amo.STATUS_PUBLIC file_ = File.from_upload(upload, self.version, self.platform, parsed_data=data) assert file_.status == amo.STATUS_AWAITING_REVIEW
def test_is_ready_for_auto_approval(self): addon = Addon.objects.get(id=3615) version = addon.current_version assert not version.is_ready_for_auto_approval version.all_files = [ File(status=amo.STATUS_AWAITING_REVIEW, is_webextension=False)] assert not version.is_ready_for_auto_approval version.all_files = [ File(status=amo.STATUS_AWAITING_REVIEW, is_webextension=True)] version.channel = amo.RELEASE_CHANNEL_UNLISTED assert not version.is_ready_for_auto_approval version.channel = amo.RELEASE_CHANNEL_LISTED assert version.is_ready_for_auto_approval addon.type = amo.ADDON_THEME assert not version.is_ready_for_auto_approval
def test_webextension_crx(self): """Test to ensure we accept CRX uploads, but convert them into XPI files ASAP to keep things simple. """ upload = self.upload('webextension.crx') file_ = File.from_upload(upload, self.version, self.platform, parse_data={'is_webextension': True}) assert file_.filename.endswith('.xpi') assert file_.is_webextension storage.delete(upload.path)
def test_webextension_crx_large(self): """Test to ensure we accept large CRX uploads, because of how we write them to storage. """ upload = self.upload('https-everywhere.crx') file_ = File.from_upload(upload, self.version, self.platform, parse_data={'is_webextension': True}) assert file_.filename.endswith('.xpi') assert file_.is_webextension storage.delete(upload.path)
def test_webextension_crx(self): """Test to ensure we accept CRX uploads, but convert them into XPI files ASAP to keep things simple. """ upload = self.upload('webextension.crx') file_ = File.from_upload(upload, self.version, self.platform, parsed_data={'is_webextension': True}) assert file_.filename.endswith('.xpi') assert file_.is_webextension storage.delete(upload.path)
def test_webextension_crx_large(self): """Test to ensure we accept large CRX uploads, because of how we write them to storage. """ upload = self.upload('https-everywhere.crx') file_ = File.from_upload(upload, self.version, self.platform, parsed_data={'is_webextension': True}) assert file_.filename.endswith('.xpi') assert file_.is_webextension storage.delete(upload.path)
def test_is_ready_for_auto_approval_addon_status(self): addon = Addon.objects.get(id=3615) addon.status = amo.STATUS_NOMINATED version = addon.current_version version.all_files = [ File(status=amo.STATUS_AWAITING_REVIEW, is_webextension=True)] assert version.is_ready_for_auto_approval addon.status = amo.STATUS_DISABLED assert not version.is_ready_for_auto_approval
def test_generate_hash(self): file_ = File() file_.version = Version.objects.get(pk=81551) filename = self.xpi_path('https-everywhere.xpi') assert file_.generate_hash(filename).startswith('sha256:95bd414295acda29c4') file_ = File.objects.get(pk=67442) with storage.open(file_.file_path, 'wb') as fp: fp.write(b'some data\n') with storage.open(file_.guarded_file_path, 'wb') as fp: fp.write(b'some data guarded\n') assert file_.generate_hash().startswith('sha256:5aa03f96c77536579166f') file_.status = amo.STATUS_DISABLED assert file_.generate_hash().startswith('sha256:6524f7791a35ef4dd4c6f') file_.status = amo.STATUS_APPROVED assert file_.generate_hash().startswith('sha256:5aa03f96c77536579166f')
def get_file(self, platform): file = File() # Real object and not a mock to get the true methods. file.version = self.version file.pk = 666 file.platform = platform file.status = amo.STATUS_PUBLIC file.strict_compatibility = False file.binary_components = False return file
def test_trusted_public_to_beta(self): upload = self.upload('beta-extension') d = parse_addon(upload.path) self.addon.update(status=amo.STATUS_PUBLIC, trusted=True) eq_(self.addon.status, amo.STATUS_PUBLIC) f = File.from_upload(upload, self.version, self.platform, is_beta=True, parse_data=d) eq_(f.status, amo.STATUS_BETA)
def test_file_for_platform(self): """If client passes a platform, make sure we get the right file.""" version = Version.objects.get(pk=self.version_1_2_2) file_one = version.files.all()[0] file_one.platform = amo.PLATFORM_LINUX.id file_one.save() file_two = File(version=version, filename='foo', hash='bar', platform=amo.PLATFORM_WIN.id, status=amo.STATUS_PUBLIC) file_two.save() version, file = self.get_update_instance( '1.2', self.version_int, self.app, amo.PLATFORM_LINUX) assert version == self.version_1_2_2 assert file == file_one.pk version, file = self.get_update_instance( '1.2', self.version_int, self.app, amo.PLATFORM_WIN) assert version == self.version_1_2_2 assert file == file_two.pk
def test_file_for_platform(self): """If client passes a platform, make sure we get the right file.""" version = Version.objects.get(pk=self.version_1_2_2) file_one = version.files.all()[0] file_one.platform = amo.PLATFORM_LINUX.id file_one.save() file_two = File(version=version, filename='foo', hash='bar', platform=amo.PLATFORM_WIN.id, status=amo.STATUS_PUBLIC) file_two.save() version, file = self.get('1.2', self.version_int, self.app, amo.PLATFORM_LINUX) assert version == self.version_1_2_2 assert file == file_one.pk version, file = self.get('1.2', self.version_int, self.app, amo.PLATFORM_WIN) assert version == self.version_1_2_2 assert file == file_two.pk
def test_permissions(self): upload = self.upload('webextension_no_id.xpi') parsed_data = parse_addon(upload) # 5 total permissions. assert len(parsed_data['permissions']) == 5 file_ = File.from_upload(upload, self.version, self.platform, parsed_data=parsed_data) permissions_list = file_.webext_permissions_list assert len(permissions_list) == 5 assert permissions_list == [u'http://*/*', u'https://*/*', 'bookmarks', 'made up permission', 'https://google.com/' ]
def test_dont_send_both_bytes_and_str_to_copy_stored_file( self, copy_stored_file_mock): upload = self.upload('wébextension.xpi') self.version.addon.name = 'jéts!' file_ = File.from_upload(upload, self.version, parsed_data={}) assert file_.filename == 'jets-0.1.xpi' expected_path_orig = force_str(upload.path) expected_path_dest = force_str(file_.current_file_path) assert copy_stored_file_mock.call_count == 1 assert copy_stored_file_mock.call_args_list[0][0] == ( expected_path_orig, expected_path_dest, )
def test_version_is_not_allowed_upload(self): version = Version.objects.get(pk=81551) version.files.all().delete() for platform in [ amo.PLATFORM_LINUX.id, amo.PLATFORM_WIN.id, amo.PLATFORM_BSD.id ]: file = File(platform=platform, version=version) file.save() version = Version.objects.get(pk=81551) assert version.is_allowed_upload() file = File(platform=amo.PLATFORM_MAC.id, version=version) file.save() # The transform don't know bout my new files. version = Version.objects.no_cache().get(pk=81551) assert not version.is_allowed_upload()
def fake_object(self, data): """Create a fake instance of Addon and related models from ES data.""" obj = Addon(id=data['id'], slug=data['slug'], is_listed=True) data_version = data.get('current_version') if data_version: obj._current_version = Version(addon=obj, id=data_version['id'], reviewed=self.handle_date( data_version['reviewed']), version=data_version['version']) data_files = data_version.get('files', []) obj._current_version.all_files = [ File(id=file_['id'], created=self.handle_date(file_['created']), hash=file_['hash'], filename=file_['filename'], platform=file_['platform'], size=file_['size'], status=file_['status'], version=obj._current_version) for file_ in data_files ] # In ES we store integers for the appversion info, we need to # convert it back to strings. compatible_apps = {} for app_id, compat_dict in data['appversion'].items(): app_name = APPS_ALL[int(app_id)] compatible_apps[app_name] = ApplicationsVersions( min=AppVersion(version=compat_dict.get('min_human', '')), max=AppVersion(version=compat_dict.get('max_human', ''))) obj._current_version.compatible_apps = compatible_apps # Attach base attributes that have the same name/format in ES and in # the model. self._attach_fields( obj, data, ('average_daily_users', 'bayesian_rating', 'created', 'default_locale', 'guid', 'hotness', 'is_listed', 'last_updated', 'public_stats', 'slug', 'status', 'type', 'weekly_downloads')) # Attach attributes that do not have the same name/format in ES. obj.tag_list = data['tags'] obj.disabled_by_user = data['is_disabled'] # Not accurate, but enough. # Attach translations (they require special treatment). self._attach_translations(obj, data, self.translated_fields) return obj
def test_force_extract(self): upload = self.get_upload('webextension_no_id.xpi') parsed_data = parse_addon(upload, user=mock.Mock()) # change the permissions so we can tell they've been re-parsed. parsed_data['permissions'].pop() file_ = File.from_upload(upload, self.version, self.platform, parsed_data=parsed_data) assert WebextPermission.objects.count() == 1 assert len(file_.webext_permissions_list) == 7 call_command('extract_permissions', force=True) file_ = File.objects.get(id=file_.id) assert WebextPermission.objects.get(file=file_) assert len(file_.webext_permissions_list) == 8
def test_force_extract(self): upload = self.get_upload('webextension_no_id.xpi') parsed_data = parse_addon(upload) # change the permissions so we can tell they've been re-parsed. parsed_data['permissions'].pop() file_ = File.from_upload(upload, self.version, self.platform, parsed_data=parsed_data) assert WebextPermission.objects.count() == 1 assert len(file_.webext_permissions) == 2 call_command('extract_permissions', force=True) file_ = File.objects.no_cache().get(id=file_.id) assert WebextPermission.objects.get(file=file_) permissions = file_.webext_permissions assert len(permissions) == 3
def test_extract(self): upload = self.get_upload('webextension_no_id.xpi') parsed_data = parse_addon(upload, user=mock.Mock()) # Remove the optional permissions from the parsed data so they aren't # added. pdata_optional_permissions = parsed_data.pop('optional_permissions') file_ = File.from_upload(upload, self.version, self.platform, parsed_data=parsed_data) assert file_.optional_permissions == [] call_command('extract_optional_permissions') file_ = File.objects.get(id=file_.id) optional_permissions = file_.optional_permissions assert len(optional_permissions) == 2 assert optional_permissions == pdata_optional_permissions
def test_is_ready_for_auto_approval_addon_status(self): addon = Addon.objects.get(id=3615) addon.status = amo.STATUS_NOMINATED version = addon.current_version version.all_files = [ File(status=amo.STATUS_AWAITING_REVIEW, is_webextension=True) ] assert not version.is_ready_for_auto_approval with override_switch('post-review', active=True): # When the post-review switch is active, we also accept add-ons # with NOMINATED status. assert version.is_ready_for_auto_approval addon.status = amo.STATUS_NOMINATED assert version.is_ready_for_auto_approval addon.status = amo.STATUS_DISABLED assert not version.is_ready_for_auto_approval
def test_extract(self): upload = self.get_upload('webextension_no_id.xpi') parsed_data = parse_addon(upload) # Delete the permissions from the parsed data so they aren't added. del parsed_data['permissions'] file_ = File.from_upload(upload, self.version, self.platform, parsed_data=parsed_data) assert WebextPermission.objects.count() == 0 assert file_.webext_permissions == {} call_command('extract_permissions') file_ = File.objects.no_cache().get(id=file_.id) assert WebextPermission.objects.get(file=file_) permissions = file_.webext_permissions assert len(permissions) == 3 assert permissions['alarms'] assert permissions[u'http://*/*'] assert permissions[u'https://*/*']
def test_extract(self): upload = self.get_upload('webextension_no_id.xpi') parsed_data = parse_addon(upload) # Delete the permissions from the parsed data so they aren't added. del parsed_data['permissions'] file_ = File.from_upload(upload, self.version, self.platform, parsed_data=parsed_data) assert WebextPermission.objects.count() == 0 assert file_.webext_permissions_list == [] call_command('extract_permissions') file_ = File.objects.no_cache().get(id=file_.id) assert WebextPermission.objects.get(file=file_) permissions_list = file_.webext_permissions_list assert len(permissions_list) == 5 assert permissions_list == [u'http://*/*', u'https://*/*', 'bookmarks', 'made up permission', 'https://google.com/' ]
def test_validator_sets_require_chrome(self): validation = json.dumps({ "errors": 0, "success": True, "warnings": 0, "notices": 0, "message_tree": {}, "messages": [], "metadata": { "version": "1.0", "name": "gK0Bes Bot", "id": "gkobes@gkobes", "requires_chrome": True } }) upload = self.get_upload(filename='extension.xpi', validation=validation) version = Version.objects.filter(addon__pk=3615)[0] file_ = File.from_upload(upload, version, amo.PLATFORM_LINUX.id) assert file_.requires_chrome
def test_validator_sets_binary_via_content(self): validation = json.dumps({ "errors": 0, "success": True, "warnings": 0, "notices": 0, "message_tree": {}, "messages": [], "metadata": { "contains_binary_content": True, "version": "1.0", "name": "gK0Bes Bot", "id": "gkobes@gkobes", } }) upload = self.get_upload(filename='extension.xpi', validation=validation) version = Version.objects.filter(addon__pk=3615)[0] file_ = File.from_upload(upload, version, amo.PLATFORM_LINUX.id) eq_(file_.binary, True)
def from_upload(cls, upload, addon, platforms, channel, send_signal=True, source=None, is_beta=False): from olympia.addons.models import AddonFeatureCompatibility data = utils.parse_addon(upload, addon) try: license = addon.versions.latest().license_id except Version.DoesNotExist: license = None version = cls.objects.create( addon=addon, version=data['version'], license_id=license, source=source, channel=channel, ) log.info( 'New version: %r (%s) from %r' % (version, version.id, upload)) # Update the add-on e10s compatibility since we're creating a new # version that may change that. e10s_compatibility = data.get('e10s_compatibility') if e10s_compatibility is not None: feature_compatibility = ( AddonFeatureCompatibility.objects.get_or_create(addon=addon)[0] ) feature_compatibility.update(e10s=e10s_compatibility) compatible_apps = {} for app in data.get('apps', []): compatible_apps[app.appdata] = ApplicationsVersions( version=version, min=app.min, max=app.max, application=app.id) compatible_apps[app.appdata].save() # See #2828: sometimes when we generate the filename(s) below, in # File.from_upload(), cache-machine is confused and has trouble # fetching the ApplicationsVersions that were just created. To work # around this we pre-generate version.compatible_apps and avoid the # queries completely. version.compatible_apps = compatible_apps if addon.type == amo.ADDON_SEARCH: # Search extensions are always for all platforms. platforms = [amo.PLATFORM_ALL.id] else: platforms = cls._make_safe_platform_files(platforms) for platform in platforms: File.from_upload(upload, version, platform, parse_data=data, is_beta=is_beta) version.disable_old_files() # After the upload has been copied to all platforms, remove the upload. storage.delete(upload.path) if send_signal: version_uploaded.send(sender=version) # Track the time it took from first upload through validation # (and whatever else) until a version was created. upload_start = utc_millesecs_from_epoch(upload.created) now = datetime.datetime.now() now_ts = utc_millesecs_from_epoch(now) upload_time = now_ts - upload_start log.info('Time for version {version} creation from upload: {delta}; ' 'created={created}; now={now}' .format(delta=upload_time, version=version, created=upload.created, now=now)) statsd.timing('devhub.version_created_from_upload', upload_time) return version