Pass test_workbench_server_condensed

This commit is contained in:
Xavier Bustamante Talavera 2018-06-19 18:38:42 +02:00
parent f00c6f2f49
commit ef132098cb
14 changed files with 240 additions and 130 deletions

View file

@ -29,7 +29,7 @@ class Client(TealClient):
item=None, item=None,
headers: dict = None, headers: dict = None,
token: str = 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)): if isclass(res) and issubclass(res, (models.Thing, schemas.Thing)):
res = res.t res = res.t
return super().open(uri, res, status, query, accept, content_type, item, headers, token, return super().open(uri, res, status, query, accept, content_type, item, headers, token,
@ -44,7 +44,7 @@ class Client(TealClient):
accept: str = JSON, accept: str = JSON,
headers: dict = None, headers: dict = None,
token: str = 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) return super().get(uri, res, query, status, item, accept, headers, token, **kw)
def post(self, def post(self,
@ -57,7 +57,7 @@ class Client(TealClient):
accept: str = JSON, accept: str = JSON,
headers: dict = None, headers: dict = None,
token: str = 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, return super().post(data, uri, res, query, status, content_type, accept, headers, token,
**kw) **kw)
@ -70,7 +70,7 @@ class Client(TealClient):
res: Union[Type[Union[models.Thing, schemas.Thing]], str], res: Union[Type[Union[models.Thing, schemas.Thing]], str],
resources: Iterable[Union[dict, int]], resources: Iterable[Union[dict, int]],
key: str = None, key: str = None,
**kw) -> Iterable[Union[Dict[str, Any], str]]: **kw) -> Iterable[Union[Dict[str, object], str]]:
"""Like :meth:`.get` but with many resources.""" """Like :meth:`.get` but with many resources."""
return ( return (
self.get(res=res, item=r[key] if key else r, **kw)[0] self.get(res=res, item=r[key] if key else r, **kw)[0]
@ -106,6 +106,6 @@ class UserClient(Client):
item=None, item=None,
headers: dict = None, headers: dict = None,
token: str = 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, return super().open(uri, res, status, query, accept, content_type, item, headers,
self.user['token'] if self.user else token, **kw) self.user['token'] if self.user else token, **kw)

View file

@ -5,10 +5,11 @@ from ereuse_devicehub.resources.device import ComponentDef, ComputerDef, DataSto
DesktopDef, DeviceDef, GraphicCardDef, HardDriveDef, LaptopDef, MicrotowerDef, \ DesktopDef, DeviceDef, GraphicCardDef, HardDriveDef, LaptopDef, MicrotowerDef, \
MotherboardDef, NetbookDef, NetworkAdapterDef, ProcessorDef, RamModuleDef, ServerDef, \ MotherboardDef, NetbookDef, NetworkAdapterDef, ProcessorDef, RamModuleDef, ServerDef, \
SolidStateDriveDef 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, \ PhotoboxSystemRateDef, PhotoboxUserDef, RateDef, RemoveDef, SnapshotDef, StepDef, \
StepRandomDef, StepZeroDef, TestDataStorageDef, TestDef, WorkbenchRateDef, EraseBasicDef, \ StepRandomDef, StepZeroDef, StressTestDef, TestDataStorageDef, TestDef, WorkbenchRateDef
EraseSectorsDef
from ereuse_devicehub.resources.inventory import InventoryDef from ereuse_devicehub.resources.inventory import InventoryDef
from ereuse_devicehub.resources.tag import TagDef from ereuse_devicehub.resources.tag import TagDef
from ereuse_devicehub.resources.user import OrganizationDef, UserDef from ereuse_devicehub.resources.user import OrganizationDef, UserDef
@ -23,7 +24,9 @@ class DevicehubConfig(Config):
OrganizationDef, TagDef, EventDef, AddDef, RemoveDef, EraseBasicDef, EraseSectorsDef, OrganizationDef, TagDef, EventDef, AddDef, RemoveDef, EraseBasicDef, EraseSectorsDef,
StepDef, StepZeroDef, StepRandomDef, RateDef, AggregateRateDef, WorkbenchRateDef, StepDef, StepZeroDef, StepRandomDef, RateDef, AggregateRateDef, WorkbenchRateDef,
PhotoboxUserDef, PhotoboxSystemRateDef, InstallDef, SnapshotDef, TestDef, 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] PASSWORD_SCHEMES = {'pbkdf2_sha256'} # type: Set[str]
SQLALCHEMY_DATABASE_URI = 'postgresql://localhost/dh-db1' # type: str SQLALCHEMY_DATABASE_URI = 'postgresql://localhost/dh-db1' # type: str

