diff options
Diffstat (limited to 'tests/units/node/node.py')
-rwxr-xr-x | tests/units/node/node.py | 1058 |
1 files changed, 198 insertions, 860 deletions
diff --git a/tests/units/node/node.py b/tests/units/node/node.py index d8f00ec..0058918 100755 --- a/tests/units/node/node.py +++ b/tests/units/node/node.py @@ -16,17 +16,17 @@ from os.path import exists, join from __init__ import tests from sugar_network import db, node, model, client -from sugar_network.client import Connection, keyfile +from sugar_network.db import files +from sugar_network.client import Connection, keyfile, api_url from sugar_network.toolkit import http, coroutine from sugar_network.toolkit.rrd import Rrd -from sugar_network.node import stats_user, stats_node, obs -from sugar_network.node.routes import NodeRoutes, generate_node_stats +from sugar_network.node import stats_user +from sugar_network.node.routes import NodeRoutes from sugar_network.node.master import MasterRoutes from sugar_network.model.user import User from sugar_network.model.context import Context -from sugar_network.model.release import Release from sugar_network.model.user import User -from sugar_network.toolkit.router import Router, Request, Response, fallbackroute, Blob, ACL, route +from sugar_network.toolkit.router import Router, Request, Response, fallbackroute, ACL, route from sugar_network.toolkit import http @@ -40,7 +40,7 @@ class NodeTest(tests.Test): def test_UserStats(self): volume = db.Volume('db', model.RESOURCES) - cp = NodeRoutes('guid', volume) + cp = NodeRoutes('guid', volume=volume) call(cp, method='POST', document='user', principal=tests.UID, content={ 'name': 'user', @@ -100,69 +100,10 @@ class NodeTest(tests.Test): }, call(cp, method='GET', cmd='stats-info', document='user', guid=tests.UID, principal=tests.UID)) - def test_NodeStats(self): - stats_node.stats_node.value = True - stats_node.stats_node_rras.value = ['RRA:AVERAGE:0.5:1:60', 'RRA:AVERAGE:0.5:3:60'] - rrd = Rrd('stats/node', stats_node.stats_node_step.value, stats_node.stats_node_rras.value) - - ts = int(time.time()) / 3 * 3 - for i in range(10): - rrd['user'].put({'total': i}, ts + i) - - volume = db.Volume('db', model.RESOURCES) - cp = NodeRoutes('guid', volume) - - self.assertEqual({ - 'user': [ - (ts + 0, {'total': 0.0}), - (ts + 1, {'total': 1.0}), - (ts + 2, {'total': 2.0}), - (ts + 3, {'total': 3.0}), - ], - }, - call(cp, method='GET', cmd='stats', source='user.total', start=ts, end=ts + 3, records=4)) - - self.assertEqual({ - 'user': [ - (ts + 0, {'total': 0.0}), - (ts + 3, {'total': 2.0}), - (ts + 6, {'total': 5.0}), - (ts + 9, {'total': 8.0}), - ], - }, - call(cp, method='GET', cmd='stats', source='user.total', start=ts, end=ts + 9, records=3)) - - def test_NodeStatsDefaults(self): - stats_node.stats_node.value = True - rrd = Rrd('stats/node', stats_node.stats_node_step.value, stats_node.stats_node_rras.value) - - ts = int(time.time()) - for i in range(10): - rrd['user'].put({'total': i}, ts + i) - - volume = db.Volume('db', model.RESOURCES) - cp = NodeRoutes('guid', volume) - - self.assertEqual({ - 'user': [ - (ts + 0, {'total': 0.0}), - (ts + 1, {'total': 1.0}), - (ts + 2, {'total': 2.0}), - (ts + 3, {'total': 3.0}), - (ts + 4, {'total': 4.0}), - (ts + 5, {'total': 5.0}), - (ts + 6, {'total': 6.0}), - (ts + 7, {'total': 7.0}), - (ts + 8, {'total': 8.0}), - (ts + 9, {'total': 9.0}), - ], - }, - call(cp, method='GET', cmd='stats', source='user.total')) - def test_HandleDeletes(self): volume = db.Volume('db', model.RESOURCES) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - cp = NodeRoutes('guid', volume) + cp = NodeRoutes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) guid = call(cp, method='POST', document='context', principal=tests.UID, content={ 'type': 'activity', @@ -192,33 +133,41 @@ class NodeTest(tests.Test): coroutine.dispatch() self.assertRaises(http.NotFound, call, cp, method='GET', document='context', guid=guid, reply=['guid', 'title']) self.assertEqual(['deleted'], volume['context'].get(guid)['layer']) - self.assertEqual({'event': 'delete', 'resource': 'context', 'guid': guid}, events[0]) - def test_SimulateDeleteEvents(self): - volume = db.Volume('db', model.RESOURCES) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - cp = NodeRoutes('guid', volume) + def test_DeletedRestoredHandlers(self): + trigger = [] - guid = call(cp, method='POST', document='context', principal=tests.UID, content={ - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) + class TestDocument(db.Resource): - def subscribe(): - for event in cp.subscribe(): - events.append(event) - events = [] - coroutine.spawn(subscribe) - coroutine.dispatch() + def deleted(self): + trigger.append(False) - call(cp, method='PUT', document='context', guid=guid, principal=tests.UID, content={'layer': ['deleted']}) - coroutine.dispatch() - self.assertEqual({'event': 'delete', 'resource': 'context', 'guid': guid}, events[0]) + def restored(self): + trigger.append(True) + + volume = self.start_master([TestDocument, User]) + conn = Connection(auth=http.SugarAuth(keyfile.value)) + + guid = conn.post(['testdocument'], {}) + self.assertEqual([], trigger) + + conn.put(['testdocument', guid, 'layer'], ['deleted']) + self.assertEqual([False], trigger) + + conn.put(['testdocument', guid, 'layer'], []) + self.assertEqual([False, True], trigger) + + conn.put(['testdocument', guid, 'layer'], ['bar']) + self.assertEqual([False, True], trigger) + + conn.put(['testdocument', guid, 'layer'], ['deleted']) + self.assertEqual([False, True, False], trigger) + + conn.put(['testdocument', guid, 'layer'], ['deleted', 'foo']) + self.assertEqual([False, True, False], trigger) def test_RegisterUser(self): - cp = NodeRoutes('guid', db.Volume('db', [User])) + cp = NodeRoutes('guid', volume=db.Volume('db', [User])) guid = call(cp, method='POST', document='user', principal=tests.UID2, content={ 'name': 'user', @@ -229,7 +178,7 @@ class NodeTest(tests.Test): def test_UnauthorizedCommands(self): volume = db.Volume('db', model.RESOURCES) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) class Routes(NodeRoutes): @@ -244,7 +193,7 @@ class NodeTest(tests.Test): class Document(db.Resource): pass - cp = Routes('guid', db.Volume('db', [User, Document])) + cp = Routes('guid', volume=db.Volume('db', [User, Document])) guid = call(cp, method='POST', document='document', principal=tests.UID, content={}) self.assertRaises(http.Unauthorized, call, cp, method='GET', cmd='probe1', document='document', guid=guid) @@ -267,8 +216,8 @@ class NodeTest(tests.Test): pass volume = db.Volume('db', [User, Document]) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - cp = Routes('guid', volume) + cp = Routes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) guid = call(cp, method='POST', document='document', principal=tests.UID, content={}) @@ -278,7 +227,7 @@ class NodeTest(tests.Test): call(cp, method='GET', cmd='probe2', document='document', guid=guid) def test_ForbiddenCommandsForUserResource(self): - cp = NodeRoutes('guid', db.Volume('db', [User])) + cp = NodeRoutes('guid', volume=db.Volume('db', [User])) call(cp, method='POST', document='user', principal=tests.UID2, content={ 'name': 'user1', @@ -304,9 +253,9 @@ class NodeTest(tests.Test): return 'ok' volume = db.Volume('db', [User]) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - volume['user'].create({'guid': tests.UID2, 'name': 'test', 'pubkey': {'blob': StringIO(tests.PUBKEY2)}}) - cp = Routes('guid', volume) + cp = Routes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) + volume['user'].create({'guid': tests.UID2, 'name': 'test', 'pubkey': tests.PUBKEY2}) self.assertRaises(http.Forbidden, call, cp, method='PROBE') self.assertRaises(http.Forbidden, call, cp, method='PROBE', principal=tests.UID2) @@ -321,9 +270,9 @@ class NodeTest(tests.Test): return value volume = db.Volume('db', [User, Document]) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - volume['user'].create({'guid': tests.UID2, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY2)}}) - cp = NodeRoutes('guid', volume) + cp = NodeRoutes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) + volume['user'].create({'guid': tests.UID2, 'name': 'user', 'pubkey': tests.PUBKEY2}) guid = call(cp, method='POST', document='document', principal=tests.UID, content={'prop': '1'}) self.assertRaises(http.Forbidden, call, cp, 'PUT', document='document', guid=guid, content={'prop': '2'}, principal=tests.UID2) @@ -342,9 +291,9 @@ class NodeTest(tests.Test): return value volume = db.Volume('db', [User, Document]) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - volume['user'].create({'guid': tests.UID2, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY2)}}) - cp = NodeRoutes('guid', volume) + cp = NodeRoutes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) + volume['user'].create({'guid': tests.UID2, 'name': 'user', 'pubkey': tests.PUBKEY2}) guid = call(cp, method='POST', document='document', principal=tests.UID, content={'prop': '1'}) @@ -363,8 +312,8 @@ class NodeTest(tests.Test): pass volume = db.Volume('db', [User]) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - cp = Routes('guid', volume) + cp = Routes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) self.assertRaises(http.Forbidden, call, cp, 'PROBE', principal=tests.UID) self.touch(('authorization.conf', [ @@ -386,7 +335,7 @@ class NodeTest(tests.Test): pass volume = db.Volume('db', [User]) - cp = Routes('guid', volume) + cp = Routes('guid', volume=volume) self.assertRaises(http.Unauthorized, call, cp, 'PROBE1') self.assertRaises(http.Forbidden, call, cp, 'PROBE2') @@ -401,8 +350,8 @@ class NodeTest(tests.Test): def test_SetUser(self): volume = db.Volume('db', model.RESOURCES) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - cp = NodeRoutes('guid', volume) + cp = NodeRoutes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) guid = call(cp, method='POST', document='context', principal=tests.UID, content={ 'type': 'activity', @@ -416,8 +365,8 @@ class NodeTest(tests.Test): def test_find_MaxLimit(self): volume = db.Volume('db', model.RESOURCES) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - cp = NodeRoutes('guid', volume) + cp = NodeRoutes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) call(cp, method='POST', document='context', principal=tests.UID, content={ 'type': 'activity', @@ -438,23 +387,26 @@ class NodeTest(tests.Test): 'description': 'description', }) - node.find_limit.value = 3 + cp._find_limit = 3 self.assertEqual(3, len(call(cp, method='GET', document='context', limit=1024)['result'])) - node.find_limit.value = 2 + cp._find_limit = 2 self.assertEqual(2, len(call(cp, method='GET', document='context', limit=1024)['result'])) - node.find_limit.value = 1 + cp._find_limit = 1 self.assertEqual(1, len(call(cp, method='GET', document='context', limit=1024)['result'])) def test_DeletedDocuments(self): volume = db.Volume('db', model.RESOURCES) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - cp = NodeRoutes('guid', volume) + cp = NodeRoutes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) guid = call(cp, method='POST', document='context', principal=tests.UID, content={ 'type': 'activity', 'title': 'title1', 'summary': 'summary', 'description': 'description', + 'artifact_icon': '', + 'icon': '', + 'logo': '', }) call(cp, method='GET', document='context', guid=guid) @@ -468,8 +420,8 @@ class NodeTest(tests.Test): def test_CreateGUID(self): # TODO Temporal security hole, see TODO volume = db.Volume('db', model.RESOURCES) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - cp = NodeRoutes('guid', volume) + cp = NodeRoutes('guid', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) call(cp, method='POST', document='context', principal=tests.UID, content={ 'guid': 'foo', 'type': 'activity', @@ -483,10 +435,10 @@ class NodeTest(tests.Test): def test_CreateMalformedGUID(self): volume = db.Volume('db', model.RESOURCES) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) cp = MasterRoutes('guid', volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) - self.assertRaises(RuntimeError, call, cp, method='POST', document='context', principal=tests.UID, content={ + self.assertRaises(http.BadRequest, call, cp, method='POST', document='context', principal=tests.UID, content={ 'guid': '!?', 'type': 'activity', 'title': 'title', @@ -496,8 +448,8 @@ class NodeTest(tests.Test): def test_FailOnExistedGUID(self): volume = db.Volume('db', model.RESOURCES) - volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) cp = MasterRoutes('guid', volume) + volume['user'].create({'guid': tests.UID, 'name': 'user', 'pubkey': tests.PUBKEY}) guid = call(cp, method='POST', document='context', principal=tests.UID, content={ 'type': 'activity', @@ -506,7 +458,7 @@ class NodeTest(tests.Test): 'description': 'description', }) - self.assertRaises(RuntimeError, call, cp, method='POST', document='context', principal=tests.UID, content={ + self.assertRaises(http.BadRequest, call, cp, method='POST', document='context', principal=tests.UID, content={ 'guid': guid, 'type': 'activity', 'title': 'title', @@ -566,139 +518,9 @@ class NodeTest(tests.Test): def test_Clone(self): volume = self.start_master() - client = Connection(auth=http.SugarAuth(keyfile.value)) + client = http.Connection(api_url.value, http.SugarAuth(keyfile.value)) - context = client.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - impl1 = client.post(['release'], { - 'context': context, - 'license': 'GPLv3+', - 'version': '1', - 'stability': 'stable', - 'notes': '', - }) - blob1 = self.zips(('topdir/probe', 'probe1')) - volume['release'].update(impl1, {'data': { - 'blob': StringIO(blob1), - 'spec': { - '*-*': { - 'requires': { - 'dep1': {}, - }, - }, - }, - }}) - impl2 = client.post(['release'], { - 'context': context, - 'license': 'GPLv3+', - 'version': '2', - 'stability': 'stable', - 'notes': '', - }) - blob2 = self.zips(('topdir/probe', 'probe2')) - volume['release'].update(impl2, {'data': { - 'blob': StringIO(blob2), - 'spec': { - '*-*': { - 'requires': { - 'dep2': {'restrictions': [[None, '2']]}, - 'dep3': {}, - }, - }, - }, - }}) - impl3 = client.post(['release'], { - 'context': context, - 'license': 'GPLv3+', - 'version': '3', - 'stability': 'stable', - 'notes': '', - }) - blob3 = self.zips(('topdir/probe', 'probe3')) - volume['release'].update(impl3, {'data': { - 'blob': StringIO(blob3), - 'spec': { - '*-*': { - 'requires': { - 'dep2': {'restrictions': [['2', None]]}, - }, - }, - }, - }}) - impl4 = client.post(['release'], { - 'context': context, - 'license': 'GPLv3+', - 'version': '4', - 'stability': 'developer', - 'notes': '', - }) - blob4 = self.zips(('topdir/probe', 'probe4')) - volume['release'].update(impl4, {'data': { - 'blob': StringIO(blob4), - 'spec': { - '*-*': { - 'requires': {}, - }, - }, - }}) - - self.assertEqual(blob3, client.get(['context', context], cmd='clone')) - self.assertEqual(blob4, client.get(['context', context], cmd='clone', stability='developer')) - self.assertEqual(blob1, client.get(['context', context], cmd='clone', version='1')) - - self.assertEqual(blob1, client.get(['context', context], cmd='clone', requires='dep1')) - self.assertEqual(blob3, client.get(['context', context], cmd='clone', requires='dep2')) - self.assertEqual(blob2, client.get(['context', context], cmd='clone', requires='dep2=1')) - self.assertEqual(blob3, client.get(['context', context], cmd='clone', requires='dep2=2')) - self.assertEqual(blob2, client.get(['context', context], cmd='clone', requires='dep3')) - - self.assertRaises(http.NotFound, client.get, ['context', context], cmd='clone', requires='dep4') - self.assertRaises(http.NotFound, client.get, ['context', context], cmd='clone', stability='foo') - - response = Response() - client.call(Request(method='GET', path=['context', context], cmd='clone'), response) - self.assertEqual({ - 'context': context, - 'stability': 'stable', - 'guid': impl3, - 'version': '3', - 'license': ['GPLv3+'], - 'layer': ['origin'], - 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, - 'ctime': self.node_volume['release'].get(impl3).ctime, - 'notes': {'en-us': ''}, - 'tags': [], - 'data': { - 'blob_size': len(blob3), - 'spec': { - '*-*': { - 'requires': { - 'dep2': { - 'restrictions': [['2', None]], - }, - }, - }, - }, - }, - }, - response.meta) - - def test_release(self): - volume = self.start_master() - conn = Connection(auth=http.SugarAuth(keyfile.value)) - - conn.post(['context'], { - 'guid': 'bundle_id', - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - activity_info = '\n'.join([ + blob1 = self.zips(('topdir/activity/activity.info', '\n'.join([ '[Activity]', 'name = TestActivitry', 'bundle_id = bundle_id', @@ -706,42 +528,12 @@ class NodeTest(tests.Test): 'icon = icon', 'activity_version = 1', 'license = Public Domain', - 'stability = developer', - 'requires = sugar>=0.88; dep' - ]) - changelog = "LOG" - bundle1 = self.zips( - ('topdir/activity/activity.info', activity_info), - ('topdir/CHANGELOG', changelog), - ) - guid1 = json.load(conn.request('POST', ['release'], bundle1, params={'cmd': 'submit'}).raw) - - impl = volume['release'].get(guid1) - self.assertEqual('bundle_id', impl['context']) - self.assertEqual('1', impl['version']) - self.assertEqual('developer', impl['stability']) - self.assertEqual(['Public Domain'], impl['license']) - self.assertEqual('developer', impl['stability']) - self.assertEqual({'en-us': changelog}, impl['notes']) - assert impl['ctime'] > 0 - assert impl['mtime'] > 0 - self.assertEqual({tests.UID: {'role': 3, 'name': 'f470db873b6a35903aca1f2492188e1c4b9ffc42', 'order': 0}}, impl['author']) - - data = impl.meta('data') - self.assertEqual({ - '*-*': { - 'commands': {'activity': {'exec': 'true'}}, - 'requires': {'dep': {}, 'sugar': {'restrictions': [['0.88', None]]}}, - }, - }, - data['spec']) - - self.assertEqual('application/vnd.olpc-sugar', data['mime_type']) - self.assertEqual(len(bundle1), data['blob_size']) - self.assertEqual(len(activity_info) + len(changelog), data.get('unpack_size')) - self.assertEqual(bundle1, conn.get(['context', 'bundle_id'], cmd='clone', stability='developer')) + 'requires = dep1', + 'stability = stable', + ]))) + release1 = json.load(client.request('POST', ['context'], blob1, params={'cmd': 'submit', 'initial': True}).raw) - activity_info = '\n'.join([ + blob2 = self.zips(('topdir/activity/activity.info', '\n'.join([ '[Activity]', 'name = TestActivitry', 'bundle_id = bundle_id', @@ -749,606 +541,152 @@ class NodeTest(tests.Test): 'icon = icon', 'activity_version = 2', 'license = Public Domain', + 'requires = dep2 < 3; dep3', 'stability = stable', - ]) - bundle2 = self.zips(('topdir/activity/activity.info', activity_info)) - guid2 = json.load(conn.request('POST', ['release'], bundle2, params={'cmd': 'submit'}).raw) - - self.assertEqual('1', volume['release'].get(guid1)['version']) - self.assertEqual(['origin'], volume['release'].get(guid1)['layer']) - self.assertEqual('2', volume['release'].get(guid2)['version']) - self.assertEqual(['origin'], volume['release'].get(guid2)['layer']) - self.assertEqual(bundle2, conn.get(['context', 'bundle_id'], cmd='clone')) + ]))) + release2 = json.load(client.request('POST', ['context'], blob2, params={'cmd': 'submit'}).raw) - activity_info = '\n'.join([ + blob3 = self.zips(('topdir/activity/activity.info', '\n'.join([ '[Activity]', 'name = TestActivitry', 'bundle_id = bundle_id', 'exec = true', 'icon = icon', - 'activity_version = 1', + 'activity_version = 3', 'license = Public Domain', + 'requires = dep2 >= 2', 'stability = stable', - ]) - bundle3 = self.zips(('topdir/activity/activity.info', activity_info)) - guid3 = json.load(conn.request('POST', ['release'], bundle3, params={'cmd': 'submit'}).raw) - - self.assertEqual('1', volume['release'].get(guid1)['version']) - self.assertEqual(sorted(['origin', 'deleted']), sorted(volume['release'].get(guid1)['layer'])) - self.assertEqual('2', volume['release'].get(guid2)['version']) - self.assertEqual(['origin'], volume['release'].get(guid2)['layer']) - self.assertEqual('1', volume['release'].get(guid3)['version']) - self.assertEqual(['origin'], volume['release'].get(guid3)['layer']) - self.assertEqual(bundle2, conn.get(['context', 'bundle_id'], cmd='clone')) + ]))) + release3 = json.load(client.request('POST', ['context'], blob3, params={'cmd': 'submit'}).raw) - activity_info = '\n'.join([ + blob4 = self.zips(('topdir/activity/activity.info', '\n'.join([ '[Activity]', 'name = TestActivitry', 'bundle_id = bundle_id', 'exec = true', 'icon = icon', - 'activity_version = 2', + 'activity_version = 4', 'license = Public Domain', - 'stability = buggy', - ]) - bundle4 = self.zips(('topdir/activity/activity.info', activity_info)) - guid4 = json.load(conn.request('POST', ['release'], bundle4, params={'cmd': 'submit'}).raw) - - self.assertEqual('1', volume['release'].get(guid1)['version']) - self.assertEqual(sorted(['origin', 'deleted']), sorted(volume['release'].get(guid1)['layer'])) - self.assertEqual('2', volume['release'].get(guid2)['version']) - self.assertEqual(sorted(['origin', 'deleted']), sorted(volume['release'].get(guid2)['layer'])) - self.assertEqual('1', volume['release'].get(guid3)['version']) - self.assertEqual(['origin'], volume['release'].get(guid3)['layer']) - self.assertEqual('2', volume['release'].get(guid4)['version']) - self.assertEqual(['origin'], volume['release'].get(guid4)['layer']) - self.assertEqual(bundle3, conn.get(['context', 'bundle_id'], cmd='clone')) - - def test_release_UpdateContext(self): - volume = self.start_master() - conn = Connection(auth=http.SugarAuth(keyfile.value)) + 'stability = developer', + ]))) + release4 = json.load(client.request('POST', ['context'], blob4, params={'cmd': 'submit'}).raw) - conn.post(['context'], { - 'guid': 'org.laptop.ImageViewerActivity', - 'type': 'activity', - 'title': {'en': ''}, - 'summary': {'en': ''}, - 'description': {'en': ''}, - }) - svg = '\n'.join([ - '<?xml version="1.0" encoding="UTF-8"?>', - '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [', - ' <!ENTITY fill_color "#123456">', - ' <!ENTITY stroke_color "#123456">', - ']>', - '<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">', - ' <rect x="3" y="7" width="44" height="36" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3"/>', - ' <polyline points="15,7 25,1 35,7" style="fill:none;;stroke:&stroke_color;;stroke-width:1.25"/>', - ' <circle cx="14" cy="19" r="4.5" style="fill:&stroke_color;;stroke:&stroke_color;;stroke-width:1.5"/>', - ' <polyline points="3,36 16,32 26,35" style="fill:none;;stroke:&stroke_color;;stroke-width:2.5"/>', - ' <polyline points="15,43 37,28 47,34 47,43" style="fill:&stroke_color;;stroke:&stroke_color;;stroke-width:3"/>', - ' <polyline points="22,41.5 35,30 27,41.5" style="fill:&fill_color;;stroke:none;;stroke-width:0"/>', - ' <polyline points="26,23 28,25 30,23" style="fill:none;;stroke:&stroke_color;;stroke-width:.9"/>', - ' <polyline points="31.2,20 33.5,17.7 35.8,20" style="fill:none;;stroke:&stroke_color;;stroke-width:1"/>', - ' <polyline points="36,13 38.5,15.5 41,13" style="fill:none;;stroke:&stroke_color;;stroke-width:1"/>', - '</svg>', - ]) - bundle = self.zips( - ('ImageViewer.activity/activity/activity.info', '\n'.join([ - '[Activity]', - 'bundle_id = org.laptop.ImageViewerActivity', - 'name = Image Viewer', - 'summary = The Image Viewer activity is a simple and fast image viewer tool', - 'description = It has features one would expect of a standard image viewer, like zoom, rotate, etc.', - 'homepage = http://wiki.sugarlabs.org/go/Activities/Image_Viewer', - 'activity_version = 22', - 'license = GPLv2+', - 'icon = activity-imageviewer', - 'exec = true', - 'mime_types = image/bmp;image/gif', - ])), - ('ImageViewer.activity/locale/ru/LC_MESSAGES/org.laptop.ImageViewerActivity.mo', - base64.b64decode('3hIElQAAAAAMAAAAHAAAAHwAAAARAAAA3AAAAAAAAAAgAQAADwAAACEBAAAOAAAAMQEAAA0AAABAAQAACgAAAE4BAAAMAAAAWQEAAA0AAABmAQAAJwAAAHQBAAAUAAAAnAEAABAAAACxAQAABwAAAMIBAAAIAAAAygEAANEBAADTAQAAIQAAAKUDAAATAAAAxwMAABwAAADbAwAAFwAAAPgDAAAhAAAAEAQAAB0AAAAyBAAAQAAAAFAEAAA9AAAAkQQAADUAAADPBAAAFAAAAAUFAAAQAAAAGgUAAAEAAAACAAAABwAAAAAAAAADAAAAAAAAAAwAAAAJAAAAAAAAAAoAAAAEAAAAAAAAAAAAAAALAAAABgAAAAgAAAAFAAAAAENob29zZSBkb2N1bWVudABEb3dubG9hZGluZy4uLgBGaXQgdG8gd2luZG93AEZ1bGxzY3JlZW4ASW1hZ2UgVmlld2VyAE9yaWdpbmFsIHNpemUAUmV0cmlldmluZyBzaGFyZWQgaW1hZ2UsIHBsZWFzZSB3YWl0Li4uAFJvdGF0ZSBhbnRpY2xvY2t3aXNlAFJvdGF0ZSBjbG9ja3dpc2UAWm9vbSBpbgBab29tIG91dABQcm9qZWN0LUlkLVZlcnNpb246IFBBQ0tBR0UgVkVSU0lPTgpSZXBvcnQtTXNnaWQtQnVncy1UbzogClBPVC1DcmVhdGlvbi1EYXRlOiAyMDEyLTA5LTI3IDE0OjU3LTA0MDAKUE8tUmV2aXNpb24tRGF0ZTogMjAxMC0wOS0yMiAxMzo1MCswMjAwCkxhc3QtVHJhbnNsYXRvcjoga3JvbTlyYSA8a3JvbTlyYUBnbWFpbC5jb20+Ckxhbmd1YWdlLVRlYW06IExBTkdVQUdFIDxMTEBsaS5vcmc+Ckxhbmd1YWdlOiAKTUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PVVURi04CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IDhiaXQKUGx1cmFsLUZvcm1zOiBucGx1cmFscz0zOyBwbHVyYWw9KG4lMTA9PTEgJiYgbiUxMDAhPTExID8gMCA6IG4lMTA+PTIgJiYgbiUxMDw9NCAmJiAobiUxMDA8MTAgfHwgbiUxMDA+PTIwKSA/IDEgOiAyKTsKWC1HZW5lcmF0b3I6IFBvb3RsZSAyLjAuMwoA0JLRi9Cx0LXRgNC40YLQtSDQtNC+0LrRg9C80LXQvdGCANCX0LDQs9GA0YPQt9C60LAuLi4A0KPQvNC10YHRgtC40YLRjCDQsiDQvtC60L3QtQDQn9C+0LvQvdGL0Lkg0Y3QutGA0LDQvQDQn9GA0L7RgdC80L7RgtGAINC60LDRgNGC0LjQvdC+0LoA0JjRgdGC0LjQvdC90YvQuSDRgNCw0LfQvNC10YAA0J/QvtC70YPRh9C10L3QuNC1INC40LfQvtCx0YDQsNC20LXQvdC40LksINC/0L7QtNC+0LbQtNC40YLQtS4uLgDQn9C+0LLQtdGA0L3Rg9GC0Ywg0L/RgNC+0YLQuNCyINGH0LDRgdC+0LLQvtC5INGB0YLRgNC10LvQutC4ANCf0L7QstC10YDQvdGD0YLRjCDQv9C+INGH0LDRgdC+0LLQvtC5INGB0YLRgNC10LvQutC1ANCf0YDQuNCx0LvQuNC30LjRgtGMANCe0YLQtNCw0LvQuNGC0YwA')), - ('ImageViewer.activity/activity/activity-imageviewer.svg', svg), - ) - impl = json.load(conn.request('POST', ['release'], bundle, params={'cmd': 'submit'}).raw) + assert blob3 == client.get(['context', 'bundle_id'], cmd='clone') + assert blob4 == client.get(['context', 'bundle_id'], cmd='clone', stability='developer') + assert blob1 == client.get(['context', 'bundle_id'], cmd='clone', version='1') - context = volume['context'].get('org.laptop.ImageViewerActivity') - self.assertEqual({ - 'en': 'Image Viewer', - 'ru': u'Просмотр картинок', - }, - context['title']) - self.assertEqual({ - 'en': 'The Image Viewer activity is a simple and fast image viewer tool', - }, - context['summary']) - self.assertEqual({ - 'en': 'It has features one would expect of a standard image viewer, like zoom, rotate, etc.', - }, - context['description']) - self.assertEqual(svg, file(context['artifact_icon']['blob']).read()) - assert 'blob' in context['icon'] - assert 'blob' in context['logo'] - self.assertEqual('http://wiki.sugarlabs.org/go/Activities/Image_Viewer', context['homepage']) - self.assertEqual(['image/bmp', 'image/gif'], context['mime_types']) - - def test_release_CreateContext(self): - volume = self.start_master() - conn = Connection(auth=http.SugarAuth(keyfile.value)) - - bundle = self.zips( - ('ImageViewer.activity/activity/activity.info', '\n'.join([ - '[Activity]', - 'bundle_id = org.laptop.ImageViewerActivity', - 'name = Image Viewer', - 'summary = The Image Viewer activity is a simple and fast image viewer tool', - 'description = It has features one would expect of a standard image viewer, like zoom, rotate, etc.', - 'homepage = http://wiki.sugarlabs.org/go/Activities/Image_Viewer', - 'activity_version = 22', - 'license = GPLv2+', - 'icon = activity-imageviewer', - 'exec = true', - 'mime_types = image/bmp;image/gif', - ])), - ('ImageViewer.activity/activity/activity-imageviewer.svg', ''), - ) - self.assertRaises(http.NotFound, conn.request, 'POST', ['release'], bundle, params={'cmd': 'submit'}) - impl = json.load(conn.request('POST', ['release'], bundle, params={'cmd': 'submit', 'initial': 1}).raw) - - context = volume['context'].get('org.laptop.ImageViewerActivity') - self.assertEqual({'en': 'Image Viewer'}, context['title']) - self.assertEqual({'en': 'The Image Viewer activity is a simple and fast image viewer tool'}, context['summary']) - self.assertEqual({'en': 'It has features one would expect of a standard image viewer, like zoom, rotate, etc.'}, context['description']) - self.assertEqual('http://wiki.sugarlabs.org/go/Activities/Image_Viewer', context['homepage']) - self.assertEqual(['image/bmp', 'image/gif'], context['mime_types']) - assert context['ctime'] > 0 - assert context['mtime'] > 0 - self.assertEqual({tests.UID: {'role': 3, 'name': 'f470db873b6a35903aca1f2492188e1c4b9ffc42', 'order': 0}}, context['author']) - - def test_release_ByNonAuthors(self): - volume = self.start_master() - bundle = self.zips( - ('ImageViewer.activity/activity/activity.info', '\n'.join([ - '[Activity]', - 'bundle_id = org.laptop.ImageViewerActivity', - 'name = Image Viewer', - 'activity_version = 1', - 'license = GPLv2+', - 'icon = activity-imageviewer', - 'exec = true', - ])), - ('ImageViewer.activity/activity/activity-imageviewer.svg', ''), - ) + assert blob1 == client.get(['context', 'bundle_id'], cmd='clone', requires='dep1') + assert blob3 == client.get(['context', 'bundle_id'], cmd='clone', requires='dep2') + assert blob2 == client.get(['context', 'bundle_id'], cmd='clone', requires='dep2=1') + assert blob3 == client.get(['context', 'bundle_id'], cmd='clone', requires='dep2=2') + assert blob2 == client.get(['context', 'bundle_id'], cmd='clone', requires='dep3') - conn = Connection(auth=http.SugarAuth(join(tests.root, 'data', tests.UID))) - impl1 = json.load(conn.request('POST', ['release'], bundle, params={'cmd': 'submit', 'initial': 1}).raw) - impl2 = json.load(conn.request('POST', ['release'], bundle, params={'cmd': 'submit'}).raw) - self.assertEqual(sorted(['origin', 'deleted']), sorted(volume['release'].get(impl1)['layer'])) - self.assertEqual(['origin'], volume['release'].get(impl2)['layer']) + self.assertRaises(http.NotFound, client.get, ['context', 'bundle_id'], cmd='clone', requires='dep4') + self.assertRaises(http.NotFound, client.get, ['context', 'bundle_id'], cmd='clone', stability='foo') - conn = Connection(auth=http.SugarAuth(join(tests.root, 'data', tests.UID2))) - conn.get(cmd='whoami') - impl3 = json.load(conn.request('POST', ['release'], bundle, params={'cmd': 'submit'}).raw) - self.assertEqual(sorted(['origin', 'deleted']), sorted(volume['release'].get(impl1)['layer'])) - self.assertEqual(sorted(['origin', 'deleted']), sorted(volume['release'].get(impl2)['layer'])) - self.assertEqual([], volume['release'].get(impl3)['layer']) + response = Response() + client.call(Request(method='GET', path=['context', 'bundle_id'], cmd='clone'), response) + announce = next(volume['post'].find(query='3', limit=1)[0]).guid + self.assertEqual({ + 'license': ['Public Domain'], + 'unpack_size': 162, + 'stability': 'stable', + 'version': '3', + 'release': [[3], 0], + 'announce': announce, + 'requires': ['dep2-2'], + 'spec': { + '*-*': { + 'commands': {'activity': {'exec': u'true'}}, + 'requires': {'dep2': {'restrictions': [['2', None]]}}, + 'bundle': str(hash(blob3)), + }, + }, + }, response.meta) - def test_release_PopulateRequires(self): + def test_release(self): volume = self.start_master() conn = Connection(auth=http.SugarAuth(keyfile.value)) + activity_info = '\n'.join([ + '[Activity]', + 'name = TestActivitry', + 'bundle_id = bundle_id', + 'exec = true', + 'icon = icon', + 'activity_version = 1', + 'license = Public Domain', + 'stability = developer', + ]) + changelog = "LOG" bundle = self.zips( - ('ImageViewer.activity/activity/activity.info', '\n'.join([ - '[Activity]', - 'bundle_id = org.laptop.ImageViewerActivity', - 'name = Image Viewer', - 'activity_version = 22', - 'license = GPLv2+', - 'icon = activity-imageviewer', - 'exec = true', - 'requires = dep1, dep2<10, dep3<=20, dep4>30, dep5>=40, dep6>5<7, dep7>=1<=3', - ])), - ('ImageViewer.activity/activity/activity-imageviewer.svg', ''), + ('topdir/activity/activity.info', activity_info), + ('topdir/CHANGELOG', changelog), ) - self.assertRaises(http.NotFound, conn.request, 'POST', ['release'], bundle, params={'cmd': 'submit'}) - impl = json.load(conn.request('POST', ['release'], bundle, params={'cmd': 'submit', 'initial': 1}).raw) - - self.assertEqual( - sorted([ - 'dep1', 'dep2', 'dep3', 'dep4-31', 'dep5-40', - 'dep6-6', - 'dep7-1', 'dep7-2', 'dep7-3', - ]), - sorted(volume['release'].get(impl)['requires'])) - - def test_generate_node_stats_Posts(self): - node.stats_root.value = 'stats' - stats_node.stats_node.value = True - stats_node.stats_node_rras.value = ['RRA:AVERAGE:0.5:1:10', 'RRA:AVERAGE:0.5:10:10'] - volume = db.Volume('db', model.RESOURCES) - - ts = 1000000000 - - volume['user'].create({ - 'guid': 'user_1', - 'ctime': ts + 1, - 'mtime': ts + 1, - 'layer': [], - 'name': '', - }) - volume['context'].create({ - 'guid': 'context_1', - 'ctime': ts + 1, - 'mtime': ts + 1, - 'layer': [], - 'type': 'activity', - 'title': '', - 'summary': '', - 'description': '', - }) - volume['release'].create({ - 'guid': 'impl_1', - 'ctime': ts + 2, - 'mtime': ts + 2, - 'layer': [], - 'context': 'context_1', - 'license': ['GPL-3'], - 'version': '1', - }) - volume['post'].create({ - 'guid': 'topic_1', - 'ctime': ts + 3, - 'mtime': ts + 3, - 'layer': [], - 'context': 'context_1', - 'type': 'object', - 'title': '', - 'message': '', - }) - volume['post'].create({ - 'guid': 'solution_1', - 'ctime': ts + 5, - 'mtime': ts + 5, - 'layer': [], - 'context': 'context_1', - 'topic': 'topic_1', - 'title': '', - 'message': '', - 'type': 'answer', - }) - volume['post'].create({ - 'guid': 'review_1', - 'ctime': ts + 6, - 'mtime': ts + 6, - 'layer': [], - 'context': 'context_1', - 'vote': 1, - 'title': '', - 'message': '', - 'type': 'review', - }) - volume['post'].create({ - 'guid': 'review_2', - 'ctime': ts + 6, - 'mtime': ts + 6, - 'layer': [], - 'context': 'context_1', - 'topic': 'topic_1', - 'vote': 2, - 'title': '', - 'message': '', - 'type': 'feedback', - }) - volume['report'].create({ - 'guid': 'report_1', - 'ctime': ts + 8, - 'mtime': ts + 8, - 'layer': [], - 'context': 'context_1', - 'release': 'impl_1', - 'error': '', - }) - volume['user'].create({ - 'guid': 'user_2', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'name': '', - }) - volume['context'].create({ - 'guid': 'context_2', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'type': 'activity', - 'title': '', - 'summary': '', - 'description': '', - }) - volume['release'].create({ - 'guid': 'impl_2', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'context': 'context_2', - 'license': ['GPL-3'], - 'version': '1', - }) - volume['release'].create({ - 'guid': 'impl_3', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'context': 'context_2', - 'license': ['GPL-3'], - 'version': '1', - }) - volume['post'].create({ - 'guid': 'review_3', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'context': 'context_2', - 'vote': 3, - 'title': '', - 'message': '', - 'type': 'review', - }) - volume['post'].create({ - 'guid': 'review_4', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'context': 'context_2', - 'vote': 4, - 'title': '', - 'message': '', - 'type': 'review', - }) - volume['report'].create({ - 'guid': 'report_2', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'context': 'context_2', - 'release': 'impl_1', - 'error': '', - }) - volume['report'].create({ - 'guid': 'report_3', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'context': 'context_2', - 'release': 'impl_1', - 'error': '', - }) - volume['post'].create({ - 'guid': 'topic_2', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'context': 'context_2', - 'type': 'object', - 'title': '', - 'message': '', - }) - volume['post'].create({ - 'guid': 'solution_2', - 'ctime': ts + 4, - 'mtime': ts + 4, - 'layer': [], - 'context': 'context_2', - 'topic': 'topic_2', - 'title': '', - 'message': '', - 'type': 'answer', - }) - - self.override(time, 'time', lambda: ts + 9) - old_stats = stats_node.Sniffer(volume, 'stats/node') - old_stats.log(Request(method='GET', path=['release', 'impl_1', 'data'])) - old_stats.log(Request(method='GET', path=['post', 'topic_1', 'data'])) - old_stats.commit(ts + 1) - old_stats.commit_objects() - old_stats.commit(ts + 2) - old_stats.commit(ts + 3) - old_stats.log(Request(method='GET', path=['release', 'impl_1', 'data'])) - old_stats.log(Request(method='GET', path=['release', 'impl_2', 'data'])) - old_stats.commit(ts + 4) - old_stats.commit_objects() - old_stats.commit(ts + 5) - old_stats.commit(ts + 6) - old_stats.log(Request(method='GET', path=['post', 'topic_1', 'data'])) - old_stats.log(Request(method='GET', path=['post', 'topic_2', 'data'])) - old_stats.commit(ts + 7) - old_stats.commit_objects() - old_stats.commit(ts + 8) - old_stats.commit_objects() - - generate_node_stats(volume, 'stats/node') - cp = NodeRoutes('guid', volume) + release = json.load(conn.request('POST', ['context'], bundle, params={'cmd': 'submit', 'initial': True}).raw) + announce = next(volume['post'].find(query='1', limit=1)[0]).guid self.assertEqual({ - 'user': [ - (ts + 1, {'total': 1.0}), - (ts + 2, {'total': 1.0}), - (ts + 3, {'total': 1.0}), - (ts + 4, {'total': 2.0}), - (ts + 5, {'total': 2.0}), - (ts + 6, {'total': 2.0}), - (ts + 7, {'total': 2.0}), - (ts + 8, {'total': 2.0}), - (ts + 9, {'total': 2.0}), - ], - 'context': [ - (ts + 1, {'total': 1.0, 'released': 0.0, 'failed': 0.0, 'downloaded': 1.0}), - (ts + 2, {'total': 1.0, 'released': 1.0, 'failed': 0.0, 'downloaded': 1.0}), - (ts + 3, {'total': 1.0, 'released': 1.0, 'failed': 0.0, 'downloaded': 1.0}), - (ts + 4, {'total': 2.0, 'released': 3.0, 'failed': 2.0, 'downloaded': 3.0}), - (ts + 5, {'total': 2.0, 'released': 3.0, 'failed': 2.0, 'downloaded': 3.0}), - (ts + 6, {'total': 2.0, 'released': 3.0, 'failed': 2.0, 'downloaded': 3.0}), - (ts + 7, {'total': 2.0, 'released': 3.0, 'failed': 2.0, 'downloaded': 3.0}), - (ts + 8, {'total': 2.0, 'released': 3.0, 'failed': 3.0, 'downloaded': 3.0}), - (ts + 9, {'total': 2.0, 'released': 3.0, 'failed': 3.0, 'downloaded': 3.0}), - ], - 'post': [ - (ts + 1, {'total': 0.0, 'downloaded': 1.0}), - (ts + 2, {'total': 0.0, 'downloaded': 1.0}), - (ts + 3, {'total': 1.0, 'downloaded': 1.0}), - (ts + 4, {'total': 5.0, 'downloaded': 1.0}), - (ts + 5, {'total': 6.0, 'downloaded': 1.0}), - (ts + 6, {'total': 8.0, 'downloaded': 1.0}), - (ts + 7, {'total': 8.0, 'downloaded': 3.0}), - (ts + 8, {'total': 8.0, 'downloaded': 3.0}), - (ts + 9, {'total': 8.0, 'downloaded': 3.0}), - ], - }, - call(cp, method='GET', cmd='stats', source=[ - 'user.total', - 'context.total', - 'context.released', - 'context.failed', - 'context.downloaded', - 'post.total', - 'post.downloaded', - ], start=ts + 1, end=ts + 10)) + release: { + 'seqno': 4, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': { + 'license': ['Public Domain'], + 'announce': announce, + 'release': [[1], 0], + 'requires': [], + 'spec': {'*-*': {'bundle': str(hash(bundle)), 'commands': {'activity': {'exec': 'true'}}, 'requires': {}}}, + 'stability': 'developer', + 'unpack_size': len(activity_info) + len(changelog), + 'version': '1', + }, + }, + }, conn.get(['context', 'bundle_id', 'releases'])) + post = volume['post'][announce] + assert tests.UID in post['author'] + self.assertEqual('notification', post['type']) self.assertEqual({ - 'downloads': 2, - 'rating': [1, 1], - }, - volume['context'].get('context_1').properties(['downloads', 'rating'])) - self.assertEqual({ - 'downloads': 1, - 'rating': [2, 7], - }, - volume['context'].get('context_2').properties(['downloads', 'rating'])) - self.assertEqual({ - 'downloads': 2, - 'rating': [1, 2], - }, - volume['post'].get('topic_1').properties(['downloads', 'rating'])) - self.assertEqual({ - 'downloads': 1, - 'rating': [0, 0], - }, - volume['post'].get('topic_2').properties(['downloads', 'rating'])) - - def test_generate_node_stats_Deletes(self): - node.stats_root.value = 'stats' - stats_node.stats_node.value = True - stats_node.stats_node_rras.value = ['RRA:AVERAGE:0.5:1:10', 'RRA:AVERAGE:0.5:10:10'] - volume = db.Volume('db', model.RESOURCES) - - ts = 1000000000 - - volume['user'].create({ - 'guid': 'user_1', - 'ctime': ts + 1, - 'mtime': ts + 2, - 'layer': ['deleted'], - 'name': '', - }) - volume['context'].create({ - 'guid': 'context_1', - 'ctime': ts + 1, - 'mtime': ts + 2, - 'layer': ['deleted'], - 'type': 'activity', - 'title': '', - 'summary': '', - 'description': '', - }) - volume['release'].create({ - 'guid': 'impl_1', - 'ctime': ts + 1, - 'mtime': ts + 2, - 'layer': ['deleted'], - 'context': 'context_1', - 'license': ['GPL-3'], - 'version': '1', - }) - volume['post'].create({ - 'guid': 'post_1', - 'ctime': ts + 1, - 'mtime': ts + 2, - 'layer': ['deleted'], - 'context': 'context_1', - 'type': 'object', - 'title': '', - 'message': '', - }) - volume['report'].create({ - 'guid': 'report_1', - 'ctime': ts + 1, - 'mtime': ts + 2, - 'layer': ['deleted'], - 'context': 'context_1', - 'release': 'impl_1', - 'error': '', - }) - - self.override(time, 'time', lambda: ts + 9) - generate_node_stats(volume, 'stats/node') - cp = NodeRoutes('guid', volume) - + 'en': 'TestActivitry 1 release', + 'es': 'TestActivitry 1 release', + 'fr': 'TestActivitry 1 release', + }, post['title']) self.assertEqual({ - 'user': [ - (ts + 1, {'total': 1.0}), - (ts + 2, {'total': 0.0}), - (ts + 3, {'total': 0.0}), - ], - 'context': [ - (ts + 1, {'total': 1.0}), - (ts + 2, {'total': 0.0}), - (ts + 3, {'total': 0.0}), - ], - 'post': [ - (ts + 1, {'total': 1.0}), - (ts + 2, {'total': 0.0}), - (ts + 3, {'total': 0.0}), - ], - }, - call(cp, method='GET', cmd='stats', source=[ - 'user.total', - 'context.total', - 'post.total', - ], start=ts + 1, end=ts + 3)) + 'en-us': 'LOG', + }, post['message']) def test_AggpropInsertAccess(self): class Document(db.Resource): - @db.stored_property(typecast=db.AggregatedType, default=db.AggregatedType(), acl=ACL.READ | ACL.INSERT) + @db.stored_property(db.Aggregated, acl=ACL.READ | ACL.INSERT) def prop1(self, value): return value - @db.stored_property(typecast=db.AggregatedType, default=db.AggregatedType(), acl=ACL.READ | ACL.INSERT | ACL.AUTHOR) + @db.stored_property(db.Aggregated, acl=ACL.READ | ACL.INSERT | ACL.AUTHOR) def prop2(self, value): return value volume = db.Volume('db', [Document, User]) - volume['user'].create({'guid': tests.UID, 'name': 'user1', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - volume['user'].create({'guid': tests.UID2, 'name': 'user2', 'pubkey': {'blob': StringIO(tests.PUBKEY2)}}) + cp = NodeRoutes('node', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user1', 'pubkey': tests.PUBKEY}) + volume['user'].create({'guid': tests.UID2, 'name': 'user2', 'pubkey': tests.PUBKEY2}) - cp = NodeRoutes('node', volume) guid = call(cp, method='POST', document='document', principal=tests.UID, content={}) self.override(time, 'time', lambda: 0) - call(cp, method='POST', path=['document', guid, 'prop1'], principal=tests.UID, content={'guid': '1'}) - call(cp, method='POST', path=['document', guid, 'prop1'], principal=tests.UID2, content={'guid': '2'}) + agg1 = call(cp, method='POST', path=['document', guid, 'prop1'], principal=tests.UID) + agg2 = call(cp, method='POST', path=['document', guid, 'prop1'], principal=tests.UID2) self.assertEqual({ - '1': {'seqno': 4, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, - '2': {'seqno': 5, 'author': {tests.UID2: {'name': 'user2', 'order': 0, 'role': 3}}}, + agg1: {'seqno': 4, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}, 'value': None}, + agg2: {'seqno': 5, 'author': {tests.UID2: {'name': 'user2', 'order': 0, 'role': 1}}, 'value': None}, }, call(cp, method='GET', path=['document', guid, 'prop1'])) - call(cp, method='POST', path=['document', guid, 'prop2'], principal=tests.UID, content={'guid': '1'}) - self.assertRaises(http. Forbidden, call, cp, method='POST', path=['document', guid, 'prop2'], principal=tests.UID2, content={'guid': '2'}) + agg3 = call(cp, method='POST', path=['document', guid, 'prop2'], principal=tests.UID) + self.assertRaises(http. Forbidden, call, cp, method='POST', path=['document', guid, 'prop2'], principal=tests.UID2) self.assertEqual({ - '1': {'seqno': 6, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, + agg3: {'seqno': 6, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}, 'value': None}, }, call(cp, method='GET', path=['document', guid, 'prop2'])) @@ -1356,64 +694,64 @@ class NodeTest(tests.Test): class Document(db.Resource): - @db.stored_property(typecast=db.AggregatedType, default=db.AggregatedType(), acl=ACL.READ | ACL.INSERT | ACL.REMOVE) + @db.stored_property(db.Aggregated, acl=ACL.READ | ACL.INSERT | ACL.REMOVE) def prop1(self, value): return value - @db.stored_property(typecast=db.AggregatedType, default=db.AggregatedType(), acl=ACL.READ | ACL.INSERT | ACL.REMOVE | ACL.AUTHOR) + @db.stored_property(db.Aggregated, acl=ACL.READ | ACL.INSERT | ACL.REMOVE | ACL.AUTHOR) def prop2(self, value): return value volume = db.Volume('db', [Document, User]) - volume['user'].create({'guid': tests.UID, 'name': 'user1', 'pubkey': {'blob': StringIO(tests.PUBKEY)}}) - volume['user'].create({'guid': tests.UID2, 'name': 'user2', 'pubkey': {'blob': StringIO(tests.PUBKEY2)}}) + cp = NodeRoutes('node', volume=volume) + volume['user'].create({'guid': tests.UID, 'name': 'user1', 'pubkey': tests.PUBKEY}) + volume['user'].create({'guid': tests.UID2, 'name': 'user2', 'pubkey': tests.PUBKEY2}) - cp = NodeRoutes('node', volume) guid = call(cp, method='POST', document='document', principal=tests.UID, content={}) self.override(time, 'time', lambda: 0) - call(cp, method='POST', path=['document', guid, 'prop1'], principal=tests.UID, content={'guid': '1', 'probe': True}) - call(cp, method='POST', path=['document', guid, 'prop1'], principal=tests.UID2, content={'guid': '2', 'probe': True}) + agg1 = call(cp, method='POST', path=['document', guid, 'prop1'], principal=tests.UID, content=True) + agg2 = call(cp, method='POST', path=['document', guid, 'prop1'], principal=tests.UID2, content=True) self.assertEqual({ - '1': {'seqno': 4, 'probe': True, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, - '2': {'seqno': 5, 'probe': True, 'author': {tests.UID2: {'name': 'user2', 'order': 0, 'role': 3}}}, + agg1: {'seqno': 4, 'value': True, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, + agg2: {'seqno': 5, 'value': True, 'author': {tests.UID2: {'name': 'user2', 'order': 0, 'role': 1}}}, }, call(cp, method='GET', path=['document', guid, 'prop1'])) - self.assertRaises(http.Forbidden, call, cp, method='DELETE', path=['document', guid, 'prop1', '1'], principal=tests.UID2) - self.assertRaises(http.Forbidden, call, cp, method='DELETE', path=['document', guid, 'prop1', '2'], principal=tests.UID) + self.assertRaises(http.Forbidden, call, cp, method='DELETE', path=['document', guid, 'prop1', agg1], principal=tests.UID2) + self.assertRaises(http.Forbidden, call, cp, method='DELETE', path=['document', guid, 'prop1', agg2], principal=tests.UID) self.assertEqual({ - '1': {'seqno': 4, 'probe': True, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, - '2': {'seqno': 5, 'probe': True, 'author': {tests.UID2: {'name': 'user2', 'order': 0, 'role': 3}}}, + agg1: {'seqno': 4, 'value': True, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, + agg2: {'seqno': 5, 'value': True, 'author': {tests.UID2: {'name': 'user2', 'order': 0, 'role': 1}}}, }, call(cp, method='GET', path=['document', guid, 'prop1'])) - call(cp, method='DELETE', path=['document', guid, 'prop1', '1'], principal=tests.UID) + call(cp, method='DELETE', path=['document', guid, 'prop1', agg1], principal=tests.UID) self.assertEqual({ - '1': {'seqno': 6}, - '2': {'seqno': 5, 'probe': True, 'author': {tests.UID2: {'name': 'user2', 'order': 0, 'role': 3}}}, + agg1: {'seqno': 6, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, + agg2: {'seqno': 5, 'value': True, 'author': {tests.UID2: {'name': 'user2', 'order': 0, 'role': 1}}}, }, call(cp, method='GET', path=['document', guid, 'prop1'])) - call(cp, method='DELETE', path=['document', guid, 'prop1', '2'], principal=tests.UID2) + call(cp, method='DELETE', path=['document', guid, 'prop1', agg2], principal=tests.UID2) self.assertEqual({ - '1': {'seqno': 6}, - '2': {'seqno': 7}, + agg1: {'seqno': 6, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, + agg2: {'seqno': 7, 'author': {tests.UID2: {'name': 'user2', 'order': 0, 'role': 1}}}, }, call(cp, method='GET', path=['document', guid, 'prop1'])) - call(cp, method='POST', path=['document', guid, 'prop2'], principal=tests.UID, content={'guid': '1', 'probe': True}) + agg3 = call(cp, method='POST', path=['document', guid, 'prop2'], principal=tests.UID, content=True) self.assertEqual({ - '1': {'seqno': 8, 'probe': True, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, + agg3: {'seqno': 8, 'value': True, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, }, call(cp, method='GET', path=['document', guid, 'prop2'])) - self.assertRaises(http.Forbidden, call, cp, method='DELETE', path=['document', guid, 'prop2', '1'], principal=tests.UID2) + self.assertRaises(http.Forbidden, call, cp, method='DELETE', path=['document', guid, 'prop2', agg3], principal=tests.UID2) self.assertEqual({ - '1': {'seqno': 8, 'probe': True, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, + agg3: {'seqno': 8, 'value': True, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, }, call(cp, method='GET', path=['document', guid, 'prop2'])) - call(cp, method='DELETE', path=['document', guid, 'prop2', '1'], principal=tests.UID) + call(cp, method='DELETE', path=['document', guid, 'prop2', agg3], principal=tests.UID) self.assertEqual({ - '1': {'seqno': 9}, + agg3: {'seqno': 9, 'author': {tests.UID: {'name': 'user1', 'order': 0, 'role': 3}}}, }, call(cp, method='GET', path=['document', guid, 'prop2'])) |