diff options
Diffstat (limited to 'tests/units/node')
-rw-r--r-- | tests/units/node/__main__.py | 4 | ||||
-rwxr-xr-x | tests/units/node/master.py | 214 | ||||
-rwxr-xr-x | tests/units/node/model.py | 660 | ||||
-rwxr-xr-x | tests/units/node/node.py | 1058 | ||||
-rwxr-xr-x | tests/units/node/obs.py | 22 | ||||
-rwxr-xr-x | tests/units/node/stats_node.py | 338 | ||||
-rwxr-xr-x | tests/units/node/sync_online.py | 22 | ||||
-rwxr-xr-x | tests/units/node/volume.py | 826 |
8 files changed, 874 insertions, 2270 deletions
diff --git a/tests/units/node/__main__.py b/tests/units/node/__main__.py index ac37315..dfadaf3 100644 --- a/tests/units/node/__main__.py +++ b/tests/units/node/__main__.py @@ -4,16 +4,14 @@ from __init__ import tests from downloads import * from files import * -from master import * from node import * from obs import * -from stats_node import * from stats_user import * from sync import * from sync_master import * from sync_offline import * from sync_online import * -from volume import * +from model import * if __name__ == '__main__': tests.main() diff --git a/tests/units/node/master.py b/tests/units/node/master.py deleted file mode 100755 index b3eaa75..0000000 --- a/tests/units/node/master.py +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/env python -# sugar-lint: disable - -import os - -from __init__ import tests - -from sugar_network.node import obs -from sugar_network.client import IPCConnection -from sugar_network.toolkit import coroutine, enforce - - -class MasterTest(tests.Test): - - def test_Aliases(self): - self.override(obs, 'get_repos', lambda: [ - {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, - {'distributor_id': 'Debian', 'name': 'Debian-6.0', 'arches': ['x86']}, - {'distributor_id': 'Debian', 'name': 'Debian-7.0', 'arches': ['x86_64']}, - ]) - self.override(obs, 'resolve', lambda repo, arch, names: ['fake']) - - self.start_online_client() - ipc = IPCConnection() - - guid = ipc.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - - ipc.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['pkg1.bin', 'pkg2.bin']], - 'devel': [['pkg3.devel']], - }, - 'Debian': { - 'binary': [['pkg4.bin']], - 'devel': [['pkg5.devel', 'pkg6.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'success', 'binary': ['pkg1.bin', 'pkg2.bin'], 'devel': ['pkg3.devel']}, - 'Debian-6.0': {'status': 'success', 'binary': ['pkg4.bin'], 'devel': ['pkg5.devel', 'pkg6.devel']}, - 'Debian-7.0': {'status': 'success', 'binary': ['pkg4.bin'], 'devel': ['pkg5.devel', 'pkg6.devel']}, - }, - ipc.get(['context', guid, 'packages'])) - - def test_WrongAliases(self): - self.override(obs, 'get_repos', lambda: [ - {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, - {'distributor_id': 'Debian', 'name': 'Debian-6.0', 'arches': ['x86']}, - {'distributor_id': 'Debian', 'name': 'Debian-7.0', 'arches': ['x86_64']}, - ]) - self.override(obs, 'resolve', lambda repo, arch, names: enforce(False, 'resolve failed')) - - self.start_online_client() - ipc = IPCConnection() - - guid = ipc.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - - ipc.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['pkg1.bin', 'pkg2.bin']], - 'devel': [['pkg3.devel']], - }, - 'Debian': { - 'binary': [['pkg4.bin']], - 'devel': [['pkg5.devel', 'pkg6.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'resolve failed'}, - 'Debian-6.0': {'status': 'resolve failed'}, - 'Debian-7.0': {'status': 'resolve failed'}, - }, - ipc.get(['context', guid, 'packages'])) - - def test_MultipleAliases(self): - - def resolve(repo, arch, names): - enforce(not [i for i in names if 'fake' in i], 'resolve failed') - return ['fake'] - - self.override(obs, 'get_repos', lambda: [ - {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, - ]) - self.override(obs, 'resolve', resolve) - - self.start_online_client() - ipc = IPCConnection() - - guid = ipc.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - - ipc.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['fake.bin'], ['proper.bin'], ['not-reach.bin']], - 'devel': [['fake.devel'], ['proper.devel'], ['not-reach.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'success', 'binary': ['proper.bin'], 'devel': ['proper.devel']}, - }, - ipc.get(['context', guid, 'packages'])) - - ipc.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['proper.bin']], - 'devel': [['fake.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'resolve failed', 'binary': ['proper.bin']}, - }, - ipc.get(['context', guid, 'packages'])) - - ipc.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['fake.bin']], - 'devel': [['proper.devel']], - }, - }) - coroutine.dispatch() - self.assertEqual({ - 'Gentoo-2.1': {'status': 'resolve failed'}, - }, - ipc.get(['context', guid, 'packages'])) - - def test_InvalidateSolutions(self): - self.override(obs, 'get_repos', lambda: [ - {'distributor_id': 'Gentoo', 'name': 'Gentoo-2.1', 'arches': ['x86_64']}, - ]) - self.override(obs, 'resolve', lambda repo, arch, names: ['fake']) - - self.start_online_client() - ipc = IPCConnection() - - events = [] - def read_events(): - for event in ipc.subscribe(): - if event.get('resource') == 'release': - events.append(event) - job = coroutine.spawn(read_events) - - guid = ipc.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - }) - coroutine.sleep(.5) - self.assertEqual([], events) - - ipc.put(['context', guid, 'aliases'], { - 'Gentoo': { - 'binary': [['bin']], - 'devel': [['devel']], - }, - }) - coroutine.sleep(.5) - self.assertEqual([ - {'event': 'populate', 'resource': 'release', 'mtime': int(os.stat('master/release/index/mtime').st_mtime)}, - ], - events) - self.assertEqual({ - 'Gentoo-2.1': {'status': 'success', 'binary': ['bin'], 'devel': ['devel']}, - }, - ipc.get(['context', guid, 'packages'])) - - def test_InvalidateSolutionsOnDependenciesChanges(self): - self.start_online_client() - ipc = IPCConnection() - - events = [] - def read_events(): - for event in ipc.subscribe(): - if event.get('resource') == 'release': - events.append(event) - job = coroutine.spawn(read_events) - - guid = ipc.post(['context'], { - 'type': 'activity', - 'title': 'title', - 'summary': 'summary', - 'description': 'description', - 'dependencies': [], - }) - self.assertEqual(0, len(events)) - - ipc.put(['context', guid, 'dependencies'], ['foo']) - coroutine.sleep(.1) - self.assertEqual([ - {'event': 'populate', 'resource': 'release', 'mtime': int(os.stat('master/release/index/mtime').st_mtime)}, - ], - events) - - -if __name__ == '__main__': - tests.main() diff --git a/tests/units/node/model.py b/tests/units/node/model.py new file mode 100755 index 0000000..68215c1 --- /dev/null +++ b/tests/units/node/model.py @@ -0,0 +1,660 @@ +#!/usr/bin/env python +# sugar-lint: disable + +import os +import time + +from __init__ import tests + +from sugar_network import db, toolkit +from sugar_network.db import files +from sugar_network.client import Connection, keyfile, api_url +from sugar_network.model.user import User +from sugar_network.model.post import Post +from sugar_network.node import model, obs +from sugar_network.node.routes import NodeRoutes +from sugar_network.toolkit.coroutine import this +from sugar_network.toolkit.router import Request, Router +from sugar_network.toolkit import i18n, http, coroutine, enforce + + +class ModelTest(tests.Test): + + def test_IncrementReleasesSeqno(self): + events = [] + volume = self.start_master([User, model.Context, Post]) + this.broadcast = lambda x: events.append(x) + conn = Connection(auth=http.SugarAuth(keyfile.value)) + + context = conn.post(['context'], { + 'type': 'group', + 'title': 'Activity', + 'summary': 'summary', + 'description': 'description', + }) + self.assertEqual([ + ], [i for i in events if i['event'] == 'release']) + self.assertEqual(0, volume.releases_seqno.value) + + aggid = conn.post(['context', context, 'releases'], -1) + self.assertEqual([ + {'event': 'release', 'seqno': 1}, + ], [i for i in events if i['event'] == 'release']) + self.assertEqual(1, volume.releases_seqno.value) + + def test_diff(self): + self.override(time, 'time', lambda: 0) + self.override(NodeRoutes, 'authorize', lambda self, user, role: True) + + class Document(db.Resource): + + @db.indexed_property(slot=1) + def prop(self, value): + return value + + volume = self.start_master([User, Document]) + conn = Connection(auth=http.SugarAuth(keyfile.value)) + + guid1 = conn.post(['document'], {'prop': 'a'}) + self.utime('master/document/%s/%s' % (guid1[:2], guid1), 1) + guid2 = conn.post(['document'], {'prop': 'b'}) + self.utime('master/document/%s/%s' % (guid2[:2], guid2), 2) + + in_seq = toolkit.Sequence([[1, None]]) + self.assertEqual([ + {'resource': 'document'}, + {'guid': guid1, + 'diff': { + 'guid': {'value': guid1, 'mtime': 1}, + 'mtime': {'value': 0, 'mtime': 1}, + 'ctime': {'value': 0, 'mtime': 1}, + 'prop': {'value': 'a', 'mtime': 1}, + 'author': {'mtime': 1, 'value': {}}, + 'layer': {'mtime': 1, 'value': []}, + 'tags': {'mtime': 1, 'value': []}, + }, + }, + {'guid': guid2, + 'diff': { + 'guid': {'value': guid2, 'mtime': 2}, + 'mtime': {'value': 0, 'mtime': 2}, + 'ctime': {'value': 0, 'mtime': 2}, + 'prop': {'value': 'b', 'mtime': 2}, + 'author': {'mtime': 2, 'value': {}}, + 'layer': {'mtime': 2, 'value': []}, + 'tags': {'mtime': 2, 'value': []}, + }, + }, + {'commit': [[1, 2]]}, + ], + [i for i in model.diff(volume, in_seq)]) + self.assertEqual([[1, None]], in_seq) + + def test_diff_Partial(self): + self.override(time, 'time', lambda: 0) + self.override(NodeRoutes, 'authorize', lambda self, user, role: True) + + class Document(db.Resource): + + @db.indexed_property(slot=1) + def prop(self, value): + return value + + volume = self.start_master([User, Document]) + conn = Connection(auth=http.SugarAuth(keyfile.value)) + + guid1 = conn.post(['document'], {'prop': 'a'}) + self.utime('master/document/%s/%s' % (guid1[:2], guid1), 1) + guid2 = conn.post(['document'], {'prop': 'b'}) + self.utime('master/document/%s/%s' % (guid2[:2], guid2), 2) + + in_seq = toolkit.Sequence([[1, None]]) + patch = model.diff(volume, in_seq) + self.assertEqual({'resource': 'document'}, next(patch)) + self.assertEqual(guid1, next(patch)['guid']) + self.assertEqual({'commit': []}, patch.throw(StopIteration())) + try: + next(patch) + assert False + except StopIteration: + pass + + patch = model.diff(volume, in_seq) + self.assertEqual({'resource': 'document'}, next(patch)) + self.assertEqual(guid1, next(patch)['guid']) + self.assertEqual(guid2, next(patch)['guid']) + self.assertEqual({'commit': [[1, 1]]}, patch.throw(StopIteration())) + try: + next(patch) + assert False + except StopIteration: + pass + + def test_diff_Stretch(self): + self.override(time, 'time', lambda: 0) + self.override(NodeRoutes, 'authorize', lambda self, user, role: True) + + class Document(db.Resource): + + @db.indexed_property(slot=1) + def prop(self, value): + return value + + volume = self.start_master([User, Document]) + conn = Connection(auth=http.SugarAuth(keyfile.value)) + + guid1 = conn.post(['document'], {'prop': 'a'}) + self.utime('master/document/%s/%s' % (guid1[:2], guid1), 1) + guid2 = conn.post(['document'], {'prop': 'b'}) + volume['document'].delete(guid2) + guid3 = conn.post(['document'], {'prop': 'c'}) + self.utime('master/document/%s/%s' % (guid3[:2], guid3), 2) + guid4 = conn.post(['document'], {'prop': 'd'}) + volume['document'].delete(guid4) + guid5 = conn.post(['document'], {'prop': 'f'}) + self.utime('master/document/%s/%s' % (guid5[:2], guid5), 2) + + in_seq = toolkit.Sequence([[1, None]]) + patch = model.diff(volume, in_seq) + self.assertEqual({'resource': 'document'}, patch.send(None)) + self.assertEqual(guid1, patch.send(None)['guid']) + self.assertEqual(guid3, patch.send(None)['guid']) + self.assertEqual(guid5, patch.send(None)['guid']) + self.assertEqual({'commit': [[1, 1], [3, 3]]}, patch.throw(StopIteration())) + try: + patch.send(None) + assert False + except StopIteration: + pass + + patch = model.diff(volume, in_seq) + self.assertEqual({'resource': 'document'}, patch.send(None)) + self.assertEqual(guid1, patch.send(None)['guid']) + self.assertEqual(guid3, patch.send(None)['guid']) + self.assertEqual(guid5, patch.send(None)['guid']) + self.assertEqual({'commit': [[1, 5]]}, patch.send(None)) + try: + patch.send(None) + assert False + except StopIteration: + pass + + def test_diff_DoNotStretchContinuesPacket(self): + self.override(time, 'time', lambda: 0) + self.override(NodeRoutes, 'authorize', lambda self, user, role: True) + + class Document(db.Resource): + + @db.indexed_property(slot=1) + def prop(self, value): + return value + + volume = self.start_master([User, Document]) + conn = Connection(auth=http.SugarAuth(keyfile.value)) + + guid1 = conn.post(['document'], {'prop': 'a'}) + volume['document'].delete(guid1) + guid2 = conn.post(['document'], {'prop': 'b'}) + volume['document'].delete(guid2) + guid3 = conn.post(['document'], {'prop': 'c'}) + self.utime('master/document/%s/%s' % (guid3[:2], guid3), 2) + guid4 = conn.post(['document'], {'prop': 'd'}) + volume['document'].delete(guid4) + guid5 = conn.post(['document'], {'prop': 'f'}) + self.utime('master/document/%s/%s' % (guid5[:2], guid5), 2) + + in_seq = toolkit.Sequence([[1, None]]) + patch = model.diff(volume, in_seq, toolkit.Sequence([[1, 1]])) + self.assertEqual({'resource': 'document'}, patch.send(None)) + self.assertEqual(guid3, patch.send(None)['guid']) + self.assertEqual(guid5, patch.send(None)['guid']) + self.assertEqual({'commit': [[1, 1], [3, 3], [5, 5]]}, patch.send(None)) + try: + patch.send(None) + assert False + except StopIteration: + pass + + def test_diff_TheSameInSeqForAllDocuments(self): + self.override(time, 'time', lambda: 0) + self.override(NodeRoutes, 'authorize', lambda self, user, role: True) + + class Document1(db.Resource): + pass + + class Document2(db.Resource): + pass + + class Document3(db.Resource): + pass + + volume = self.start_master([User, Document1, Document2, Document3]) + conn = Connection(auth=http.SugarAuth(keyfile.value)) + + guid3 = conn.post(['document1'], {}) + self.utime('master/document/%s/%s' % (guid3[:2], guid3), 3) + guid2 = conn.post(['document2'], {}) + self.utime('master/document/%s/%s' % (guid2[:2], guid2), 2) + guid1 = conn.post(['document3'], {}) + self.utime('master/document/%s/%s' % (guid1[:2], guid1), 1) + + in_seq = toolkit.Sequence([[1, None]]) + patch = model.diff(volume, in_seq) + self.assertEqual({'resource': 'document1'}, patch.send(None)) + self.assertEqual(guid3, patch.send(None)['guid']) + self.assertEqual({'resource': 'document2'}, patch.send(None)) + self.assertEqual(guid2, patch.send(None)['guid']) + self.assertEqual({'resource': 'document3'}, patch.send(None)) + self.assertEqual(guid1, patch.send(None)['guid']) + self.assertEqual({'commit': [[1, 3]]}, patch.send(None)) + try: + patch.send(None) + assert False + except StopIteration: + pass + + def test_merge_Create(self): + self.override(time, 'time', lambda: 0) + self.override(NodeRoutes, 'authorize', lambda self, user, role: True) + + class Document1(db.Resource): + + @db.indexed_property(slot=1) + def prop(self, value): + return value + + class Document2(db.Resource): + pass + + self.touch(('master/db.seqno', '100')) + volume = self.start_master([Document1, Document2]) + + records = [ + {'resource': 'document1'}, + {'guid': '1', 'diff': { + 'guid': {'value': '1', 'mtime': 1.0}, + 'ctime': {'value': 2, 'mtime': 2.0}, + 'mtime': {'value': 3, 'mtime': 3.0}, + 'prop': {'value': '4', 'mtime': 4.0}, + }}, + {'resource': 'document2'}, + {'guid': '5', 'diff': { + 'guid': {'value': '5', 'mtime': 5.0}, + 'ctime': {'value': 6, 'mtime': 6.0}, + 'mtime': {'value': 7, 'mtime': 7.0}, + }}, + {'commit': [[1, 2]]}, + ] + self.assertEqual(([[1, 2]], [[101, 102]]), model.merge(volume, records)) + + self.assertEqual( + {'guid': '1', 'prop': '4', 'ctime': 2, 'mtime': 3}, + volume['document1'].get('1').properties(['guid', 'ctime', 'mtime', 'prop'])) + self.assertEqual(1, os.stat('master/document1/1/1/guid').st_mtime) + self.assertEqual(2, os.stat('master/document1/1/1/ctime').st_mtime) + self.assertEqual(3, os.stat('master/document1/1/1/mtime').st_mtime) + self.assertEqual(4, os.stat('master/document1/1/1/prop').st_mtime) + + self.assertEqual( + {'guid': '5', 'ctime': 6, 'mtime': 7}, + volume['document2'].get('5').properties(['guid', 'ctime', 'mtime'])) + self.assertEqual(5, os.stat('master/document2/5/5/guid').st_mtime) + self.assertEqual(6, os.stat('master/document2/5/5/ctime').st_mtime) + self.assertEqual(7, os.stat('master/document2/5/5/mtime').st_mtime) + + def test_merge_Update(self): + self.override(time, 'time', lambda: 0) + self.override(NodeRoutes, 'authorize', lambda self, user, role: True) + + class Document(db.Resource): + + @db.indexed_property(slot=1) + def prop(self, value): + return value + + self.touch(('master/db.seqno', '100')) + volume = db.Volume('master', [Document]) + volume['document'].create({'guid': '1', 'prop': '1', 'ctime': 1, 'mtime': 1}) + for i in os.listdir('master/document/1/1'): + os.utime('master/document/1/1/%s' % i, (2, 2)) + + records = [ + {'resource': 'document'}, + {'guid': '1', 'diff': {'prop': {'value': '2', 'mtime': 1.0}}}, + {'commit': [[1, 1]]}, + ] + self.assertEqual(([[1, 1]], []), model.merge(volume, records)) + self.assertEqual( + {'guid': '1', 'prop': '1', 'ctime': 1, 'mtime': 1}, + volume['document'].get('1').properties(['guid', 'ctime', 'mtime', 'prop'])) + self.assertEqual(2, os.stat('master/document/1/1/prop').st_mtime) + + records = [ + {'resource': 'document'}, + {'guid': '1', 'diff': {'prop': {'value': '3', 'mtime': 2.0}}}, + {'commit': [[2, 2]]}, + ] + self.assertEqual(([[2, 2]], []), model.merge(volume, records)) + self.assertEqual( + {'guid': '1', 'prop': '1', 'ctime': 1, 'mtime': 1}, + volume['document'].get('1').properties(['guid', 'ctime', 'mtime', 'prop'])) + self.assertEqual(2, os.stat('master/document/1/1/prop').st_mtime) + + records = [ + {'resource': 'document'}, + {'guid': '1', 'diff': {'prop': {'value': '4', 'mtime': 3.0}}}, + {'commit': [[3, 3]]}, + ] + self.assertEqual(([[3, 3]], [[102, 102]]), model.merge(volume, records)) + self.assertEqual( + {'guid': '1', 'prop': '4', 'ctime': 1, 'mtime': 1}, + volume['document'].get('1').properties(['guid', 'ctime', 'mtime', 'prop'])) + self.assertEqual(3, os.stat('master/document/1/1/prop').st_mtime) + + def test_merge_MultipleCommits(self): + self.override(time, 'time', lambda: 0) + + class Document(db.Resource): + + @db.stored_property() + def prop(self, value): + return value + + self.touch(('master/db.seqno', '100')) + volume = db.Volume('master', [Document]) + + def generator(): + for i in [ + {'resource': 'document'}, + {'commit': [[1, 1]]}, + {'guid': '1', 'diff': { + 'guid': {'value': '1', 'mtime': 1.0}, + 'ctime': {'value': 2, 'mtime': 2.0}, + 'mtime': {'value': 3, 'mtime': 3.0}, + 'prop': {'value': '4', 'mtime': 4.0}, + }}, + {'commit': [[2, 3]]}, + ]: + yield i + + records = generator() + self.assertEqual(([[1, 3]], [[101, 101]]), model.merge(volume, records)) + assert volume['document'].exists('1') + + def test_diff_ByLayers(self): + self.override(time, 'time', lambda: 0) + self.override(NodeRoutes, 'authorize', lambda self, user, role: True) + + class Context(db.Resource): + pass + + class Post(db.Resource): + pass + + this.request = Request() + volume = db.Volume('db', [Context, Post]) + volume['context'].create({'guid': '0', 'ctime': 1, 'mtime': 1, 'layer': ['layer0', 'common']}) + volume['context'].create({'guid': '1', 'ctime': 1, 'mtime': 1, 'layer': ['layer1']}) + volume['post'].create({'guid': '3', 'ctime': 3, 'mtime': 3, 'layer': 'layer3'}) + + volume['context'].update('0', {'tags': '0'}) + volume['context'].update('1', {'tags': '1'}) + volume['post'].update('3', {'tags': '3'}) + self.utime('db', 0) + + self.assertEqual(sorted([ + {'resource': 'context'}, + {'guid': '0', 'diff': {'tags': {'value': '0', 'mtime': 0}}}, + {'guid': '1', 'diff': {'tags': {'value': '1', 'mtime': 0}}}, + {'resource': 'post'}, + {'guid': '3', 'diff': {'tags': {'value': '3', 'mtime': 0}}}, + {'commit': [[4, 6]]}, + ]), + sorted([i for i in model.diff(volume, toolkit.Sequence([[4, None]]))])) + + self.assertEqual(sorted([ + {'resource': 'context'}, + {'guid': '0', 'diff': {'tags': {'value': '0', 'mtime': 0}}}, + {'guid': '1', 'diff': {'tags': {'value': '1', 'mtime': 0}}}, + {'resource': 'post'}, + {'guid': '3', 'diff': {'tags': {'value': '3', 'mtime': 0}}}, + {'commit': [[4, 6]]}, + ]), + sorted([i for i in model.diff(volume, toolkit.Sequence([[4, None]]), layer='layer1')])) + + self.assertEqual(sorted([ + {'resource': 'context'}, + {'guid': '0', 'diff': {'tags': {'value': '0', 'mtime': 0}}}, + {'resource': 'post'}, + {'guid': '3', 'diff': {'tags': {'value': '3', 'mtime': 0}}}, + {'commit': [[4, 6]]}, + ]), + sorted([i for i in model.diff(volume, toolkit.Sequence([[4, None]]), layer='layer2')])) + + self.assertEqual(sorted([ + {'resource': 'context'}, + {'guid': '0', 'diff': {'tags': {'value': '0', 'mtime': 0}}}, + {'resource': 'post'}, + {'guid': '3', 'diff': {'tags': {'value': '3', 'mtime': 0}}}, + {'commit': [[4, 6]]}, + ]), + sorted([i for i in model.diff(volume, toolkit.Sequence([[4, None]]), layer='foo')])) + + def test_Packages(self): + self.override(obs, 'get_repos', lambda: [ + {'lsb_id': 'Gentoo', 'lsb_release': '2.1', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, + {'lsb_id': 'Debian', 'lsb_release': '6.0', 'name': 'Debian-6.0', 'arches': ['x86']}, + {'lsb_id': 'Debian', 'lsb_release': '7.0', 'name': 'Debian-7.0', 'arches': ['x86_64']}, + ]) + self.override(obs, 'resolve', lambda repo, arch, names: ['fake']) + + volume = self.start_master([User, model.Context]) + conn = http.Connection(api_url.value, http.SugarAuth(keyfile.value)) + + guid = conn.post(['context'], { + 'type': 'package', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + }) + conn.put(['context', guid, 'releases', '*'], { + 'binary': ['pkg1.bin', 'pkg2.bin'], + 'devel': 'pkg3.devel', + }) + self.assertEqual({ + '*': { + 'seqno': 3, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['pkg1.bin', 'pkg2.bin'], 'devel': ['pkg3.devel']}, + }, + 'status': { + 'Gentoo-2.1': 'success', + 'Debian-6.0': 'success', + 'Debian-7.0': 'success', + }, + }, + volume['context'][guid]['releases']) + + guid = conn.post(['context'], { + 'type': 'package', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + }) + conn.put(['context', guid, 'releases', 'Gentoo'], { + 'binary': ['pkg1.bin', 'pkg2.bin'], + 'devel': 'pkg3.devel', + }) + self.assertEqual({ + 'Gentoo': { + 'seqno': 5, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['pkg1.bin', 'pkg2.bin'], 'devel': ['pkg3.devel']}, + }, + 'status': { + 'Gentoo-2.1': 'success', + }, + }, + volume['context'][guid]['releases']) + + guid = conn.post(['context'], { + 'type': 'package', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + }) + conn.put(['context', guid, 'releases', 'Debian-6.0'], { + 'binary': ['pkg1.bin', 'pkg2.bin'], + 'devel': 'pkg3.devel', + }) + self.assertEqual({ + 'Debian-6.0': { + 'seqno': 7, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['pkg1.bin', 'pkg2.bin'], 'devel': ['pkg3.devel']}, + }, + 'status': { + 'Debian-6.0': 'success', + }, + }, + volume['context'][guid]['releases']) + + def test_UnresolvedPackages(self): + self.override(obs, 'get_repos', lambda: [ + {'lsb_id': 'Gentoo', 'lsb_release': '2.1', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, + ]) + self.override(obs, 'resolve', lambda repo, arch, names: enforce(False, 'resolve failed')) + + volume = self.start_master([User, model.Context]) + conn = http.Connection(api_url.value, http.SugarAuth(keyfile.value)) + + guid = conn.post(['context'], { + 'type': 'package', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + }) + conn.put(['context', guid, 'releases', '*'], { + 'binary': ['pkg1.bin', 'pkg2.bin'], + 'devel': 'pkg3.devel', + }) + self.assertEqual({ + '*': { + 'seqno': 3, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['pkg1.bin', 'pkg2.bin'], 'devel': ['pkg3.devel']}, + }, + 'status': { + 'Gentoo-2.1': 'resolve failed', + }, + }, + volume['context'][guid]['releases']) + + def test_PackageOverrides(self): + self.override(obs, 'get_repos', lambda: [ + {'lsb_id': 'Gentoo', 'lsb_release': '2.1', 'name': 'Gentoo-2.1', 'arches': ['x86', 'x86_64']}, + {'lsb_id': 'Debian', 'lsb_release': '6.0', 'name': 'Debian-6.0', 'arches': ['x86']}, + {'lsb_id': 'Debian', 'lsb_release': '7.0', 'name': 'Debian-7.0', 'arches': ['x86_64']}, + ]) + + volume = self.start_master([User, model.Context]) + conn = http.Connection(api_url.value, http.SugarAuth(keyfile.value)) + guid = conn.post(['context'], { + 'type': 'package', + 'title': 'title', + 'summary': 'summary', + 'description': 'description', + }) + + self.override(obs, 'resolve', lambda repo, arch, names: enforce(False, '1')) + conn.put(['context', guid, 'releases', '*'], {'binary': '1'}) + self.assertEqual({ + '*': { + 'seqno': 3, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['1']}, + }, + 'status': { + 'Gentoo-2.1': '1', + 'Debian-6.0': '1', + 'Debian-7.0': '1', + }, + }, + volume['context'][guid]['releases']) + + self.override(obs, 'resolve', lambda repo, arch, names: enforce(False, '2')) + conn.put(['context', guid, 'releases', 'Debian'], {'binary': '2'}) + self.assertEqual({ + '*': { + 'seqno': 3, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['1']}, + }, + 'Debian': { + 'seqno': 4, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['2']}, + }, + 'status': { + 'Gentoo-2.1': '1', + 'Debian-6.0': '2', + 'Debian-7.0': '2', + }, + }, + volume['context'][guid]['releases']) + + self.override(obs, 'resolve', lambda repo, arch, names: enforce(False, '3')) + conn.put(['context', guid, 'releases', 'Debian-6.0'], {'binary': '3'}) + self.assertEqual({ + '*': { + 'seqno': 3, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['1']}, + }, + 'Debian': { + 'seqno': 4, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['2']}, + }, + 'Debian-6.0': { + 'seqno': 5, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['3']}, + }, + 'status': { + 'Gentoo-2.1': '1', + 'Debian-6.0': '3', + 'Debian-7.0': '2', + }, + }, + volume['context'][guid]['releases']) + + self.override(obs, 'resolve', lambda repo, arch, names: enforce(False, '4')) + conn.put(['context', guid, 'releases', 'Debian'], {'binary': '4'}) + self.assertEqual({ + '*': { + 'seqno': 3, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['1']}, + }, + 'Debian': { + 'seqno': 6, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['4']}, + }, + 'Debian-6.0': { + 'seqno': 5, + 'author': {tests.UID: {'name': tests.UID, 'order': 0, 'role': 3}}, + 'value': {'binary': ['3']}, + }, + 'status': { + 'Gentoo-2.1': '1', + 'Debian-6.0': '3', + 'Debian-7.0': '4', + }, + }, + volume['context'][guid]['releases']) + + +if __name__ == '__main__': + tests.main() 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'])) diff --git a/tests/units/node/obs.py b/tests/units/node/obs.py index bf43ed6..21b53a0 100755 --- a/tests/units/node/obs.py +++ b/tests/units/node/obs.py @@ -39,8 +39,8 @@ class ObsTest(tests.Test): ])) self.assertEqual([ - {'distributor_id': 'Debian', 'name': 'Debian-6.0', 'arches': ['i586', 'x86_64']}, - {'distributor_id': 'Fedora', 'name': 'Fedora-11', 'arches': ['i586']}, + {'lsb_id': 'Debian', 'lsb_release': '6.0', 'name': 'Debian-6.0', 'arches': ['i586', 'x86_64']}, + {'lsb_id': 'Fedora', 'lsb_release': '11', 'name': 'Fedora-11', 'arches': ['i586']}, ], obs.get_repos()) @@ -51,21 +51,10 @@ class ObsTest(tests.Test): 'project': 'base', 'repository': 'repo', 'arch': 'arch', - 'package': 'pkg1', + 'package': ['pkg1', 'pkg2'], }}, [ '<resolve>', ' <binary name="pygame" url="http://pkg1.prm" arch="arch"/>', - '</resolve>', - ], - ), - (('GET', ['resolve']), - {'allowed': (400, 404), 'params': { - 'project': 'base', - 'repository': 'repo', - 'arch': 'arch', - 'package': 'pkg2', - }}, - [ '<resolve>', ' <binary name="pygame" url="http://pkg2.prm" arch="arch"/>', '</resolve>', ], @@ -122,10 +111,7 @@ class ObsTest(tests.Test): ('http://pkg2-2.prm', ['4']), ])) - obs.presolve({ - 'Debian': {'binary': [['deb']]}, - 'Fedora': {'binary': [['pkg1', 'pkg2']], 'devel': [['pkg3']]}, - }, '.') + obs.presolve(None, ['pkg1', 'pkg2'], '.') self.assertEqual({ 'arch': [ diff --git a/tests/units/node/stats_node.py b/tests/units/node/stats_node.py deleted file mode 100755 index eab7fb8..0000000 --- a/tests/units/node/stats_node.py +++ /dev/null @@ -1,338 +0,0 @@ -#!/usr/bin/env python -# sugar-lint: disable - -import time - -from __init__ import tests - -from sugar_network import db, model -from sugar_network.node.stats_node import Sniffer, stats_node_step -from sugar_network.toolkit.rrd import Rrd -from sugar_network.toolkit.router import Request - - -class StatsTest(tests.Test): - - def test_InitializeTotals(self): - volume = db.Volume('local', model.RESOURCES) - - stats = Sniffer(volume, 'stats/node') - self.assertEqual(0, stats._stats['user']['total']) - self.assertEqual(0, stats._stats['context']['total']) - self.assertEqual(0, stats._stats['post']['total']) - - volume['user'].create({'guid': 'user', 'name': 'user', 'pubkey': ''}) - volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''}) - volume['post'].create({'guid': 'post', 'context': 'context', 'title': '', 'message': '', 'type': 'update'}) - - stats = Sniffer(volume, 'stats/node') - self.assertEqual(1, stats._stats['user']['total']) - self.assertEqual(1, stats._stats['context']['total']) - self.assertEqual(1, stats._stats['post']['total']) - - def test_POSTs(self): - volume = db.Volume('local', model.RESOURCES) - stats = Sniffer(volume, 'stats/node') - - request = Request(method='POST', path=['context']) - request.principal = 'user' - stats.log(request) - stats.log(request) - stats.log(request) - self.assertEqual(3, stats._stats['context']['total']) - - def test_DELETEs(self): - volume = db.Volume('local', model.RESOURCES) - stats = Sniffer(volume, 'stats/node') - - request = Request(method='DELETE', path=['context']) - request.principal = 'user' - stats.log(request) - stats.log(request) - stats.log(request) - self.assertEqual(-3, stats._stats['context']['total']) - - def test_Posts(self): - volume = db.Volume('local', model.RESOURCES) - stats = Sniffer(volume, 'stats/node') - volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''}) - volume['post'].create({'guid': 'topic', 'type': 'update', 'context': 'context', 'title': '', 'message': ''}) - - request = Request(method='POST', path=['post']) - request.principal = 'user' - request.content = {'context': 'context', 'vote': 1, 'type': 'review', 'title': '', 'message': ''} - stats.log(request) - self.assertEqual(1, stats._stats['post']['total']) - - request = Request(method='POST', path=['post']) - request.principal = 'user' - request.content = {'context': 'context', 'vote': 2, 'type': 'review', 'title': '', 'message': ''} - stats.log(request) - self.assertEqual(2, stats._stats['post']['total']) - - request = Request(method='POST', path=['post']) - request.principal = 'user' - request.content = {'topic': 'topic', 'vote': 3, 'type': 'feedback', 'title': '', 'message': ''} - stats.log(request) - self.assertEqual(3, stats._stats['post']['total']) - - stats.commit_objects() - self.assertEqual([2, 3], volume['context'].get('context')['rating']) - self.assertEqual([1, 3], volume['post'].get('topic')['rating']) - - def test_ContextDownloaded(self): - volume = db.Volume('local', model.RESOURCES) - stats = Sniffer(volume, 'stats/node') - volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''}) - volume['release'].create({'guid': 'release', 'context': 'context', 'license': 'GPLv3', 'version': '1', 'date': 0, 'stability': 'stable', 'notes': ''}) - - request = Request(method='GET', path=['release', 'release', 'fake']) - request.principal = 'user' - stats.log(request) - self.assertEqual(0, stats._stats['context']['downloaded']) - - request = Request(method='GET', path=['release', 'release', 'data']) - request.principal = 'user' - stats.log(request) - self.assertEqual(1, stats._stats['context']['downloaded']) - - def test_ContextReleased(self): - volume = db.Volume('local', model.RESOURCES) - stats = Sniffer(volume, 'stats/node') - volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''}) - - request = Request(method='POST', path=['release']) - request.principal = 'user' - request.content = {'context': 'context'} - stats.log(request) - self.assertEqual(1, stats._stats['context']['released']) - - def test_ContextFailed(self): - volume = db.Volume('local', model.RESOURCES) - stats = Sniffer(volume, 'stats/node') - volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''}) - - request = Request(method='POST', path=['report']) - request.principal = 'user' - request.content = {'context': 'context'} - stats.log(request) - self.assertEqual(1, stats._stats['context']['failed']) - - def test_PostDownloaded(self): - volume = db.Volume('local', model.RESOURCES) - stats = Sniffer(volume, 'stats/node') - volume['post'].create({'guid': 'topic', 'type': 'object', 'context': 'context', 'title': '', 'message': ''}) - - request = Request(method='GET', path=['post', 'topic', 'fake']) - request.principal = 'user' - stats.log(request) - self.assertEqual(0, stats._stats['post']['downloaded']) - - request = Request(method='GET', path=['post', 'topic', 'data']) - request.principal = 'user' - stats.log(request) - self.assertEqual(1, stats._stats['post']['downloaded']) - - def test_Commit(self): - volume = db.Volume('local', model.RESOURCES) - volume['user'].create({'guid': 'user', 'name': 'user', 'pubkey': ''}) - volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''}) - volume['post'].create({'guid': 'review', 'context': 'context', 'type': 'review', 'title': '', 'message': '', 'vote': 5}) - - stats = Sniffer(volume, 'stats/node') - request = Request(method='GET', path=['user', 'user']) - request.principal = 'user' - stats.log(request) - request = Request(method='GET', path=['context', 'context']) - request.principal = 'user' - stats.log(request) - request = Request(method='GET', path=['post', 'review']) - request.principal = 'user' - stats.log(request) - - self.assertEqual(1, stats._stats['user']['total']) - self.assertEqual(1, stats._stats['context']['total']) - self.assertEqual(1, stats._stats['post']['total']) - - ts = int(time.time()) - stats.commit(ts) - stats.commit_objects() - - self.assertEqual(1, stats._stats['user']['total']) - self.assertEqual(1, stats._stats['context']['total']) - self.assertEqual(1, stats._stats['post']['total']) - - self.assertEqual([ - [('post', ts, { - 'downloaded': 0.0, - 'total': 1.0, - })], - [('user', ts, { - 'total': 1.0, - })], - [('context', ts, { - 'failed': 0.0, - 'downloaded': 0.0, - 'total': 1.0, - 'released': 0.0, - })], - ], - [[(j.name,) + i for i in j.get(j.last, j.last)] for j in Rrd('stats/node', 1)]) - - def test_CommitContextStats(self): - volume = db.Volume('local', model.RESOURCES) - - volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''}) - volume['release'].create({'guid': 'release', 'context': 'context', 'license': 'GPLv3', 'version': '1', 'date': 0, 'stability': 'stable', 'notes': ''}) - - self.assertEqual(0, volume['context'].get('context')['downloads']) - self.assertEqual([0, 0], volume['context'].get('context')['rating']) - - stats = Sniffer(volume, 'stats/node') - request = Request(method='GET', path=['release', 'release', 'data']) - request.principal = 'user' - stats.log(request) - request = Request(method='POST', path=['post']) - request.principal = 'user' - request.content = {'context': 'context', 'vote': 5, 'type': 'review', 'title': '', 'message': ''} - stats.log(request) - - stats.commit() - stats.commit_objects() - - self.assertEqual(1, volume['context'].get('context')['downloads']) - self.assertEqual([1, 5], volume['context'].get('context')['rating']) - - stats.commit() - stats.commit_objects() - - self.assertEqual(1, volume['context'].get('context')['downloads']) - self.assertEqual([1, 5], volume['context'].get('context')['rating']) - - stats = Sniffer(volume, 'stats/node') - request = Request(method='GET', path=['release', 'release', 'data']) - request.principal = 'user' - stats.log(request) - request = Request(method='POST', path=['post']) - request.principal = 'user' - request.content = {'context': 'context', 'vote': 1, 'type': 'review', 'title': '', 'message': ''} - stats.log(request) - stats.commit() - stats.commit_objects() - - self.assertEqual(2, volume['context'].get('context')['downloads']) - self.assertEqual([2, 6], volume['context'].get('context')['rating']) - - def test_CommitTopicStats(self): - volume = db.Volume('local', model.RESOURCES) - - volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''}) - volume['post'].create({'guid': 'topic', 'type': 'object', 'context': 'context', 'title': '', 'message': ''}) - - self.assertEqual(0, volume['post'].get('topic')['downloads']) - self.assertEqual([0, 0], volume['post'].get('topic')['rating']) - - stats = Sniffer(volume, 'stats/node') - request = Request(method='GET', path=['post', 'topic', 'data']) - request.principal = 'user' - stats.log(request) - request = Request(method='POST', path=['post']) - request.principal = 'user' - request.content = {'topic': 'topic', 'vote': 5, 'type': 'feedback'} - stats.log(request) - stats.commit() - stats.commit_objects() - - self.assertEqual(1, volume['post'].get('topic')['downloads']) - self.assertEqual([1, 5], volume['post'].get('topic')['rating']) - - stats.commit() - stats.commit_objects() - - self.assertEqual(1, volume['post'].get('topic')['downloads']) - self.assertEqual([1, 5], volume['post'].get('topic')['rating']) - - request = Request(method='GET', path=['post', 'topic', 'data']) - request.principal = 'user' - stats.log(request) - request = Request(method='POST', path=['post']) - request.principal = 'user' - request.content = {'topic': 'topic', 'vote': 1, 'type': 'feedback'} - stats.log(request) - stats.commit() - stats.commit_objects() - - self.assertEqual(2, volume['post'].get('topic')['downloads']) - self.assertEqual([2, 6], volume['post'].get('topic')['rating']) - - def test_Suspend(self): - stats_node_step.value = 5 - volume = db.Volume('local', model.RESOURCES) - volume['context'].create({'guid': 'context', 'type': 'activity', 'title': '', 'summary': '', 'description': ''}) - volume['release'].create({'guid': 'impl', 'context': 'context', 'license': 'GPLv3', 'version': '1', 'date': 0, 'stability': 'stable', 'notes': ''}) - - ts = self.ts = 1000000000 - self.override(time, 'time', lambda: self.ts) - - stats = Sniffer(volume, 'stats') - request = Request(method='POST', path=['context']) - stats.log(request) - request = Request(method='GET', path=['release', 'impl', 'data'], context='context') - stats.log(request) - stats.suspend() - - rdb = Rrd('stats', 1)['context'] - self.assertEqual([ - ], - [i for i in rdb.get(ts, ts + 10)]) - - stats = Sniffer(volume, 'stats') - stats.suspend() - - rdb = Rrd('stats', 1)['context'] - self.assertEqual([ - ], - [i for i in rdb.get(ts, ts + 10)]) - - self.ts += 6 - stats = Sniffer(volume, 'stats') - - rdb = Rrd('stats', 1)['context'] - self.assertEqual([ - (ts + 0, {'failed': 0.0, 'downloaded': 0.0, 'total': 0.0, 'released': 0.0}), - (ts + 5, {'failed': 0.0, 'downloaded': 1.0, 'total': 2.0, 'released': 0.0}), - ], - [i for i in rdb.get(ts, ts + 20)]) - - request = Request(method='POST', path=['context']) - stats.log(request) - request = Request(method='GET', path=['release', 'impl', 'data'], context='context') - stats.log(request) - request = Request(method='GET', path=['release', 'impl', 'data'], context='context') - stats.log(request) - stats.suspend() - - stats = Sniffer(volume, 'stats') - stats.suspend() - - rdb = Rrd('stats', 1)['context'] - self.assertEqual([ - (ts + 0, {'failed': 0.0, 'downloaded': 0.0, 'total': 0.0, 'released': 0.0}), - (ts + 5, {'failed': 0.0, 'downloaded': 1.0, 'total': 2.0, 'released': 0.0}), - ], - [i for i in rdb.get(ts, ts + 10)]) - - self.ts += 6 - stats = Sniffer(volume, 'stats') - - rdb = Rrd('stats', 1)['context'] - self.assertEqual([ - (ts + 0, {'failed': 0.0, 'downloaded': 0.0, 'total': 0.0, 'released': 0.0}), - (ts + 5, {'failed': 0.0, 'downloaded': 1.0, 'total': 2.0, 'released': 0.0}), - (ts + 10, {'failed': 0.0, 'downloaded': 3.0, 'total': 3.0, 'released': 0.0}), - ], - [i for i in rdb.get(ts, ts + 20)]) - - -if __name__ == '__main__': - tests.main() diff --git a/tests/units/node/sync_online.py b/tests/units/node/sync_online.py index 7ee6dcb..e2c864a 100755 --- a/tests/units/node/sync_online.py +++ b/tests/units/node/sync_online.py @@ -44,11 +44,11 @@ class SyncOnlineTest(tests.Test): def type(self, value): return value - @db.indexed_property(slot=1, prefix='N', full_text=True, localized=True) + @db.indexed_property(db.Localized, slot=1, prefix='N', full_text=True) def title(self, value): return value - @db.indexed_property(prefix='D', full_text=True, localized=True) + @db.indexed_property(db.Localized, prefix='D', full_text=True) def message(self, value): return value @@ -80,8 +80,8 @@ class SyncOnlineTest(tests.Test): self.assertEqual([[4, None]], json.load(file('slave/pull.sequence'))) self.assertEqual([[2, None]], json.load(file('slave/push.sequence'))) - guid1 = client.post(['document'], {'context': '', 'message': '1', 'title': '', 'type': 'comment'}) - guid2 = client.post(['document'], {'context': '', 'message': '2', 'title': '', 'type': 'comment'}) + guid1 = client.post(['document'], {'context': '', 'message': '1', 'title': '', 'type': 'post'}) + guid2 = client.post(['document'], {'context': '', 'message': '2', 'title': '', 'type': 'post'}) client.post(cmd='online-sync') self.assertEqual([ @@ -92,7 +92,7 @@ class SyncOnlineTest(tests.Test): self.assertEqual([[6, None]], json.load(file('slave/pull.sequence'))) self.assertEqual([[4, None]], json.load(file('slave/push.sequence'))) - guid3 = client.post(['document'], {'context': '', 'message': '3', 'title': '', 'type': 'comment'}) + guid3 = client.post(['document'], {'context': '', 'message': '3', 'title': '', 'type': 'post'}) client.post(cmd='online-sync') self.assertEqual([ {'guid': guid1, 'message': {'en-us': '1'}}, @@ -128,7 +128,7 @@ class SyncOnlineTest(tests.Test): client.put(['document', guid1], {'message': 'a'}) client.put(['document', guid2], {'message': 'b'}) client.put(['document', guid3], {'message': 'c'}) - guid4 = client.post(['document'], {'context': '', 'message': 'd', 'title': '', 'type': 'comment'}) + guid4 = client.post(['document'], {'context': '', 'message': 'd', 'title': '', 'type': 'post'}) client.delete(['document', guid2]) client.post(cmd='online-sync') self.assertEqual([ @@ -158,8 +158,8 @@ class SyncOnlineTest(tests.Test): self.assertEqual([[4, None]], json.load(file('slave/pull.sequence'))) self.assertEqual([[2, None]], json.load(file('slave/push.sequence'))) - guid1 = client.post(['document'], {'context': '', 'message': '1', 'title': '', 'type': 'comment'}) - guid2 = client.post(['document'], {'context': '', 'message': '2', 'title': '', 'type': 'comment'}) + guid1 = client.post(['document'], {'context': '', 'message': '1', 'title': '', 'type': 'post'}) + guid2 = client.post(['document'], {'context': '', 'message': '2', 'title': '', 'type': 'post'}) slave_client.post(cmd='online-sync') self.assertEqual([ @@ -170,7 +170,7 @@ class SyncOnlineTest(tests.Test): self.assertEqual([[6, None]], json.load(file('slave/pull.sequence'))) self.assertEqual([[2, None]], json.load(file('slave/push.sequence'))) - guid3 = client.post(['document'], {'context': '', 'message': '3', 'title': '', 'type': 'comment'}) + guid3 = client.post(['document'], {'context': '', 'message': '3', 'title': '', 'type': 'post'}) slave_client.post(cmd='online-sync') self.assertEqual([ {'guid': guid1, 'message': {'en-us': '1'}}, @@ -206,7 +206,7 @@ class SyncOnlineTest(tests.Test): client.put(['document', guid1], {'message': 'a'}) client.put(['document', guid2], {'message': 'b'}) client.put(['document', guid3], {'message': 'c'}) - guid4 = client.post(['document'], {'context': '', 'message': 'd', 'title': '', 'type': 'comment'}) + guid4 = client.post(['document'], {'context': '', 'message': 'd', 'title': '', 'type': 'post'}) client.delete(['document', guid2]) slave_client.post(cmd='online-sync') self.assertEqual([ @@ -252,7 +252,7 @@ class SyncOnlineTest(tests.Test): self.assertEqual([[4, None]], json.load(file('slave/pull.sequence'))) self.assertEqual([[2, None]], json.load(file('slave/push.sequence'))) - guid = slave.post(['document'], {'context': '', 'message': '1', 'title': '1', 'type': 'comment'}) + guid = slave.post(['document'], {'context': '', 'message': '1', 'title': '1', 'type': 'post'}) slave.post(cmd='online-sync') coroutine.sleep(1) diff --git a/tests/units/node/volume.py b/tests/units/node/volume.py deleted file mode 100755 index 01e71a7..0000000 --- a/tests/units/node/volume.py +++ /dev/null @@ -1,826 +0,0 @@ -#!/usr/bin/env python -# sugar-lint: disable - -import os -import time -import urllib2 -import hashlib -from cStringIO import StringIO - -from __init__ import tests - -from sugar_network import db, toolkit, model -from sugar_network.node.volume import diff, merge -from sugar_network.node.stats_node import Sniffer -from sugar_network.node.routes import NodeRoutes -from sugar_network.toolkit.rrd import Rrd -from sugar_network.toolkit.router import Router, Request, Response, fallbackroute, Blob, ACL, route - - -current_time = time.time - - -class VolumeTest(tests.Test): - - def setUp(self): - tests.Test.setUp(self) - self.override(time, 'time', lambda: 0) - self.override(NodeRoutes, 'authorize', lambda self, user, role: True) - - def test_diff(self): - - class Document(db.Resource): - - @db.indexed_property(slot=1) - def prop(self, value): - return value - - volume = db.Volume('db', [Document]) - cp = NodeRoutes('guid', volume) - - guid1 = call(cp, method='POST', document='document', content={'prop': 'a'}) - self.utime('db/document/%s/%s' % (guid1[:2], guid1), 1) - guid2 = call(cp, method='POST', document='document', content={'prop': 'b'}) - self.utime('db/document/%s/%s' % (guid2[:2], guid2), 2) - - in_seq = toolkit.Sequence([[1, None]]) - self.assertEqual([ - {'resource': 'document'}, - {'guid': guid1, - 'diff': { - 'guid': {'value': guid1, 'mtime': 1}, - 'mtime': {'value': 0, 'mtime': 1}, - 'ctime': {'value': 0, 'mtime': 1}, - 'prop': {'value': 'a', 'mtime': 1}, - 'author': {'mtime': 1, 'value': {}}, - 'layer': {'mtime': 1, 'value': []}, - 'tags': {'mtime': 1, 'value': []}, - }, - }, - {'guid': guid2, - 'diff': { - 'guid': {'value': guid2, 'mtime': 2}, - 'mtime': {'value': 0, 'mtime': 2}, - 'ctime': {'value': 0, 'mtime': 2}, - 'prop': {'value': 'b', 'mtime': 2}, - 'author': {'mtime': 2, 'value': {}}, - 'layer': {'mtime': 2, 'value': []}, - 'tags': {'mtime': 2, 'value': []}, - }, - }, - {'commit': [[1, 2]]}, - ], - [i for i in diff(volume, in_seq)]) - self.assertEqual([[1, None]], in_seq) - - def test_diff_Partial(self): - - class Document(db.Resource): - - @db.indexed_property(slot=1) - def prop(self, value): - return value - - volume = db.Volume('db', [Document]) - cp = NodeRoutes('guid', volume) - - guid1 = call(cp, method='POST', document='document', content={'prop': 'a'}) - self.utime('db/document/%s/%s' % (guid1[:2], guid1), 1) - guid2 = call(cp, method='POST', document='document', content={'prop': 'b'}) - self.utime('db/document/%s/%s' % (guid2[:2], guid2), 2) - - in_seq = toolkit.Sequence([[1, None]]) - patch = diff(volume, in_seq) - self.assertEqual({'resource': 'document'}, next(patch)) - self.assertEqual(guid1, next(patch)['guid']) - self.assertEqual({'commit': []}, patch.throw(StopIteration())) - try: - next(patch) - assert False - except StopIteration: - pass - - patch = diff(volume, in_seq) - self.assertEqual({'resource': 'document'}, next(patch)) - self.assertEqual(guid1, next(patch)['guid']) - self.assertEqual(guid2, next(patch)['guid']) - self.assertEqual({'commit': [[1, 1]]}, patch.throw(StopIteration())) - try: - next(patch) - assert False - except StopIteration: - pass - - def test_diff_Stretch(self): - - class Document(db.Resource): - - @db.indexed_property(slot=1) - def prop(self, value): - return value - - volume = db.Volume('db', [Document]) - cp = NodeRoutes('guid', volume) - - guid1 = call(cp, method='POST', document='document', content={'prop': 'a'}) - self.utime('db/document/%s/%s' % (guid1[:2], guid1), 1) - guid2 = call(cp, method='POST', document='document', content={'prop': 'b'}) - volume['document'].delete(guid2) - guid3 = call(cp, method='POST', document='document', content={'prop': 'c'}) - self.utime('db/document/%s/%s' % (guid3[:2], guid3), 2) - guid4 = call(cp, method='POST', document='document', content={'prop': 'd'}) - volume['document'].delete(guid4) - guid5 = call(cp, method='POST', document='document', content={'prop': 'f'}) - self.utime('db/document/%s/%s' % (guid5[:2], guid5), 2) - - in_seq = toolkit.Sequence([[1, None]]) - patch = diff(volume, in_seq) - self.assertEqual({'resource': 'document'}, patch.send(None)) - self.assertEqual(guid1, patch.send(None)['guid']) - self.assertEqual(guid3, patch.send(None)['guid']) - self.assertEqual(guid5, patch.send(None)['guid']) - self.assertEqual({'commit': [[1, 1], [3, 3]]}, patch.throw(StopIteration())) - try: - patch.send(None) - assert False - except StopIteration: - pass - - patch = diff(volume, in_seq) - self.assertEqual({'resource': 'document'}, patch.send(None)) - self.assertEqual(guid1, patch.send(None)['guid']) - self.assertEqual(guid3, patch.send(None)['guid']) - self.assertEqual(guid5, patch.send(None)['guid']) - self.assertEqual({'commit': [[1, 5]]}, patch.send(None)) - try: - patch.send(None) - assert False - except StopIteration: - pass - - def test_diff_DoNotStretchContinuesPacket(self): - - class Document(db.Resource): - - @db.indexed_property(slot=1) - def prop(self, value): - return value - - volume = db.Volume('db', [Document]) - cp = NodeRoutes('guid', volume) - - guid1 = call(cp, method='POST', document='document', content={'prop': 'a'}) - volume['document'].delete(guid1) - guid2 = call(cp, method='POST', document='document', content={'prop': 'b'}) - volume['document'].delete(guid2) - guid3 = call(cp, method='POST', document='document', content={'prop': 'c'}) - self.utime('db/document/%s/%s' % (guid3[:2], guid3), 2) - guid4 = call(cp, method='POST', document='document', content={'prop': 'd'}) - volume['document'].delete(guid4) - guid5 = call(cp, method='POST', document='document', content={'prop': 'f'}) - self.utime('db/document/%s/%s' % (guid5[:2], guid5), 2) - - in_seq = toolkit.Sequence([[1, None]]) - patch = diff(volume, in_seq, toolkit.Sequence([[1, 1]])) - self.assertEqual({'resource': 'document'}, patch.send(None)) - self.assertEqual(guid3, patch.send(None)['guid']) - self.assertEqual(guid5, patch.send(None)['guid']) - self.assertEqual({'commit': [[1, 1], [3, 3], [5, 5]]}, patch.send(None)) - try: - patch.send(None) - assert False - except StopIteration: - pass - - def test_diff_TheSameInSeqForAllDocuments(self): - - class Document1(db.Resource): - pass - - class Document2(db.Resource): - pass - - class Document3(db.Resource): - pass - - volume = db.Volume('db', [Document1, Document2, Document3]) - cp = NodeRoutes('guid', volume) - - guid3 = call(cp, method='POST', document='document1', content={}) - self.utime('db/document/%s/%s' % (guid3[:2], guid3), 3) - guid2 = call(cp, method='POST', document='document2', content={}) - self.utime('db/document/%s/%s' % (guid2[:2], guid2), 2) - guid1 = call(cp, method='POST', document='document3', content={}) - self.utime('db/document/%s/%s' % (guid1[:2], guid1), 1) - - in_seq = toolkit.Sequence([[1, None]]) - patch = diff(volume, in_seq) - self.assertEqual({'resource': 'document1'}, patch.send(None)) - self.assertEqual(guid3, patch.send(None)['guid']) - self.assertEqual({'resource': 'document2'}, patch.send(None)) - self.assertEqual(guid2, patch.send(None)['guid']) - self.assertEqual({'resource': 'document3'}, patch.send(None)) - self.assertEqual(guid1, patch.send(None)['guid']) - self.assertEqual({'commit': [[1, 3]]}, patch.send(None)) - try: - patch.send(None) - assert False - except StopIteration: - pass - - def test_merge_Create(self): - - class Document1(db.Resource): - - @db.indexed_property(slot=1) - def prop(self, value): - return value - - class Document2(db.Resource): - pass - - self.touch(('db/seqno', '100')) - volume = db.Volume('db', [Document1, Document2]) - - records = [ - {'resource': 'document1'}, - {'guid': '1', 'diff': { - 'guid': {'value': '1', 'mtime': 1.0}, - 'ctime': {'value': 2, 'mtime': 2.0}, - 'mtime': {'value': 3, 'mtime': 3.0}, - 'prop': {'value': '4', 'mtime': 4.0}, - }}, - {'resource': 'document2'}, - {'guid': '5', 'diff': { - 'guid': {'value': '5', 'mtime': 5.0}, - 'ctime': {'value': 6, 'mtime': 6.0}, - 'mtime': {'value': 7, 'mtime': 7.0}, - }}, - {'commit': [[1, 2]]}, - ] - self.assertEqual(([[1, 2]], [[101, 102]]), merge(volume, records)) - - self.assertEqual( - {'guid': '1', 'prop': '4', 'ctime': 2, 'mtime': 3}, - volume['document1'].get('1').properties(['guid', 'ctime', 'mtime', 'prop'])) - self.assertEqual(1, os.stat('db/document1/1/1/guid').st_mtime) - self.assertEqual(2, os.stat('db/document1/1/1/ctime').st_mtime) - self.assertEqual(3, os.stat('db/document1/1/1/mtime').st_mtime) - self.assertEqual(4, os.stat('db/document1/1/1/prop').st_mtime) - - self.assertEqual( - {'guid': '5', 'ctime': 6, 'mtime': 7}, - volume['document2'].get('5').properties(['guid', 'ctime', 'mtime'])) - self.assertEqual(5, os.stat('db/document2/5/5/guid').st_mtime) - self.assertEqual(6, os.stat('db/document2/5/5/ctime').st_mtime) - self.assertEqual(7, os.stat('db/document2/5/5/mtime').st_mtime) - - def test_merge_Update(self): - - class Document(db.Resource): - - @db.indexed_property(slot=1) - def prop(self, value): - return value - - self.touch(('db/seqno', '100')) - volume = db.Volume('db', [Document]) - volume['document'].create({'guid': '1', 'prop': '1', 'ctime': 1, 'mtime': 1}) - for i in os.listdir('db/document/1/1'): - os.utime('db/document/1/1/%s' % i, (2, 2)) - - records = [ - {'resource': 'document'}, - {'guid': '1', 'diff': {'prop': {'value': '2', 'mtime': 1.0}}}, - {'commit': [[1, 1]]}, - ] - self.assertEqual(([[1, 1]], []), merge(volume, records)) - self.assertEqual( - {'guid': '1', 'prop': '1', 'ctime': 1, 'mtime': 1}, - volume['document'].get('1').properties(['guid', 'ctime', 'mtime', 'prop'])) - self.assertEqual(2, os.stat('db/document/1/1/prop').st_mtime) - - records = [ - {'resource': 'document'}, - {'guid': '1', 'diff': {'prop': {'value': '3', 'mtime': 2.0}}}, - {'commit': [[2, 2]]}, - ] - self.assertEqual(([[2, 2]], []), merge(volume, records)) - self.assertEqual( - {'guid': '1', 'prop': '1', 'ctime': 1, 'mtime': 1}, - volume['document'].get('1').properties(['guid', 'ctime', 'mtime', 'prop'])) - self.assertEqual(2, os.stat('db/document/1/1/prop').st_mtime) - - records = [ - {'resource': 'document'}, - {'guid': '1', 'diff': {'prop': {'value': '4', 'mtime': 3.0}}}, - {'commit': [[3, 3]]}, - ] - self.assertEqual(([[3, 3]], [[102, 102]]), merge(volume, records)) - self.assertEqual( - {'guid': '1', 'prop': '4', 'ctime': 1, 'mtime': 1}, - volume['document'].get('1').properties(['guid', 'ctime', 'mtime', 'prop'])) - self.assertEqual(3, os.stat('db/document/1/1/prop').st_mtime) - - def test_merge_MultipleCommits(self): - - class Document(db.Resource): - - @db.stored_property() - def prop(self, value): - return value - - self.touch(('db/seqno', '100')) - volume = db.Volume('db', [Document]) - - def generator(): - for i in [ - {'resource': 'document'}, - {'commit': [[1, 1]]}, - {'guid': '1', 'diff': { - 'guid': {'value': '1', 'mtime': 1.0}, - 'ctime': {'value': 2, 'mtime': 2.0}, - 'mtime': {'value': 3, 'mtime': 3.0}, - 'prop': {'value': '4', 'mtime': 4.0}, - }}, - {'commit': [[2, 3]]}, - ]: - yield i - - records = generator() - self.assertEqual(([[1, 3]], [[101, 101]]), merge(volume, records)) - assert volume['document'].exists('1') - - def test_merge_UpdateStats(self): - volume = db.Volume('db', model.RESOURCES) - cp = NodeRoutes('guid', volume) - stats = Sniffer(volume, 'stats/node') - - records = [ - {'resource': 'context'}, - {'guid': 'context', 'diff': { - 'guid': {'value': 'context', 'mtime': 1.0}, - 'ctime': {'value': 1, 'mtime': 1.0}, - 'mtime': {'value': 1, 'mtime': 1.0}, - 'type': {'value': ['package'], 'mtime': 1.0}, - 'title': {'value': {}, 'mtime': 1.0}, - 'summary': {'value': {}, 'mtime': 1.0}, - 'description': {'value': {}, 'mtime': 1.0}, - }}, - {'resource': 'post'}, - {'guid': 'topic_1', 'diff': { - 'guid': {'value': 'topic_1', 'mtime': 1.0}, - 'ctime': {'value': 1, 'mtime': 1.0}, - 'mtime': {'value': 1, 'mtime': 1.0}, - 'type': {'value': 'object', 'mtime': 1.0}, - 'context': {'value': 'context', 'mtime': 1.0}, - 'title': {'value': {}, 'mtime': 1.0}, - 'message': {'value': {}, 'mtime': 1.0}, - 'solution': {'value': 'solution_1', 'mtime': 1.0}, - }}, - {'guid': 'topic_2', 'diff': { - 'guid': {'value': 'topic_2', 'mtime': 1.0}, - 'ctime': {'value': 1, 'mtime': 1.0}, - 'mtime': {'value': 1, 'mtime': 1.0}, - 'type': {'value': 'object', 'mtime': 1.0}, - 'context': {'value': 'context', 'mtime': 1.0}, - 'title': {'value': {}, 'mtime': 1.0}, - 'message': {'value': {}, 'mtime': 1.0}, - 'solution': {'value': 'solution_2', 'mtime': 1.0}, - }}, - {'guid': 'context_review', 'diff': { - 'guid': {'value': 'context_review', 'mtime': 1.0}, - 'ctime': {'value': 1, 'mtime': 1.0}, - 'mtime': {'value': 1, 'mtime': 1.0}, - 'context': {'value': 'context', 'mtime': 1.0}, - 'vote': {'value': 1, 'mtime': 1.0}, - 'author': {'mtime': 1, 'value': {}}, - 'layer': {'mtime': 1, 'value': []}, - 'tags': {'mtime': 1, 'value': []}, - 'type': {'value': 'review', 'mtime': 1.0}, - }}, - {'guid': 'topic_review', 'diff': { - 'guid': {'value': 'topic_review', 'mtime': 1.0}, - 'ctime': {'value': 1, 'mtime': 1.0}, - 'mtime': {'value': 1, 'mtime': 1.0}, - 'context': {'value': 'context', 'mtime': 1.0}, - 'topic': {'value': 'topic_1', 'mtime': 1.0}, - 'vote': {'value': 1, 'mtime': 1.0}, - 'author': {'mtime': 1, 'value': {}}, - 'layer': {'mtime': 1, 'value': []}, - 'tags': {'mtime': 1, 'value': []}, - 'type': {'value': 'feedback', 'mtime': 1.0}, - }}, - {'guid': 'solution_1', 'diff': { - 'guid': {'value': 'solution_1', 'mtime': 1.0}, - 'ctime': {'value': 1, 'mtime': 1.0}, - 'mtime': {'value': 1, 'mtime': 1.0}, - 'context': {'value': 'context', 'mtime': 1.0}, - 'topic': {'value': 'topic_1', 'mtime': 1.0}, - 'type': {'value': 'answer', 'mtime': 1.0}, - 'title': {'value': {}, 'mtime': 1.0}, - 'message': {'value': {}, 'mtime': 1.0}, - }}, - {'guid': 'solution_2', 'diff': { - 'guid': {'value': 'solution_2', 'mtime': 1.0}, - 'ctime': {'value': 1, 'mtime': 1.0}, - 'mtime': {'value': 1, 'mtime': 1.0}, - 'context': {'value': 'context', 'mtime': 1.0}, - 'topic': {'value': 'topic_2', 'mtime': 1.0}, - 'type': {'value': 'answer', 'mtime': 1.0}, - 'title': {'value': {}, 'mtime': 1.0}, - 'message': {'value': {}, 'mtime': 1.0}, - }}, - {'resource': 'release'}, - {'guid': 'release', 'diff': { - 'guid': {'value': 'release', 'mtime': 1.0}, - 'ctime': {'value': 1, 'mtime': 1.0}, - 'mtime': {'value': 1, 'mtime': 1.0}, - 'context': {'value': 'context', 'mtime': 1.0}, - 'license': {'value': ['GPL-3.0'], 'mtime': 1.0}, - 'version': {'value': '1', 'mtime': 1.0}, - 'stability': {'value': 'stable', 'mtime': 1.0}, - 'notes': {'value': {}, 'mtime': 1.0}, - }}, - {'commit': [[1, 1]]}, - ] - merge(volume, records, stats=stats) - ts = int(current_time()) - stats.commit(ts) - stats.commit_objects() - - self.assertEqual([ - [('post', ts, { - 'downloaded': 0.0, - 'total': 6.0, - })], - [('user', ts, { - 'total': 0.0, - })], - [('context', ts, { - 'failed': 0.0, - 'downloaded': 0.0, - 'total': 1.0, - 'released': 1.0, - })], - ], - [[(j.name,) + i for i in j.get(j.last, j.last)] for j in Rrd('stats/node', 1)]) - self.assertEqual([1, 1], volume['context'].get('context')['rating']) - self.assertEqual([1, 1], volume['post'].get('topic_1')['rating']) - - records = [ - {'resource': 'post'}, - {'guid': 'topic_2', 'diff': {'solution': {'value': '', 'mtime': 2.0}}}, - {'commit': [[2, 2]]}, - ] - merge(volume, records, stats=stats) - ts += 1 - stats.commit(ts) - stats.commit_objects() - - self.assertEqual([ - [('post', ts, { - 'downloaded': 0.0, - 'total': 6.0, - })], - [('user', ts, { - 'total': 0.0, - })], - [('context', ts, { - 'failed': 0.0, - 'downloaded': 0.0, - 'total': 1.0, - 'released': 1.0, - })], - ], - [[(j.name,) + i for i in j.get(j.last, j.last)] for j in Rrd('stats/node', 1)]) - - records = [ - {'resource': 'context'}, - {'guid': 'context', 'diff': {'layer': {'value': ['deleted'], 'mtime': 3.0}}}, - {'resource': 'post'}, - {'guid': 'topic_1', 'diff': {'layer': {'value': ['deleted'], 'mtime': 3.0}}}, - {'guid': 'topic_2', 'diff': {'layer': {'value': ['deleted'], 'mtime': 3.0}}}, - {'guid': 'context_review', 'diff': {'layer': {'value': ['deleted'], 'mtime': 3.0}}}, - {'guid': 'topic_review', 'diff': {'layer': {'value': ['deleted'], 'mtime': 3.0}}}, - {'guid': 'solution_1', 'diff': {'layer': {'value': ['deleted'], 'mtime': 3.0}}}, - {'guid': 'solution_2', 'diff': {'layer': {'value': ['deleted'], 'mtime': 3.0}}}, - {'resource': 'release'}, - {'guid': 'release', 'diff': {'layer': {'value': ['deleted'], 'mtime': 3.0}}}, - {'commit': [[3, 3]]}, - ] - merge(volume, records, stats=stats) - ts += 1 - stats.commit(ts) - stats.commit_objects() - - self.assertEqual([ - [('post', ts, { - 'downloaded': 0.0, - 'total': 0.0, - })], - [('user', ts, { - 'total': 0.0, - })], - [('context', ts, { - 'failed': 0.0, - 'downloaded': 0.0, - 'total': 0.0, - 'released': 1.0, - })], - ], - [[(j.name,) + i for i in j.get(j.last, j.last)] for j in Rrd('stats/node', 1)]) - - def test_diff_Blobs(self): - - class Document(db.Resource): - - @db.blob_property() - def prop(self, value): - return value - - volume = db.Volume('db', [Document]) - cp = NodeRoutes('guid', volume) - - guid = call(cp, method='POST', document='document', content={}) - call(cp, method='PUT', document='document', guid=guid, content={'prop': 'payload'}) - self.utime('db', 0) - - patch = diff(volume, toolkit.Sequence([[1, None]])) - self.assertEqual( - {'resource': 'document'}, - next(patch)) - record = next(patch) - self.assertEqual('payload', ''.join([i for i in record.pop('blob')])) - self.assertEqual( - {'guid': guid, 'blob_size': len('payload'), 'diff': { - 'prop': { - 'digest': hashlib.sha1('payload').hexdigest(), - 'blob_size': len('payload'), - 'mime_type': 'application/octet-stream', - 'mtime': 0, - }, - }}, - record) - self.assertEqual( - {'guid': guid, 'diff': { - 'guid': {'value': guid, 'mtime': 0}, - 'author': {'mtime': 0, 'value': {}}, - 'layer': {'mtime': 0, 'value': []}, - 'tags': {'mtime': 0, 'value': []}, - 'mtime': {'value': 0, 'mtime': 0}, - 'ctime': {'value': 0, 'mtime': 0}, - }}, - next(patch)) - self.assertEqual( - {'commit': [[1, 2]]}, - next(patch)) - self.assertRaises(StopIteration, next, patch) - - def test_diff_BlobUrls(self): - url = 'http://src.sugarlabs.org/robots.txt' - blob = urllib2.urlopen(url).read() - - class Document(db.Resource): - - @db.blob_property() - def prop(self, value): - return value - - volume = db.Volume('db', [Document]) - cp = NodeRoutes('guid', volume) - - guid = call(cp, method='POST', document='document', content={}) - call(cp, method='PUT', document='document', guid=guid, content={'prop': {'url': url}}) - self.utime('db', 1) - - self.assertEqual([ - {'resource': 'document'}, - {'guid': guid, - 'diff': { - 'guid': {'value': guid, 'mtime': 1}, - 'author': {'mtime': 1, 'value': {}}, - 'layer': {'mtime': 1, 'value': []}, - 'tags': {'mtime': 1, 'value': []}, - 'mtime': {'value': 0, 'mtime': 1}, - 'ctime': {'value': 0, 'mtime': 1}, - 'prop': {'url': url, 'mtime': 1}, - }, - }, - {'commit': [[1, 2]]}, - ], - [i for i in diff(volume, toolkit.Sequence([[1, None]]))]) - - patch = diff(volume, toolkit.Sequence([[1, None]]), fetch_blobs=True) - self.assertEqual( - {'resource': 'document'}, - next(patch)) - record = next(patch) - self.assertEqual(blob, ''.join([i for i in record.pop('blob')])) - self.assertEqual( - {'guid': guid, 'blob_size': len(blob), 'diff': {'prop': {'mtime': 1}}}, - record) - self.assertEqual( - {'guid': guid, 'diff': { - 'guid': {'value': guid, 'mtime': 1}, - 'author': {'mtime': 1, 'value': {}}, - 'layer': {'mtime': 1, 'value': []}, - 'tags': {'mtime': 1, 'value': []}, - 'mtime': {'value': 0, 'mtime': 1}, - 'ctime': {'value': 0, 'mtime': 1}, - }}, - next(patch)) - self.assertEqual( - {'commit': [[1, 2]]}, - next(patch)) - self.assertRaises(StopIteration, next, patch) - - def test_diff_SkipBrokenBlobUrls(self): - - class Document(db.Resource): - - @db.blob_property() - def prop(self, value): - return value - - volume = db.Volume('db', [Document]) - cp = NodeRoutes('guid', volume) - - guid1 = call(cp, method='POST', document='document', content={}) - call(cp, method='PUT', document='document', guid=guid1, content={'prop': {'url': 'http://foo/bar'}}) - guid2 = call(cp, method='POST', document='document', content={}) - self.utime('db', 1) - - self.assertEqual([ - {'resource': 'document'}, - {'guid': guid1, - 'diff': { - 'guid': {'value': guid1, 'mtime': 1}, - 'author': {'mtime': 1, 'value': {}}, - 'layer': {'mtime': 1, 'value': []}, - 'tags': {'mtime': 1, 'value': []}, - 'mtime': {'value': 0, 'mtime': 1}, - 'ctime': {'value': 0, 'mtime': 1}, - 'prop': {'url': 'http://foo/bar', 'mtime': 1}, - }, - }, - {'guid': guid2, - 'diff': { - 'guid': {'value': guid2, 'mtime': 1}, - 'author': {'mtime': 1, 'value': {}}, - 'layer': {'mtime': 1, 'value': []}, - 'tags': {'mtime': 1, 'value': []}, - 'mtime': {'value': 0, 'mtime': 1}, - 'ctime': {'value': 0, 'mtime': 1}, - }, - }, - {'commit': [[1, 3]]}, - ], - [i for i in diff(volume, toolkit.Sequence([[1, None]]), fetch_blobs=False)]) - - self.assertEqual([ - {'resource': 'document'}, - {'guid': guid1, - 'diff': { - 'guid': {'value': guid1, 'mtime': 1}, - 'author': {'mtime': 1, 'value': {}}, - 'layer': {'mtime': 1, 'value': []}, - 'tags': {'mtime': 1, 'value': []}, - 'mtime': {'value': 0, 'mtime': 1}, - 'ctime': {'value': 0, 'mtime': 1}, - }, - }, - {'guid': guid2, - 'diff': { - 'guid': {'value': guid2, 'mtime': 1}, - 'author': {'mtime': 1, 'value': {}}, - 'layer': {'mtime': 1, 'value': []}, - 'tags': {'mtime': 1, 'value': []}, - 'mtime': {'value': 0, 'mtime': 1}, - 'ctime': {'value': 0, 'mtime': 1}, - }, - }, - {'commit': [[1, 3]]}, - ], - [i for i in diff(volume, toolkit.Sequence([[1, None]]), fetch_blobs=True)]) - - def test_merge_Blobs(self): - - class Document(db.Resource): - - @db.blob_property() - def prop(self, value): - return value - - volume = db.Volume('db', [Document]) - - merge(volume, [ - {'resource': 'document'}, - {'guid': '1', 'diff': { - 'guid': {'value': '1', 'mtime': 1.0}, - 'ctime': {'value': 2, 'mtime': 2.0}, - 'mtime': {'value': 3, 'mtime': 3.0}, - 'prop': { - 'blob': StringIO('payload'), - 'blob_size': len('payload'), - 'digest': hashlib.sha1('payload').hexdigest(), - 'mime_type': 'foo/bar', - 'mtime': 1, - }, - }}, - {'commit': [[1, 1]]}, - ]) - - assert volume['document'].exists('1') - blob = volume['document'].get('1')['prop'] - self.assertEqual(1, blob['mtime']) - self.assertEqual('foo/bar', blob['mime_type']) - self.assertEqual(hashlib.sha1('payload').hexdigest(), blob['digest']) - self.assertEqual(tests.tmpdir + '/db/document/1/1/prop.blob', blob['blob']) - self.assertEqual('payload', file(blob['blob']).read()) - - def test_diff_ByLayers(self): - - class Context(db.Resource): - pass - - class release(db.Resource): - pass - - class Review(db.Resource): - pass - - volume = db.Volume('db', [Context, release, Review]) - volume['context'].create({'guid': '0', 'ctime': 1, 'mtime': 1, 'layer': ['layer0', 'common']}) - volume['context'].create({'guid': '1', 'ctime': 1, 'mtime': 1, 'layer': 'layer1'}) - volume['release'].create({'guid': '2', 'ctime': 2, 'mtime': 2, 'layer': 'layer2'}) - volume['review'].create({'guid': '3', 'ctime': 3, 'mtime': 3, 'layer': 'layer3'}) - - volume['context'].update('0', {'tags': '0'}) - volume['context'].update('1', {'tags': '1'}) - volume['release'].update('2', {'tags': '2'}) - volume['review'].update('3', {'tags': '3'}) - self.utime('db', 0) - - self.assertEqual(sorted([ - {'resource': 'context'}, - {'guid': '0', 'diff': {'tags': {'value': '0', 'mtime': 0}}}, - {'guid': '1', 'diff': {'tags': {'value': '1', 'mtime': 0}}}, - {'resource': 'release'}, - {'guid': '2', 'diff': {'tags': {'value': '2', 'mtime': 0}}}, - {'resource': 'review'}, - {'guid': '3', 'diff': {'tags': {'value': '3', 'mtime': 0}}}, - {'commit': [[5, 8]]}, - ]), - sorted([i for i in diff(volume, toolkit.Sequence([[5, None]]))])) - - self.assertEqual(sorted([ - {'resource': 'context'}, - {'guid': '0', 'diff': {'tags': {'value': '0', 'mtime': 0}}}, - {'guid': '1', 'diff': {'tags': {'value': '1', 'mtime': 0}}}, - {'resource': 'release'}, - {'resource': 'review'}, - {'guid': '3', 'diff': {'tags': {'value': '3', 'mtime': 0}}}, - {'commit': [[5, 8]]}, - ]), - sorted([i for i in diff(volume, toolkit.Sequence([[5, None]]), layer='layer1')])) - - self.assertEqual(sorted([ - {'resource': 'context'}, - {'guid': '0', 'diff': {'tags': {'value': '0', 'mtime': 0}}}, - {'resource': 'release'}, - {'guid': '2', 'diff': {'tags': {'value': '2', 'mtime': 0}}}, - {'resource': 'review'}, - {'guid': '3', 'diff': {'tags': {'value': '3', 'mtime': 0}}}, - {'commit': [[5, 8]]}, - ]), - sorted([i for i in diff(volume, toolkit.Sequence([[5, None]]), layer='layer2')])) - - self.assertEqual(sorted([ - {'resource': 'context'}, - {'guid': '0', 'diff': {'tags': {'value': '0', 'mtime': 0}}}, - {'resource': 'release'}, - {'resource': 'review'}, - {'guid': '3', 'diff': {'tags': {'value': '3', 'mtime': 0}}}, - {'commit': [[5, 8]]}, - ]), - sorted([i for i in diff(volume, toolkit.Sequence([[5, None]]), layer='foo')])) - - -def call(routes, method, document=None, guid=None, prop=None, cmd=None, content=None, **kwargs): - path = [] - if document: - path.append(document) - if guid: - path.append(guid) - if prop: - path.append(prop) - request = Request(method=method, path=path, cmd=cmd, content=content) - request.update(kwargs) - request.environ['HTTP_HOST'] = '127.0.0.1' - router = Router(routes) - return router.call(request, Response()) - - -if __name__ == '__main__': - tests.main() |