View file

@ -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 import post_load, pre_load
from marshmallow.fields import Float, Integer, Str from marshmallow.fields import Float, Integer, Str
from marshmallow.validate import Length, OneOf, Range from marshmallow.validate import Length, OneOf, Range
from marshmallow_enum import EnumField from marshmallow_enum import EnumField
from sqlalchemy.util import OrderedSet 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 from teal.marshmallow import ValidationError
@ -52,11 +52,11 @@ class Device(Thing):
@post_load @post_load
def validate_snapshot_events(self, data): def validate_snapshot_events(self, data):
"""Validates that only snapshot-related events can be uploaded.""" """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']: for event in data['events_one']:
if not isinstance(event, (Install, EraseBasic, Rate, Test)): if not isinstance(event, (Install, EraseBasic, Rate, Test, Benchmark)):
raise ValidationError('You cannot upload {}'.format(event['type']), raise ValidationError('You cannot upload {}'.format(event), field_names=['events'])
field_names='events')
class Computer(Device): class Computer(Device):

View file

@ -2,14 +2,15 @@ from contextlib import suppress
from itertools import groupby from itertools import groupby
from typing import Iterable, Set from typing import Iterable, Set
from sqlalchemy import inspect
from sqlalchemy.util import OrderedSet
from ereuse_devicehub.db import db from ereuse_devicehub.db import db
from ereuse_devicehub.resources.device.exceptions import NeedsId from ereuse_devicehub.resources.device.exceptions import NeedsId
from ereuse_devicehub.resources.device.models import Component, Computer, Device from ereuse_devicehub.resources.device.models import Component, Computer, Device
from ereuse_devicehub.resources.event.models import Remove from ereuse_devicehub.resources.event.models import Remove
from ereuse_devicehub.resources.tag.model import Tag 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.db import ResourceNotFound
from teal.marshmallow import ValidationError from teal.marshmallow import ValidationError
@ -153,7 +154,10 @@ class Sync:
if device.hid: if device.hid:
with suppress(ResourceNotFound): with suppress(ResourceNotFound):
db_device = Device.query.filter_by(hid=device.hid).one() 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] linked_tags = {tag for tag in tags if tag.device_id} # type: Set[Tag]
if linked_tags: if linked_tags:
sample_tag = next(iter(linked_tags)) sample_tag = next(iter(linked_tags))
@ -172,7 +176,18 @@ class Sync:
db.session.add(device) db.session.add(device)
db_device = device db_device = device
db_device.tags |= tags # Union of tags the device had plus the (potentially) new ones 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 assert db_device is not None
return db_device return db_device

View file

@ -1,9 +1,11 @@
from typing import Callable, Iterable, Tuple from typing import Callable, Iterable, Tuple
from ereuse_devicehub.resources.device.sync import Sync from ereuse_devicehub.resources.device.sync import Sync
from ereuse_devicehub.resources.event.schemas import Add, AggregateRate, EraseBasic, Event, \ from ereuse_devicehub.resources.event.schemas import Add, AggregateRate, Benchmark, \
Install, PhotoboxSystemRate, PhotoboxUserRate, Rate, Remove, Snapshot, Step, StepRandom, \ BenchmarkDataStorage, BenchmarkProcessor, BenchmarkProcessorSysbench, BenchmarkRamSysbench, \
StepZero, Test, TestDataStorage, WorkbenchRate, EraseSectors 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 ereuse_devicehub.resources.event.views import EventView, SnapshotView
from teal.resource import Converters, Resource from teal.resource import Converters, Resource
@ -85,3 +87,31 @@ class TestDef(EventDef):
class TestDataStorageDef(TestDef): class TestDataStorageDef(TestDef):
SCHEMA = TestDataStorage 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

View file

@ -2,6 +2,14 @@ from collections import Iterable
from typing import Set, Union from typing import Set, Union
from uuid import uuid4 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 flask import g
from sqlalchemy import BigInteger, Boolean, CheckConstraint, Column, DateTime, Enum as DBEnum, \ from sqlalchemy import BigInteger, Boolean, CheckConstraint, Column, DateTime, Enum as DBEnum, \
Float, ForeignKey, Interval, JSON, SmallInteger, Unicode, event 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.orm.events import AttributeEvents as Events
from sqlalchemy.util import OrderedSet 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, \ from teal.db import ArrayOfEnum, CASCADE, CASCADE_OWN, INHERIT_COND, POLYMORPHIC_ID, \
POLYMORPHIC_ON, StrictVersionType, check_range POLYMORPHIC_ON, StrictVersionType, check_range
@ -46,6 +46,8 @@ class Event(Thing):
closed.comment = """ closed.comment = """
Whether the author has finished the event. Whether the author has finished the event.
After this is set to True, no modifications are allowed. 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 = Column(Boolean, default=False, nullable=False)
error.comment = """ error.comment = """
@ -392,7 +394,7 @@ class StressTest(Test):
class Benchmark(JoinedTableMixin, EventWithOneDevice): class Benchmark(JoinedTableMixin, EventWithOneDevice):
pass elapsed = Column(Interval)
class BenchmarkDataStorage(Benchmark): class BenchmarkDataStorage(Benchmark):

View file

@ -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.marshmallow import NestedOn
from ereuse_devicehub.resources.device.schemas import Component, Device from ereuse_devicehub.resources.device.schemas import Component, Device
from ereuse_devicehub.resources.enums import AppearanceRange, Bios, FunctionalityRange, \ 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.models import STR_BIG_SIZE, STR_SIZE
from ereuse_devicehub.resources.schemas import Thing from ereuse_devicehub.resources.schemas import Thing
from ereuse_devicehub.resources.user.schemas import User 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.marshmallow import Version
from teal.resource import Schema from teal.resource import Schema
@ -26,6 +27,7 @@ class Event(Thing):
components = NestedOn(Component, dump_only=True, many=True) components = NestedOn(Component, dump_only=True, many=True)
description = String(default='', description=m.Event.description.comment) description = String(default='', description=m.Event.description.comment)
author = NestedOn(User, dump_only=True, exclude=('token',)) author = NestedOn(User, dump_only=True, exclude=('token',))
closed = Boolean(missing=True, description=m.Event.closed.comment)
class EventWithOneDevice(Event): class EventWithOneDevice(Event):
@ -157,7 +159,7 @@ class WorkbenchRate(IndividualRate):
class Install(EventWithOneDevice): class Install(EventWithOneDevice):
name = String(validate=Length(STR_BIG_SIZE), name = String(validate=Length(min=4, max=STR_BIG_SIZE),
required=True, required=True,
description='The name of the OS installed.') description='The name of the OS installed.')
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True) elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
@ -176,12 +178,12 @@ class Snapshot(EventWithOneDevice):
description='The software that generated this Snapshot.') description='The software that generated this Snapshot.')
version = Version(required=True, description='The version of the software.') version = Version(required=True, description='The version of the software.')
events = NestedOn(Event, many=True, dump_only=True) events = NestedOn(Event, many=True, dump_only=True)
expected_events = EnumField(SnapshotExpectedEvents, expected_events = List(EnumField(SnapshotExpectedEvents),
many=True, data_key='expectedEvents',
data_key='expectedEvents', description='Keep open this Snapshot until the following events'
description='Keep open this Snapshot until the following events' 'are performed. Setting this value will activate'
'are performed. Setting this value will activate' 'the async Snapshot.')
'the async Snapshot.')
device = NestedOn(Device) device = NestedOn(Device)
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True) elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
components = NestedOn(Component, components = NestedOn(Component,
@ -217,8 +219,42 @@ class TestDataStorage(Test):
length = EnumField(TestHardDriveLength, required=True) length = EnumField(TestHardDriveLength, required=True)
status = String(validate=Length(max=STR_SIZE), required=True) status = String(validate=Length(max=STR_SIZE), required=True)
lifetime = TimeDelta(precision=TimeDelta.DAYS, 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): class StressTest(Test):
pass 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

View file

@ -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

View file

@ -1,12 +1,11 @@
from flask import Response, current_app as app, request from flask import Response, current_app as app, request
from marshmallow import Schema
from marshmallow.fields import List, String, URL from marshmallow.fields import List, String, URL
from webargs.flaskparser import parser from webargs.flaskparser import parser
from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.device.models import Device
from ereuse_devicehub.resources.tag import Tag from ereuse_devicehub.resources.tag import Tag
from teal.marshmallow import ValidationError from teal.marshmallow import ValidationError
from teal.resource import View from teal.resource import View, Schema
class TagView(View): class TagView(View):

View file

@ -9,8 +9,8 @@ type: 'Snapshot'
uuid: 'cb8ce6b5-6a1b-4084-b5b9-d8fadad2a015' uuid: 'cb8ce6b5-6a1b-4084-b5b9-d8fadad2a015'
version: '11.0' version: '11.0'
software: 'Workbench' software: 'Workbench'
startTime: '2018-06-08T17:52:00'
expectedEvents: ['TestDataStorage', 'StressTest', 'EraseSectors', 'Install'] expectedEvents: ['TestDataStorage', 'StressTest', 'EraseSectors', 'Install']
elapsed: 500
device: device:
type: 'Microtower' type: 'Microtower'
serialNumber: 'd1s' serialNumber: 'd1s'
@ -19,14 +19,12 @@ device:
tags: tags:
- type: 'Tag' - type: 'Tag'
id: 'tag1' id: 'tag1'
- type: 'Tag' events:
id: 'tag2' - type: 'WorkbenchRate'
events: appearanceRange: 'A'
- type: 'WorkbenchRate' functionalityRange: 'B'
appearanceRange: 'A' - type: 'BenchmarkRamSysbench'
functionalityRange: 'B' rate: 2444
- type: 'BenchmarkRamSysbench'
rate: 2444
components: components:
- type: 'GraphicCard' - type: 'GraphicCard'
serialNumber: 'gc1-1s' serialNumber: 'gc1-1s'
@ -43,7 +41,7 @@ components:
- type: 'Processor' - type: 'Processor'
model: 'p1-1s' model: 'p1-1s'
manufacturer: 'p1-1mr' manufacturer: 'p1-1mr'
benchmarks: events:
- type: 'BenchmarkProcessor' - type: 'BenchmarkProcessor'
rate: 2410 rate: 2410
- type: 'BenchmarkProcessorSysbench' - type: 'BenchmarkProcessorSysbench'
@ -52,35 +50,36 @@ components:
serialNumber: 'ssd1-1s' serialNumber: 'ssd1-1s'
model: 'ssd1-1ml' model: 'ssd1-1ml'
manufacturer: 'ssd1-1mr' manufacturer: 'ssd1-1mr'
benchmark: events:
type: 'BenchmarkDataStorage' - type: 'BenchmarkDataStorage'
readingSpeed: 20 readSpeed: 20
writingSpeed: 15 writeSpeed: 15
test: elapsed: 21
type: 'TestDataStorage' - type: 'TestDataStorage'
firstError: 0 elapsed: 233
error: False firstError: 0
status: 'Completed without error' error: False
length: 'Short' status: 'Completed without error'
lifetime: 99 length: 'Short'
passedLifeTime: 99 lifetime: 99
assessment: True passedLifetime: 99
powerCycleCount: 11 assessment: True
reallocatedSectorCount: 2 powerCycleCount: 11
powerCycleCount: 4 reallocatedSectorCount: 2
reportedUncorrectableErrors: 1 powerCycleCount: 4
commandTimeout: 11 reportedUncorrectableErrors: 1
currentPendingSectorCount: 1 commandTimeout: 11
offlineUncorrectable: 33 currentPendingSectorCount: 1
remainingLifetimePercentage: 1 offlineUncorrectable: 33
remainingLifetimePercentage: 1
- type: 'HardDrive' - type: 'HardDrive'
serialNumber: 'hdd1-1s' serialNumber: 'hdd1-1s'
model: 'hdd1-1ml' model: 'hdd1-1ml'
manufacturer: 'hdd1-1mr' manufacturer: 'hdd1-1mr'
benchmark: events:
type: 'BenchmarkDataStorage' - type: 'BenchmarkDataStorage'
readingSpeed: 10 readSpeed: 10
writingSpeed: 5 writeSpeed: 5
- type: 'Motherboard' - type: 'Motherboard'
serialNumber: 'mb1-1s' serialNumber: 'mb1-1s'
model: 'mb1-1ml' model: 'mb1-1ml'

View file

@ -9,4 +9,4 @@
type: 'StressTest' type: 'StressTest'
elapsed: 300 elapsed: 300
error: False error: False
snapshot: None # fulfill! # snapshot: None fulfill!

View file

@ -8,8 +8,8 @@
type: 'EraseSectors' type: 'EraseSectors'
error: False error: False
snapshot: None # fulfill! # snapshot: None fulfill!
device: None # fulfill! # device: None fulfill!
cleanWithZeros: False cleanWithZeros: False
startTime: 2018-01-01T10:10:10 startTime: 2018-01-01T10:10:10
endTime: 2018-01-01T12:10:10 endTime: 2018-01-01T12:10:10
@ -19,3 +19,5 @@ steps:
startTime: '2018-01-01T10:10:10' startTime: '2018-01-01T10:10:10'
endTime: '2018-01-01T12:10:10' endTime: '2018-01-01T12:10:10'
error: False error: False
cleanWithZeros: False
secureRandomSteps: 0

View file

@ -9,6 +9,6 @@
type: 'Install' type: 'Install'
elapsed: 420 elapsed: 420
error: False error: False
snapshot: None # fulfill! # snapshot: None fulfill!
device: None # fulfill! # device: None fulfill!
name: 'LinuxMint 18.01 32b' name: 'LinuxMint 18.01 32b'

View file

@ -1,13 +1,52 @@
""" """
Tests that emulates the behaviour of a WorkbenchServer. Tests that emulates the behaviour of a WorkbenchServer.
""" """
import pytest
from ereuse_devicehub.client import UserClient from ereuse_devicehub.client import UserClient
from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.device.models import Device
from ereuse_devicehub.resources.event.models import EraseSectors, Install, Snapshot, \ from ereuse_devicehub.resources.event.models import EraseSectors, Install, Snapshot, \
StressTest StressTest
from ereuse_devicehub.resources.tag.model import Tag
from tests.conftest import file 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): def test_workbench_server_phases(user: UserClient):
""" """
Tests the phases described in the docs section `Snapshots from 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']) pc, _ = user.get(res=Device, item=snapshot['id'])
assert len(pc['events']) == 10 # todo shall I add child events? 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']