diff --git a/ereuse_devicehub/client.py b/ereuse_devicehub/client.py index f10f6458..dd5d9c2f 100644 --- a/ereuse_devicehub/client.py +++ b/ereuse_devicehub/client.py @@ -29,7 +29,7 @@ class Client(TealClient): item=None, headers: dict = None, token: str = None, - **kw) -> Tuple[Union[Dict[str, Any], str], Response]: + **kw) -> Tuple[Union[Dict[str, object], str], Response]: if isclass(res) and issubclass(res, (models.Thing, schemas.Thing)): res = res.t return super().open(uri, res, status, query, accept, content_type, item, headers, token, @@ -44,7 +44,7 @@ class Client(TealClient): accept: str = JSON, headers: dict = None, token: str = None, - **kw) -> Tuple[Union[Dict[str, Any], str], Response]: + **kw) -> Tuple[Union[Dict[str, object], str], Response]: return super().get(uri, res, query, status, item, accept, headers, token, **kw) def post(self, @@ -57,7 +57,7 @@ class Client(TealClient): accept: str = JSON, headers: dict = None, token: str = None, - **kw) -> Tuple[Union[Dict[str, Any], str], Response]: + **kw) -> Tuple[Union[Dict[str, object], str], Response]: return super().post(data, uri, res, query, status, content_type, accept, headers, token, **kw) @@ -70,7 +70,7 @@ class Client(TealClient): res: Union[Type[Union[models.Thing, schemas.Thing]], str], resources: Iterable[Union[dict, int]], key: str = None, - **kw) -> Iterable[Union[Dict[str, Any], str]]: + **kw) -> Iterable[Union[Dict[str, object], str]]: """Like :meth:`.get` but with many resources.""" return ( self.get(res=res, item=r[key] if key else r, **kw)[0] @@ -106,6 +106,6 @@ class UserClient(Client): item=None, headers: dict = None, token: str = None, - **kw) -> Tuple[Union[Dict[str, Any], str], Response]: + **kw) -> Tuple[Union[Dict[str, object], str], Response]: return super().open(uri, res, status, query, accept, content_type, item, headers, self.user['token'] if self.user else token, **kw) diff --git a/ereuse_devicehub/config.py b/ereuse_devicehub/config.py index 00eecd49..e796ebca 100644 --- a/ereuse_devicehub/config.py +++ b/ereuse_devicehub/config.py @@ -5,10 +5,11 @@ from ereuse_devicehub.resources.device import ComponentDef, ComputerDef, DataSto DesktopDef, DeviceDef, GraphicCardDef, HardDriveDef, LaptopDef, MicrotowerDef, \ MotherboardDef, NetbookDef, NetworkAdapterDef, ProcessorDef, RamModuleDef, ServerDef, \ SolidStateDriveDef -from ereuse_devicehub.resources.event import AddDef, AggregateRateDef, EventDef, InstallDef, \ +from ereuse_devicehub.resources.event import AddDef, AggregateRateDef, BenchmarkDataStorageDef, \ + BenchmarkDef, BenchmarkProcessorDef, BenchmarkProcessorSysbenchDef, BenchmarkRamSysbenchDef, \ + BenchmarkWithRateDef, EraseBasicDef, EraseSectorsDef, EventDef, InstallDef, \ PhotoboxSystemRateDef, PhotoboxUserDef, RateDef, RemoveDef, SnapshotDef, StepDef, \ - StepRandomDef, StepZeroDef, TestDataStorageDef, TestDef, WorkbenchRateDef, EraseBasicDef, \ - EraseSectorsDef + StepRandomDef, StepZeroDef, StressTestDef, TestDataStorageDef, TestDef, WorkbenchRateDef from ereuse_devicehub.resources.inventory import InventoryDef from ereuse_devicehub.resources.tag import TagDef from ereuse_devicehub.resources.user import OrganizationDef, UserDef @@ -23,7 +24,9 @@ class DevicehubConfig(Config): OrganizationDef, TagDef, EventDef, AddDef, RemoveDef, EraseBasicDef, EraseSectorsDef, StepDef, StepZeroDef, StepRandomDef, RateDef, AggregateRateDef, WorkbenchRateDef, PhotoboxUserDef, PhotoboxSystemRateDef, InstallDef, SnapshotDef, TestDef, - TestDataStorageDef, WorkbenchRateDef, InventoryDef + TestDataStorageDef, StressTestDef, WorkbenchRateDef, InventoryDef, BenchmarkDef, + BenchmarkDataStorageDef, BenchmarkWithRateDef, BenchmarkProcessorDef, + BenchmarkProcessorSysbenchDef, BenchmarkRamSysbenchDef } PASSWORD_SCHEMES = {'pbkdf2_sha256'} # type: Set[str] SQLALCHEMY_DATABASE_URI = 'postgresql://localhost/dh-db1' # type: str diff --git a/ereuse_devicehub/resources/device/schemas.py b/ereuse_devicehub/resources/device/schemas.py index 87faacd6..020be4f8 100644 --- a/ereuse_devicehub/resources/device/schemas.py +++ b/ereuse_devicehub/resources/device/schemas.py @@ -1,13 +1,13 @@ +from ereuse_devicehub.marshmallow import NestedOn +from ereuse_devicehub.resources.enums import RamFormat, RamInterface +from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE +from ereuse_devicehub.resources.schemas import Thing, UnitCodes from marshmallow import post_load, pre_load from marshmallow.fields import Float, Integer, Str from marshmallow.validate import Length, OneOf, Range from marshmallow_enum import EnumField from sqlalchemy.util import OrderedSet -from ereuse_devicehub.marshmallow import NestedOn -from ereuse_devicehub.resources.enums import RamFormat, RamInterface -from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE -from ereuse_devicehub.resources.schemas import Thing, UnitCodes from teal.marshmallow import ValidationError @@ -52,11 +52,11 @@ class Device(Thing): @post_load def validate_snapshot_events(self, data): """Validates that only snapshot-related events can be uploaded.""" - from ereuse_devicehub.resources.event.models import EraseBasic, Test, Rate, Install + from ereuse_devicehub.resources.event.models import EraseBasic, Test, Rate, Install, \ + Benchmark for event in data['events_one']: - if not isinstance(event, (Install, EraseBasic, Rate, Test)): - raise ValidationError('You cannot upload {}'.format(event['type']), - field_names='events') + if not isinstance(event, (Install, EraseBasic, Rate, Test, Benchmark)): + raise ValidationError('You cannot upload {}'.format(event), field_names=['events']) class Computer(Device): diff --git a/ereuse_devicehub/resources/device/sync.py b/ereuse_devicehub/resources/device/sync.py index 7eb9d5a9..7fdb5621 100644 --- a/ereuse_devicehub/resources/device/sync.py +++ b/ereuse_devicehub/resources/device/sync.py @@ -2,14 +2,15 @@ from contextlib import suppress from itertools import groupby from typing import Iterable, Set -from sqlalchemy import inspect -from sqlalchemy.util import OrderedSet - from ereuse_devicehub.db import db from ereuse_devicehub.resources.device.exceptions import NeedsId from ereuse_devicehub.resources.device.models import Component, Computer, Device from ereuse_devicehub.resources.event.models import Remove from ereuse_devicehub.resources.tag.model import Tag +from sqlalchemy import inspect +from sqlalchemy.exc import IntegrityError +from sqlalchemy.util import OrderedSet + from teal.db import ResourceNotFound from teal.marshmallow import ValidationError @@ -153,7 +154,10 @@ class Sync: if device.hid: with suppress(ResourceNotFound): db_device = Device.query.filter_by(hid=device.hid).one() - tags = {Tag.query.filter_by(id=tag.id).one() for tag in device.tags} # type: Set[Tag] + try: + tags = {Tag.query.filter_by(id=tag.id).one() for tag in device.tags} # type: Set[Tag] + except ResourceNotFound: + raise ResourceNotFound('tag you are linking to device {}'.format(device)) linked_tags = {tag for tag in tags if tag.device_id} # type: Set[Tag] if linked_tags: sample_tag = next(iter(linked_tags)) @@ -172,7 +176,18 @@ class Sync: db.session.add(device) db_device = device db_device.tags |= tags # Union of tags the device had plus the (potentially) new ones - db.session.flush() + try: + db.session.flush() + except IntegrityError as e: + # Manage 'one tag per organization' unique constraint + if 'One tag per organization' in e.args[0]: + # todo test for this + id = int(e.args[0][135:e.args[0].index(',', 135)]) + raise ValidationError('The device is already linked to tag {} ' + 'from the same organization.'.format(id), + field_names=['device.tags']) + else: + raise assert db_device is not None return db_device diff --git a/ereuse_devicehub/resources/event/__init__.py b/ereuse_devicehub/resources/event/__init__.py index 536601c7..6d323ae1 100644 --- a/ereuse_devicehub/resources/event/__init__.py +++ b/ereuse_devicehub/resources/event/__init__.py @@ -1,9 +1,11 @@ from typing import Callable, Iterable, Tuple from ereuse_devicehub.resources.device.sync import Sync -from ereuse_devicehub.resources.event.schemas import Add, AggregateRate, EraseBasic, Event, \ - Install, PhotoboxSystemRate, PhotoboxUserRate, Rate, Remove, Snapshot, Step, StepRandom, \ - StepZero, Test, TestDataStorage, WorkbenchRate, EraseSectors +from ereuse_devicehub.resources.event.schemas import Add, AggregateRate, Benchmark, \ + BenchmarkDataStorage, BenchmarkProcessor, BenchmarkProcessorSysbench, BenchmarkRamSysbench, \ + BenchmarkWithRate, EraseBasic, EraseSectors, Event, Install, PhotoboxSystemRate, \ + PhotoboxUserRate, Rate, Remove, Snapshot, Step, StepRandom, StepZero, StressTest, Test, \ + TestDataStorage, WorkbenchRate from ereuse_devicehub.resources.event.views import EventView, SnapshotView from teal.resource import Converters, Resource @@ -85,3 +87,31 @@ class TestDef(EventDef): class TestDataStorageDef(TestDef): SCHEMA = TestDataStorage + + +class StressTestDef(TestDef): + SCHEMA = StressTest + + +class BenchmarkDef(EventDef): + SCHEMA = Benchmark + + +class BenchmarkDataStorageDef(BenchmarkDef): + SCHEMA = BenchmarkDataStorage + + +class BenchmarkWithRateDef(BenchmarkDef): + SCHEMA = BenchmarkWithRate + + +class BenchmarkProcessorDef(BenchmarkWithRateDef): + SCHEMA = BenchmarkProcessor + + +class BenchmarkProcessorSysbenchDef(BenchmarkProcessorDef): + SCHEMA = BenchmarkProcessorSysbench + + +class BenchmarkRamSysbenchDef(BenchmarkWithRateDef): + SCHEMA = BenchmarkRamSysbench diff --git a/ereuse_devicehub/resources/event/models.py b/ereuse_devicehub/resources/event/models.py index 0036515c..d26b6f60 100644 --- a/ereuse_devicehub/resources/event/models.py +++ b/ereuse_devicehub/resources/event/models.py @@ -2,6 +2,14 @@ from collections import Iterable from typing import Set, Union from uuid import uuid4 +from ereuse_devicehub.db import db +from ereuse_devicehub.resources.device.models import Component, Computer, DataStorage, Device +from ereuse_devicehub.resources.enums import AppearanceRange, BOX_RATE_3, BOX_RATE_5, Bios, \ + FunctionalityRange, RATE_NEGATIVE, RATE_POSITIVE, RatingRange, RatingSoftware, \ + SnapshotExpectedEvents, SnapshotSoftware, TestHardDriveLength +from ereuse_devicehub.resources.image.models import Image +from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE, STR_SM_SIZE, Thing +from ereuse_devicehub.resources.user.models import User from flask import g from sqlalchemy import BigInteger, Boolean, CheckConstraint, Column, DateTime, Enum as DBEnum, \ Float, ForeignKey, Interval, JSON, SmallInteger, Unicode, event @@ -12,14 +20,6 @@ from sqlalchemy.orm import backref, relationship from sqlalchemy.orm.events import AttributeEvents as Events from sqlalchemy.util import OrderedSet -from ereuse_devicehub.db import db -from ereuse_devicehub.resources.device.models import Component, Computer, DataStorage, Device -from ereuse_devicehub.resources.enums import AppearanceRange, BOX_RATE_3, BOX_RATE_5, Bios, \ - FunctionalityRange, RATE_NEGATIVE, RATE_POSITIVE, RatingRange, RatingSoftware, \ - SnapshotExpectedEvents, SnapshotSoftware, TestHardDriveLength -from ereuse_devicehub.resources.image.models import Image -from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE, STR_SM_SIZE, Thing -from ereuse_devicehub.resources.user.models import User from teal.db import ArrayOfEnum, CASCADE, CASCADE_OWN, INHERIT_COND, POLYMORPHIC_ID, \ POLYMORPHIC_ON, StrictVersionType, check_range @@ -46,6 +46,8 @@ class Event(Thing): closed.comment = """ Whether the author has finished the event. After this is set to True, no modifications are allowed. + + By default are events are closed when performed. """ error = Column(Boolean, default=False, nullable=False) error.comment = """ @@ -392,7 +394,7 @@ class StressTest(Test): class Benchmark(JoinedTableMixin, EventWithOneDevice): - pass + elapsed = Column(Interval) class BenchmarkDataStorage(Benchmark): diff --git a/ereuse_devicehub/resources/event/schemas.py b/ereuse_devicehub/resources/event/schemas.py index 1510d249..91c6d81e 100644 --- a/ereuse_devicehub/resources/event/schemas.py +++ b/ereuse_devicehub/resources/event/schemas.py @@ -1,9 +1,3 @@ -from flask import current_app as app -from marshmallow import ValidationError, validates_schema -from marshmallow.fields import Boolean, DateTime, Float, Integer, Nested, String, TimeDelta, UUID -from marshmallow.validate import Length, Range -from marshmallow_enum import EnumField - from ereuse_devicehub.marshmallow import NestedOn from ereuse_devicehub.resources.device.schemas import Component, Device from ereuse_devicehub.resources.enums import AppearanceRange, Bios, FunctionalityRange, \ @@ -12,6 +6,13 @@ from ereuse_devicehub.resources.event import models as m from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE from ereuse_devicehub.resources.schemas import Thing from ereuse_devicehub.resources.user.schemas import User +from flask import current_app as app +from marshmallow import ValidationError, validates_schema +from marshmallow.fields import Boolean, DateTime, Float, Integer, List, Nested, String, TimeDelta, \ + UUID +from marshmallow.validate import Length, Range +from marshmallow_enum import EnumField + from teal.marshmallow import Version from teal.resource import Schema @@ -26,6 +27,7 @@ class Event(Thing): components = NestedOn(Component, dump_only=True, many=True) description = String(default='', description=m.Event.description.comment) author = NestedOn(User, dump_only=True, exclude=('token',)) + closed = Boolean(missing=True, description=m.Event.closed.comment) class EventWithOneDevice(Event): @@ -157,7 +159,7 @@ class WorkbenchRate(IndividualRate): class Install(EventWithOneDevice): - name = String(validate=Length(STR_BIG_SIZE), + name = String(validate=Length(min=4, max=STR_BIG_SIZE), required=True, description='The name of the OS installed.') elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True) @@ -176,12 +178,12 @@ class Snapshot(EventWithOneDevice): description='The software that generated this Snapshot.') version = Version(required=True, description='The version of the software.') events = NestedOn(Event, many=True, dump_only=True) - expected_events = EnumField(SnapshotExpectedEvents, - many=True, - data_key='expectedEvents', - description='Keep open this Snapshot until the following events' - 'are performed. Setting this value will activate' - 'the async Snapshot.') + expected_events = List(EnumField(SnapshotExpectedEvents), + data_key='expectedEvents', + description='Keep open this Snapshot until the following events' + 'are performed. Setting this value will activate' + 'the async Snapshot.') + device = NestedOn(Device) elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True) components = NestedOn(Component, @@ -217,8 +219,42 @@ class TestDataStorage(Test): length = EnumField(TestHardDriveLength, required=True) status = String(validate=Length(max=STR_SIZE), required=True) lifetime = TimeDelta(precision=TimeDelta.DAYS, required=True) - first_error = Integer() + first_error = Integer(missing=0, data_key='firstError') + passed_lifetime = TimeDelta(precision=TimeDelta.DAYS, data_key='passedLifetime') + assessment = Boolean() + reallocated_sector_count = Integer(data_key='reallocatedSectorCount') + power_cycle_count = Integer(data_key='powerCycleCount') + reported_uncorrectable_errors = Integer(data_key='reportedUncorrectableErrors') + command_timeout = Integer(data_key='commandTimeout') + current_pending_sector_count = Integer(data_key='currentPendingSectorCount') + offline_uncorrectable = Integer(data_key='offlineUncorrectable') + remaining_lifetime_percentage = Integer(data_key='remainingLifetimePercentage') class StressTest(Test): pass + + +class Benchmark(EventWithOneDevice): + elapsed = TimeDelta(precision=TimeDelta.SECONDS) + + +class BenchmarkDataStorage(Benchmark): + read_speed = Float(required=True, data_key='readSpeed') + write_speed = Float(required=True, data_key='writeSpeed') + + +class BenchmarkWithRate(Benchmark): + rate = Integer(required=True) + + +class BenchmarkProcessor(BenchmarkWithRate): + pass + + +class BenchmarkProcessorSysbench(BenchmarkProcessor): + pass + + +class BenchmarkRamSysbench(BenchmarkWithRate): + pass diff --git a/ereuse_devicehub/resources/tag/model.pyi b/ereuse_devicehub/resources/tag/model.pyi new file mode 100644 index 00000000..84c9ef9d --- /dev/null +++ b/ereuse_devicehub/resources/tag/model.pyi @@ -0,0 +1,25 @@ +from uuid import UUID + +from boltons.urlutils import URL +from sqlalchemy import Column +from sqlalchemy.orm import relationship + +from ereuse_devicehub.resources.device.models import Device +from ereuse_devicehub.resources.models import Thing + + +class Tag(Thing): + id = ... # type: Column + org_id = ... # type: Column + org = ... # type: relationship + provider = ... # type: Column + device_id = ... # type: Column + device = ... # type: relationship + + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.id = ... # type: str + self.org_id = ... # type: UUID + self.provider = ... # type: URL + self.device_id = ... # type: int + self.device = ... # type: Device diff --git a/ereuse_devicehub/resources/tag/view.py b/ereuse_devicehub/resources/tag/view.py index 318e6d1a..7989020e 100644 --- a/ereuse_devicehub/resources/tag/view.py +++ b/ereuse_devicehub/resources/tag/view.py @@ -1,12 +1,11 @@ from flask import Response, current_app as app, request -from marshmallow import Schema from marshmallow.fields import List, String, URL from webargs.flaskparser import parser from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.tag import Tag from teal.marshmallow import ValidationError -from teal.resource import View +from teal.resource import View, Schema class TagView(View): diff --git a/tests/files/workbench-server-1.snapshot.yaml b/tests/files/workbench-server-1.snapshot.yaml index 0966d1a4..b7b03f63 100644 --- a/tests/files/workbench-server-1.snapshot.yaml +++ b/tests/files/workbench-server-1.snapshot.yaml @@ -9,8 +9,8 @@ type: 'Snapshot' uuid: 'cb8ce6b5-6a1b-4084-b5b9-d8fadad2a015' version: '11.0' software: 'Workbench' -startTime: '2018-06-08T17:52:00' expectedEvents: ['TestDataStorage', 'StressTest', 'EraseSectors', 'Install'] +elapsed: 500 device: type: 'Microtower' serialNumber: 'd1s' @@ -19,14 +19,12 @@ device: tags: - type: 'Tag' id: 'tag1' - - type: 'Tag' - id: 'tag2' -events: - - type: 'WorkbenchRate' - appearanceRange: 'A' - functionalityRange: 'B' - - type: 'BenchmarkRamSysbench' - rate: 2444 + events: + - type: 'WorkbenchRate' + appearanceRange: 'A' + functionalityRange: 'B' + - type: 'BenchmarkRamSysbench' + rate: 2444 components: - type: 'GraphicCard' serialNumber: 'gc1-1s' @@ -43,7 +41,7 @@ components: - type: 'Processor' model: 'p1-1s' manufacturer: 'p1-1mr' - benchmarks: + events: - type: 'BenchmarkProcessor' rate: 2410 - type: 'BenchmarkProcessorSysbench' @@ -52,35 +50,36 @@ components: serialNumber: 'ssd1-1s' model: 'ssd1-1ml' manufacturer: 'ssd1-1mr' - benchmark: - type: 'BenchmarkDataStorage' - readingSpeed: 20 - writingSpeed: 15 - test: - type: 'TestDataStorage' - firstError: 0 - error: False - status: 'Completed without error' - length: 'Short' - lifetime: 99 - passedLifeTime: 99 - assessment: True - powerCycleCount: 11 - reallocatedSectorCount: 2 - powerCycleCount: 4 - reportedUncorrectableErrors: 1 - commandTimeout: 11 - currentPendingSectorCount: 1 - offlineUncorrectable: 33 - remainingLifetimePercentage: 1 + events: + - type: 'BenchmarkDataStorage' + readSpeed: 20 + writeSpeed: 15 + elapsed: 21 + - type: 'TestDataStorage' + elapsed: 233 + firstError: 0 + error: False + status: 'Completed without error' + length: 'Short' + lifetime: 99 + passedLifetime: 99 + assessment: True + powerCycleCount: 11 + reallocatedSectorCount: 2 + powerCycleCount: 4 + reportedUncorrectableErrors: 1 + commandTimeout: 11 + currentPendingSectorCount: 1 + offlineUncorrectable: 33 + remainingLifetimePercentage: 1 - type: 'HardDrive' serialNumber: 'hdd1-1s' model: 'hdd1-1ml' manufacturer: 'hdd1-1mr' - benchmark: - type: 'BenchmarkDataStorage' - readingSpeed: 10 - writingSpeed: 5 + events: + - type: 'BenchmarkDataStorage' + readSpeed: 10 + writeSpeed: 5 - type: 'Motherboard' serialNumber: 'mb1-1s' model: 'mb1-1ml' diff --git a/tests/files/workbench-server-2.stress-test.yaml b/tests/files/workbench-server-2.stress-test.yaml index c762e16d..5c048615 100644 --- a/tests/files/workbench-server-2.stress-test.yaml +++ b/tests/files/workbench-server-2.stress-test.yaml @@ -9,4 +9,4 @@ type: 'StressTest' elapsed: 300 error: False -snapshot: None # fulfill! \ No newline at end of file +# snapshot: None fulfill! \ No newline at end of file diff --git a/tests/files/workbench-server-3.erase.yaml b/tests/files/workbench-server-3.erase.yaml index a19935ce..4ef2b792 100644 --- a/tests/files/workbench-server-3.erase.yaml +++ b/tests/files/workbench-server-3.erase.yaml @@ -8,8 +8,8 @@ type: 'EraseSectors' error: False -snapshot: None # fulfill! -device: None # fulfill! +# snapshot: None fulfill! +# device: None fulfill! cleanWithZeros: False startTime: 2018-01-01T10:10:10 endTime: 2018-01-01T12:10:10 @@ -19,3 +19,5 @@ steps: startTime: '2018-01-01T10:10:10' endTime: '2018-01-01T12:10:10' error: False + cleanWithZeros: False + secureRandomSteps: 0 diff --git a/tests/files/workbench-server-4.install.yaml b/tests/files/workbench-server-4.install.yaml index 33091dc2..ba8dd3b4 100644 --- a/tests/files/workbench-server-4.install.yaml +++ b/tests/files/workbench-server-4.install.yaml @@ -9,6 +9,6 @@ type: 'Install' elapsed: 420 error: False -snapshot: None # fulfill! -device: None # fulfill! +# snapshot: None fulfill! +# device: None fulfill! name: 'LinuxMint 18.01 32b' \ No newline at end of file diff --git a/tests/test_workbench.py b/tests/test_workbench.py index 058784ec..410924eb 100644 --- a/tests/test_workbench.py +++ b/tests/test_workbench.py @@ -1,13 +1,52 @@ """ Tests that emulates the behaviour of a WorkbenchServer. """ +import pytest from ereuse_devicehub.client import UserClient from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.event.models import EraseSectors, Install, Snapshot, \ StressTest +from ereuse_devicehub.resources.tag.model import Tag + from tests.conftest import file +def test_workbench_server_condensed(user: UserClient): + """ + As :def:`.test_workbench_server_phases` but all the events + condensed in only one big ``Snapshot`` file, as described + in the docs. + """ + s = file('workbench-server-1.snapshot') + del s['expectedEvents'] + s['device']['events'].append(file('workbench-server-2.stress-test')) + s['components'][4]['events'].extend(( + file('workbench-server-3.erase'), + file('workbench-server-4.install') + )) + s['components'][5]['events'] = [file('workbench-server-3.erase')] + # Create tags + user.post(res=Tag, query=[('ids', t['id']) for t in s['device']['tags']], data={}) + snapshot, _ = user.post(res=Snapshot, data=s) + events = snapshot['events'] + assert {(event['type'], event['device']) for event in events} == { + # todo missing Rate event aggregating the rates + ('WorkbenchRate', 1), + ('BenchmarkProcessorSysbench', 5), + ('StressTest', 1), + ('EraseSectors', 6), + ('BenchmarkRamSysbench', 1), + ('BenchmarkProcessor', 5), + ('Install', 6), + ('EraseSectors', 7), + ('BenchmarkDataStorage', 6), + ('TestDataStorage', 6) + } + assert snapshot['closed'] + assert not snapshot['error'] + + +@pytest.mark.xfail(reason='Functionality not yet developed.') def test_workbench_server_phases(user: UserClient): """ Tests the phases described in the docs section `Snapshots from @@ -73,43 +112,3 @@ def test_workbench_server_phases(user: UserClient): pc, _ = user.get(res=Device, item=snapshot['id']) assert len(pc['events']) == 10 # todo shall I add child events? - - -def test_workbench_server_condensed(user: UserClient): - """ - As :def:`.test_workbench_server_phases` but all the events - condensed in only one big ``Snapshot`` file, as described - in the docs. - """ - s = file('workbench-server-1.snapshot') - s['events'].append(file('workbench-server-2.stress-test')) - s['components'][5]['erasure'] = file('workbench-server-3.erase') - s['components'][5]['installation'] = file('workbench-server-4.install') - s['components'][6]['erasure'] = file('workbench-server-3.erase') - snapshot, _ = user.post(res=Snapshot, data=s) - events = snapshot['events'] - assert events[0]['type'] == 'Rate' - assert events[0]['device'] == 1 - assert events[0]['closed'] - assert events[0]['type'] == 'WorkbenchRate' - assert events[0]['device'] == 1 - assert events[1]['type'] == 'BenchmarkProcessor' - assert events[1]['device'] == 5 - assert events[2]['type'] == 'BenchmarkProcessorSysbench' - assert events[2]['device'] == 5 - assert events[3]['type'] == 'BenchmarkDataStorage' - assert events[3]['device'] == 6 - assert events[4]['type'] == 'TestDataStorage' - assert events[4]['device'] == 6 - assert events[4]['type'] == 'BenchmarkDataStorage' - assert events[4]['device'] == 7 - assert events[5]['type'] == 'StressTest' - assert events[5]['device'] == 1 - assert events[6]['type'] == 'EraseSectors' - assert events[6]['device'] == 6 - assert events[7]['type'] == 'EraseSectors' - assert events[7]['device'] == 7 - assert events[8]['type'] == 'Install' - assert events[8]['device'] == 6 - assert snapshot['closed'] - assert not snapshot['error']