validate fields for the new snapshot
This commit is contained in:
parent
6bad17013d
commit
18883b2b8d
|
@ -1,14 +1,28 @@
|
||||||
import copy
|
import copy
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from dateutil.tz import tzutc
|
from dateutil.tz import tzutc
|
||||||
from flask import current_app as app, g
|
from flask import current_app as app
|
||||||
from marshmallow import Schema as MarshmallowSchema, ValidationError, fields as f, validates_schema, pre_load, post_load
|
from flask import g
|
||||||
from marshmallow.fields import Boolean, DateTime, Decimal, Float, Integer, Nested, String, \
|
from marshmallow import Schema as MarshmallowSchema
|
||||||
TimeDelta, UUID
|
from marshmallow import ValidationError
|
||||||
|
from marshmallow import fields as f
|
||||||
|
from marshmallow import post_load, pre_load, validates_schema
|
||||||
|
from marshmallow.fields import (
|
||||||
|
UUID,
|
||||||
|
Boolean,
|
||||||
|
DateTime,
|
||||||
|
Decimal,
|
||||||
|
Float,
|
||||||
|
Integer,
|
||||||
|
Nested,
|
||||||
|
String,
|
||||||
|
TimeDelta,
|
||||||
|
)
|
||||||
from marshmallow.validate import Length, OneOf, Range
|
from marshmallow.validate import Length, OneOf, Range
|
||||||
from sqlalchemy.util import OrderedSet
|
from sqlalchemy.util import OrderedSet
|
||||||
from teal.enums import Country, Currency, Subdivision
|
from teal.enums import Country, Currency, Subdivision
|
||||||
from teal.marshmallow import EnumField, IP, SanitizedStr, URL, Version
|
from teal.marshmallow import IP, URL, EnumField, SanitizedStr, Version
|
||||||
from teal.resource import Schema
|
from teal.resource import Schema
|
||||||
|
|
||||||
from ereuse_devicehub.marshmallow import NestedOn
|
from ereuse_devicehub.marshmallow import NestedOn
|
||||||
|
@ -16,24 +30,32 @@ from ereuse_devicehub.resources import enums
|
||||||
from ereuse_devicehub.resources.action import models as m
|
from ereuse_devicehub.resources.action import models as m
|
||||||
from ereuse_devicehub.resources.agent import schemas as s_agent
|
from ereuse_devicehub.resources.agent import schemas as s_agent
|
||||||
from ereuse_devicehub.resources.device import schemas as s_device
|
from ereuse_devicehub.resources.device import schemas as s_device
|
||||||
from ereuse_devicehub.resources.tradedocument import schemas as s_document
|
|
||||||
from ereuse_devicehub.resources.documents import schemas as s_generic_document
|
from ereuse_devicehub.resources.documents import schemas as s_generic_document
|
||||||
from ereuse_devicehub.resources.enums import AppearanceRange, BiosAccessRange, FunctionalityRange, \
|
from ereuse_devicehub.resources.enums import (
|
||||||
PhysicalErasureMethod, R_POSITIVE, RatingRange, \
|
R_POSITIVE,
|
||||||
Severity, SnapshotSoftware, TestDataStorageLength
|
AppearanceRange,
|
||||||
|
BiosAccessRange,
|
||||||
|
FunctionalityRange,
|
||||||
|
PhysicalErasureMethod,
|
||||||
|
RatingRange,
|
||||||
|
Severity,
|
||||||
|
SnapshotSoftware,
|
||||||
|
TestDataStorageLength,
|
||||||
|
)
|
||||||
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.tradedocument import schemas as s_document
|
||||||
|
from ereuse_devicehub.resources.tradedocument.models import TradeDocument
|
||||||
from ereuse_devicehub.resources.user import schemas as s_user
|
from ereuse_devicehub.resources.user import schemas as s_user
|
||||||
from ereuse_devicehub.resources.user.models import User
|
from ereuse_devicehub.resources.user.models import User
|
||||||
from ereuse_devicehub.resources.tradedocument.models import TradeDocument
|
|
||||||
|
|
||||||
|
|
||||||
class Action(Thing):
|
class Action(Thing):
|
||||||
__doc__ = m.Action.__doc__
|
__doc__ = m.Action.__doc__
|
||||||
id = UUID(dump_only=True)
|
id = UUID(dump_only=True)
|
||||||
name = SanitizedStr(default='',
|
name = SanitizedStr(
|
||||||
validate=Length(max=STR_BIG_SIZE),
|
default='', validate=Length(max=STR_BIG_SIZE), description=m.Action.name.comment
|
||||||
description=m.Action.name.comment)
|
)
|
||||||
closed = Boolean(missing=True, description=m.Action.closed.comment)
|
closed = Boolean(missing=True, description=m.Action.closed.comment)
|
||||||
severity = EnumField(Severity, description=m.Action.severity.comment)
|
severity = EnumField(Severity, description=m.Action.severity.comment)
|
||||||
description = SanitizedStr(default='', description=m.Action.description.comment)
|
description = SanitizedStr(default='', description=m.Action.description.comment)
|
||||||
|
@ -43,7 +65,9 @@ class Action(Thing):
|
||||||
agent = NestedOn(s_agent.Agent, description=m.Action.agent_id.comment)
|
agent = NestedOn(s_agent.Agent, description=m.Action.agent_id.comment)
|
||||||
author = NestedOn(s_user.User, dump_only=True, exclude=('token',))
|
author = NestedOn(s_user.User, dump_only=True, exclude=('token',))
|
||||||
components = NestedOn(s_device.Component, dump_only=True, many=True)
|
components = NestedOn(s_device.Component, dump_only=True, many=True)
|
||||||
parent = NestedOn(s_device.Computer, dump_only=True, description=m.Action.parent_id.comment)
|
parent = NestedOn(
|
||||||
|
s_device.Computer, dump_only=True, description=m.Action.parent_id.comment
|
||||||
|
)
|
||||||
url = URL(dump_only=True, description=m.Action.url.__doc__)
|
url = URL(dump_only=True, description=m.Action.url.__doc__)
|
||||||
|
|
||||||
@validates_schema
|
@validates_schema
|
||||||
|
@ -67,24 +91,27 @@ class ActionWithOneDevice(Action):
|
||||||
|
|
||||||
class ActionWithMultipleDocuments(Action):
|
class ActionWithMultipleDocuments(Action):
|
||||||
__doc__ = m.ActionWithMultipleTradeDocuments.__doc__
|
__doc__ = m.ActionWithMultipleTradeDocuments.__doc__
|
||||||
documents = NestedOn(s_document.TradeDocument,
|
documents = NestedOn(
|
||||||
many=True,
|
s_document.TradeDocument,
|
||||||
required=True, # todo test ensuring len(devices) >= 1
|
many=True,
|
||||||
only_query='id',
|
required=True, # todo test ensuring len(devices) >= 1
|
||||||
collection_class=OrderedSet)
|
only_query='id',
|
||||||
|
collection_class=OrderedSet,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ActionWithMultipleDevices(Action):
|
class ActionWithMultipleDevices(Action):
|
||||||
__doc__ = m.ActionWithMultipleDevices.__doc__
|
__doc__ = m.ActionWithMultipleDevices.__doc__
|
||||||
devices = NestedOn(s_device.Device,
|
devices = NestedOn(
|
||||||
many=True,
|
s_device.Device,
|
||||||
required=True, # todo test ensuring len(devices) >= 1
|
many=True,
|
||||||
only_query='id',
|
required=True, # todo test ensuring len(devices) >= 1
|
||||||
collection_class=OrderedSet)
|
only_query='id',
|
||||||
|
collection_class=OrderedSet,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ActionWithMultipleDevicesCheckingOwner(ActionWithMultipleDevices):
|
class ActionWithMultipleDevicesCheckingOwner(ActionWithMultipleDevices):
|
||||||
|
|
||||||
@post_load
|
@post_load
|
||||||
def check_owner_of_device(self, data):
|
def check_owner_of_device(self, data):
|
||||||
for dev in data['devices']:
|
for dev in data['devices']:
|
||||||
|
@ -102,20 +129,29 @@ class Remove(ActionWithOneDevice):
|
||||||
|
|
||||||
class Allocate(ActionWithMultipleDevicesCheckingOwner):
|
class Allocate(ActionWithMultipleDevicesCheckingOwner):
|
||||||
__doc__ = m.Allocate.__doc__
|
__doc__ = m.Allocate.__doc__
|
||||||
start_time = DateTime(data_key='startTime', required=True,
|
start_time = DateTime(
|
||||||
description=m.Action.start_time.comment)
|
data_key='startTime', required=True, description=m.Action.start_time.comment
|
||||||
end_time = DateTime(data_key='endTime', required=False,
|
)
|
||||||
description=m.Action.end_time.comment)
|
end_time = DateTime(
|
||||||
final_user_code = SanitizedStr(data_key="finalUserCode",
|
data_key='endTime', required=False, description=m.Action.end_time.comment
|
||||||
validate=Length(min=1, max=STR_BIG_SIZE),
|
)
|
||||||
required=False,
|
final_user_code = SanitizedStr(
|
||||||
description='This is a internal code for mainteing the secrets of the \
|
data_key="finalUserCode",
|
||||||
personal datas of the new holder')
|
validate=Length(min=1, max=STR_BIG_SIZE),
|
||||||
transaction = SanitizedStr(validate=Length(min=1, max=STR_BIG_SIZE),
|
required=False,
|
||||||
required=False,
|
description='This is a internal code for mainteing the secrets of the \
|
||||||
description='The code used from the owner for \
|
personal datas of the new holder',
|
||||||
relation with external tool.')
|
)
|
||||||
end_users = Integer(data_key='endUsers', validate=[Range(min=1, error="Value must be greater than 0")])
|
transaction = SanitizedStr(
|
||||||
|
validate=Length(min=1, max=STR_BIG_SIZE),
|
||||||
|
required=False,
|
||||||
|
description='The code used from the owner for \
|
||||||
|
relation with external tool.',
|
||||||
|
)
|
||||||
|
end_users = Integer(
|
||||||
|
data_key='endUsers',
|
||||||
|
validate=[Range(min=1, error="Value must be greater than 0")],
|
||||||
|
)
|
||||||
|
|
||||||
@validates_schema
|
@validates_schema
|
||||||
def validate_allocate(self, data: dict):
|
def validate_allocate(self, data: dict):
|
||||||
|
@ -136,12 +172,15 @@ class Allocate(ActionWithMultipleDevicesCheckingOwner):
|
||||||
|
|
||||||
class Deallocate(ActionWithMultipleDevicesCheckingOwner):
|
class Deallocate(ActionWithMultipleDevicesCheckingOwner):
|
||||||
__doc__ = m.Deallocate.__doc__
|
__doc__ = m.Deallocate.__doc__
|
||||||
start_time = DateTime(data_key='startTime', required=True,
|
start_time = DateTime(
|
||||||
description=m.Action.start_time.comment)
|
data_key='startTime', required=True, description=m.Action.start_time.comment
|
||||||
transaction = SanitizedStr(validate=Length(min=1, max=STR_BIG_SIZE),
|
)
|
||||||
required=False,
|
transaction = SanitizedStr(
|
||||||
description='The code used from the owner for \
|
validate=Length(min=1, max=STR_BIG_SIZE),
|
||||||
relation with external tool.')
|
required=False,
|
||||||
|
description='The code used from the owner for \
|
||||||
|
relation with external tool.',
|
||||||
|
)
|
||||||
|
|
||||||
@validates_schema
|
@validates_schema
|
||||||
def validate_deallocate(self, data: dict):
|
def validate_deallocate(self, data: dict):
|
||||||
|
@ -232,7 +271,9 @@ class MeasureBattery(Test):
|
||||||
__doc__ = m.MeasureBattery.__doc__
|
__doc__ = m.MeasureBattery.__doc__
|
||||||
size = Integer(required=True, description=m.MeasureBattery.size.comment)
|
size = Integer(required=True, description=m.MeasureBattery.size.comment)
|
||||||
voltage = Integer(required=True, description=m.MeasureBattery.voltage.comment)
|
voltage = Integer(required=True, description=m.MeasureBattery.voltage.comment)
|
||||||
cycle_count = Integer(data_key='cycleCount', description=m.MeasureBattery.cycle_count.comment)
|
cycle_count = Integer(
|
||||||
|
data_key='cycleCount', description=m.MeasureBattery.cycle_count.comment
|
||||||
|
)
|
||||||
health = EnumField(enums.BatteryHealth, description=m.MeasureBattery.health.comment)
|
health = EnumField(enums.BatteryHealth, description=m.MeasureBattery.health.comment)
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,28 +330,32 @@ class TestBios(Test):
|
||||||
class VisualTest(Test):
|
class VisualTest(Test):
|
||||||
__doc__ = m.VisualTest.__doc__
|
__doc__ = m.VisualTest.__doc__
|
||||||
appearance_range = EnumField(AppearanceRange, data_key='appearanceRange')
|
appearance_range = EnumField(AppearanceRange, data_key='appearanceRange')
|
||||||
functionality_range = EnumField(FunctionalityRange,
|
functionality_range = EnumField(FunctionalityRange, data_key='functionalityRange')
|
||||||
data_key='functionalityRange')
|
|
||||||
labelling = Boolean()
|
labelling = Boolean()
|
||||||
|
|
||||||
|
|
||||||
class Rate(ActionWithOneDevice):
|
class Rate(ActionWithOneDevice):
|
||||||
__doc__ = m.Rate.__doc__
|
__doc__ = m.Rate.__doc__
|
||||||
rating = Integer(validate=Range(*R_POSITIVE),
|
rating = Integer(
|
||||||
dump_only=True,
|
validate=Range(*R_POSITIVE), dump_only=True, description=m.Rate._rating.comment
|
||||||
description=m.Rate._rating.comment)
|
)
|
||||||
version = Version(dump_only=True,
|
version = Version(dump_only=True, description=m.Rate.version.comment)
|
||||||
description=m.Rate.version.comment)
|
appearance = Integer(
|
||||||
appearance = Integer(validate=Range(enums.R_NEGATIVE),
|
validate=Range(enums.R_NEGATIVE),
|
||||||
dump_only=True,
|
dump_only=True,
|
||||||
description=m.Rate._appearance.comment)
|
description=m.Rate._appearance.comment,
|
||||||
functionality = Integer(validate=Range(enums.R_NEGATIVE),
|
)
|
||||||
dump_only=True,
|
functionality = Integer(
|
||||||
description=m.Rate._functionality.comment)
|
validate=Range(enums.R_NEGATIVE),
|
||||||
rating_range = EnumField(RatingRange,
|
dump_only=True,
|
||||||
dump_only=True,
|
description=m.Rate._functionality.comment,
|
||||||
data_key='ratingRange',
|
)
|
||||||
description=m.Rate.rating_range.__doc__)
|
rating_range = EnumField(
|
||||||
|
RatingRange,
|
||||||
|
dump_only=True,
|
||||||
|
data_key='ratingRange',
|
||||||
|
description=m.Rate.rating_range.__doc__,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class RateComputer(Rate):
|
class RateComputer(Rate):
|
||||||
|
@ -320,19 +365,25 @@ class RateComputer(Rate):
|
||||||
data_storage = Float(dump_only=True, data_key='dataStorage')
|
data_storage = Float(dump_only=True, data_key='dataStorage')
|
||||||
graphic_card = Float(dump_only=True, data_key='graphicCard')
|
graphic_card = Float(dump_only=True, data_key='graphicCard')
|
||||||
|
|
||||||
data_storage_range = EnumField(RatingRange, dump_only=True, data_key='dataStorageRange')
|
data_storage_range = EnumField(
|
||||||
|
RatingRange, dump_only=True, data_key='dataStorageRange'
|
||||||
|
)
|
||||||
ram_range = EnumField(RatingRange, dump_only=True, data_key='ramRange')
|
ram_range = EnumField(RatingRange, dump_only=True, data_key='ramRange')
|
||||||
processor_range = EnumField(RatingRange, dump_only=True, data_key='processorRange')
|
processor_range = EnumField(RatingRange, dump_only=True, data_key='processorRange')
|
||||||
graphic_card_range = EnumField(RatingRange, dump_only=True, data_key='graphicCardRange')
|
graphic_card_range = EnumField(
|
||||||
|
RatingRange, dump_only=True, data_key='graphicCardRange'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Price(ActionWithOneDevice):
|
class Price(ActionWithOneDevice):
|
||||||
__doc__ = m.Price.__doc__
|
__doc__ = m.Price.__doc__
|
||||||
currency = EnumField(Currency, required=True, description=m.Price.currency.comment)
|
currency = EnumField(Currency, required=True, description=m.Price.currency.comment)
|
||||||
price = Decimal(places=m.Price.SCALE,
|
price = Decimal(
|
||||||
rounding=m.Price.ROUND,
|
places=m.Price.SCALE,
|
||||||
required=True,
|
rounding=m.Price.ROUND,
|
||||||
description=m.Price.price.comment)
|
required=True,
|
||||||
|
description=m.Price.price.comment,
|
||||||
|
)
|
||||||
version = Version(dump_only=True, description=m.Price.version.comment)
|
version = Version(dump_only=True, description=m.Price.version.comment)
|
||||||
rating = NestedOn(Rate, dump_only=True, description=m.Price.rating_id.comment)
|
rating = NestedOn(Rate, dump_only=True, description=m.Price.rating_id.comment)
|
||||||
|
|
||||||
|
@ -356,13 +407,33 @@ class EreusePrice(Price):
|
||||||
|
|
||||||
class Install(ActionWithOneDevice):
|
class Install(ActionWithOneDevice):
|
||||||
__doc__ = m.Install.__doc__
|
__doc__ = m.Install.__doc__
|
||||||
name = SanitizedStr(validate=Length(min=4, max=STR_BIG_SIZE),
|
name = SanitizedStr(
|
||||||
required=True,
|
validate=Length(min=4, max=STR_BIG_SIZE),
|
||||||
description='The name of the OS installed.')
|
required=True,
|
||||||
|
description='The name of the OS installed.',
|
||||||
|
)
|
||||||
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
|
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
|
||||||
address = Integer(validate=OneOf({8, 16, 32, 64, 128, 256}))
|
address = Integer(validate=OneOf({8, 16, 32, 64, 128, 256}))
|
||||||
|
|
||||||
|
|
||||||
|
class Snapshot2(MarshmallowSchema):
|
||||||
|
uuid = UUID()
|
||||||
|
version = Version(required=True, description='The version of the software.')
|
||||||
|
type = String()
|
||||||
|
endTime = DateTime('iso', dump_only=True, description=m.Thing.updated.comment)
|
||||||
|
|
||||||
|
@validates_schema
|
||||||
|
def validate_workbench_version(self, data: dict):
|
||||||
|
if data['version'] < app.config['MIN_WORKBENCH']:
|
||||||
|
raise ValidationError(
|
||||||
|
'Min. supported Workbench version is '
|
||||||
|
'{} but yours is {}.'.format(
|
||||||
|
app.config['MIN_WORKBENCH'], data['version']
|
||||||
|
),
|
||||||
|
field_names=['version'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Snapshot(ActionWithOneDevice):
|
class Snapshot(ActionWithOneDevice):
|
||||||
__doc__ = m.Snapshot.__doc__
|
__doc__ = m.Snapshot.__doc__
|
||||||
"""
|
"""
|
||||||
|
@ -372,18 +443,22 @@ class Snapshot(ActionWithOneDevice):
|
||||||
See docs for more info.
|
See docs for more info.
|
||||||
"""
|
"""
|
||||||
uuid = UUID()
|
uuid = UUID()
|
||||||
software = EnumField(SnapshotSoftware,
|
software = EnumField(
|
||||||
required=True,
|
SnapshotSoftware,
|
||||||
description='The software that generated this Snapshot.')
|
required=True,
|
||||||
|
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.')
|
||||||
actions = NestedOn(Action, many=True, dump_only=True)
|
actions = NestedOn(Action, many=True, dump_only=True)
|
||||||
elapsed = TimeDelta(precision=TimeDelta.SECONDS)
|
elapsed = TimeDelta(precision=TimeDelta.SECONDS)
|
||||||
components = NestedOn(s_device.Component,
|
components = NestedOn(
|
||||||
many=True,
|
s_device.Component,
|
||||||
description='A list of components that are inside of the device'
|
many=True,
|
||||||
'at the moment of this Snapshot.'
|
description='A list of components that are inside of the device'
|
||||||
'Order is preserved, so the component num 0 when'
|
'at the moment of this Snapshot.'
|
||||||
'submitting is the component num 0 when returning it back.')
|
'Order is preserved, so the component num 0 when'
|
||||||
|
'submitting is the component num 0 when returning it back.',
|
||||||
|
)
|
||||||
|
|
||||||
@validates_schema
|
@validates_schema
|
||||||
def validate_workbench_version(self, data: dict):
|
def validate_workbench_version(self, data: dict):
|
||||||
|
@ -391,16 +466,21 @@ class Snapshot(ActionWithOneDevice):
|
||||||
if data['version'] < app.config['MIN_WORKBENCH']:
|
if data['version'] < app.config['MIN_WORKBENCH']:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
'Min. supported Workbench version is '
|
'Min. supported Workbench version is '
|
||||||
'{} but yours is {}.'.format(app.config['MIN_WORKBENCH'], data['version']),
|
'{} but yours is {}.'.format(
|
||||||
field_names=['version']
|
app.config['MIN_WORKBENCH'], data['version']
|
||||||
|
),
|
||||||
|
field_names=['version'],
|
||||||
)
|
)
|
||||||
|
|
||||||
@validates_schema
|
@validates_schema
|
||||||
def validate_components_only_workbench(self, data: dict):
|
def validate_components_only_workbench(self, data: dict):
|
||||||
if (data['software'] != SnapshotSoftware.Workbench) and (data['software'] != SnapshotSoftware.WorkbenchAndroid):
|
if (data['software'] != SnapshotSoftware.Workbench) and (
|
||||||
|
data['software'] != SnapshotSoftware.WorkbenchAndroid
|
||||||
|
):
|
||||||
if data.get('components', None) is not None:
|
if data.get('components', None) is not None:
|
||||||
raise ValidationError('Only Workbench can add component info',
|
raise ValidationError(
|
||||||
field_names=['components'])
|
'Only Workbench can add component info', field_names=['components']
|
||||||
|
)
|
||||||
|
|
||||||
@validates_schema
|
@validates_schema
|
||||||
def validate_only_workbench_fields(self, data: dict):
|
def validate_only_workbench_fields(self, data: dict):
|
||||||
|
@ -408,22 +488,32 @@ class Snapshot(ActionWithOneDevice):
|
||||||
# todo test
|
# todo test
|
||||||
if data['software'] == SnapshotSoftware.Workbench:
|
if data['software'] == SnapshotSoftware.Workbench:
|
||||||
if not data.get('uuid', None):
|
if not data.get('uuid', None):
|
||||||
raise ValidationError('Snapshots from Workbench and WorkbenchAndroid must have uuid',
|
raise ValidationError(
|
||||||
field_names=['uuid'])
|
'Snapshots from Workbench and WorkbenchAndroid must have uuid',
|
||||||
|
field_names=['uuid'],
|
||||||
|
)
|
||||||
if data.get('elapsed', None) is None:
|
if data.get('elapsed', None) is None:
|
||||||
raise ValidationError('Snapshots from Workbench must have elapsed',
|
raise ValidationError(
|
||||||
field_names=['elapsed'])
|
'Snapshots from Workbench must have elapsed',
|
||||||
|
field_names=['elapsed'],
|
||||||
|
)
|
||||||
elif data['software'] == SnapshotSoftware.WorkbenchAndroid:
|
elif data['software'] == SnapshotSoftware.WorkbenchAndroid:
|
||||||
if not data.get('uuid', None):
|
if not data.get('uuid', None):
|
||||||
raise ValidationError('Snapshots from Workbench and WorkbenchAndroid must have uuid',
|
raise ValidationError(
|
||||||
field_names=['uuid'])
|
'Snapshots from Workbench and WorkbenchAndroid must have uuid',
|
||||||
|
field_names=['uuid'],
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if data.get('uuid', None):
|
if data.get('uuid', None):
|
||||||
raise ValidationError('Only Snapshots from Workbench or WorkbenchAndroid can have uuid',
|
raise ValidationError(
|
||||||
field_names=['uuid'])
|
'Only Snapshots from Workbench or WorkbenchAndroid can have uuid',
|
||||||
|
field_names=['uuid'],
|
||||||
|
)
|
||||||
if data.get('elapsed', None):
|
if data.get('elapsed', None):
|
||||||
raise ValidationError('Only Snapshots from Workbench can have elapsed',
|
raise ValidationError(
|
||||||
field_names=['elapsed'])
|
'Only Snapshots from Workbench can have elapsed',
|
||||||
|
field_names=['elapsed'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ToRepair(ActionWithMultipleDevicesCheckingOwner):
|
class ToRepair(ActionWithMultipleDevicesCheckingOwner):
|
||||||
|
@ -440,16 +530,20 @@ class Ready(ActionWithMultipleDevicesCheckingOwner):
|
||||||
|
|
||||||
class ActionStatus(Action):
|
class ActionStatus(Action):
|
||||||
rol_user = NestedOn(s_user.User, dump_only=True, exclude=('token',))
|
rol_user = NestedOn(s_user.User, dump_only=True, exclude=('token',))
|
||||||
devices = NestedOn(s_device.Device,
|
devices = NestedOn(
|
||||||
many=True,
|
s_device.Device,
|
||||||
required=False, # todo test ensuring len(devices) >= 1
|
many=True,
|
||||||
only_query='id',
|
required=False, # todo test ensuring len(devices) >= 1
|
||||||
collection_class=OrderedSet)
|
only_query='id',
|
||||||
documents = NestedOn(s_document.TradeDocument,
|
collection_class=OrderedSet,
|
||||||
many=True,
|
)
|
||||||
required=False, # todo test ensuring len(devices) >= 1
|
documents = NestedOn(
|
||||||
only_query='id',
|
s_document.TradeDocument,
|
||||||
collection_class=OrderedSet)
|
many=True,
|
||||||
|
required=False, # todo test ensuring len(devices) >= 1
|
||||||
|
only_query='id',
|
||||||
|
collection_class=OrderedSet,
|
||||||
|
)
|
||||||
|
|
||||||
@pre_load
|
@pre_load
|
||||||
def put_devices(self, data: dict):
|
def put_devices(self, data: dict):
|
||||||
|
@ -508,20 +602,28 @@ class Live(ActionWithOneDevice):
|
||||||
See docs for more info.
|
See docs for more info.
|
||||||
"""
|
"""
|
||||||
uuid = UUID()
|
uuid = UUID()
|
||||||
software = EnumField(SnapshotSoftware,
|
software = EnumField(
|
||||||
required=True,
|
SnapshotSoftware,
|
||||||
description='The software that generated this Snapshot.')
|
required=True,
|
||||||
|
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.')
|
||||||
final_user_code = SanitizedStr(data_key="finalUserCode", dump_only=True)
|
final_user_code = SanitizedStr(data_key="finalUserCode", dump_only=True)
|
||||||
licence_version = Version(required=True, description='The version of the software.')
|
licence_version = Version(required=True, description='The version of the software.')
|
||||||
components = NestedOn(s_device.Component,
|
components = NestedOn(
|
||||||
many=True,
|
s_device.Component,
|
||||||
description='A list of components that are inside of the device'
|
many=True,
|
||||||
'at the moment of this Snapshot.'
|
description='A list of components that are inside of the device'
|
||||||
'Order is preserved, so the component num 0 when'
|
'at the moment of this Snapshot.'
|
||||||
'submitting is the component num 0 when returning it back.')
|
'Order is preserved, so the component num 0 when'
|
||||||
usage_time_allocate = TimeDelta(data_key='usageTimeAllocate', required=False,
|
'submitting is the component num 0 when returning it back.',
|
||||||
precision=TimeDelta.HOURS, dump_only=True)
|
)
|
||||||
|
usage_time_allocate = TimeDelta(
|
||||||
|
data_key='usageTimeAllocate',
|
||||||
|
required=False,
|
||||||
|
precision=TimeDelta.HOURS,
|
||||||
|
dump_only=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Organize(ActionWithMultipleDevices):
|
class Organize(ActionWithMultipleDevices):
|
||||||
|
@ -570,7 +672,7 @@ class Revoke(ActionWithMultipleDevices):
|
||||||
@validates_schema
|
@validates_schema
|
||||||
def validate_documents(self, data):
|
def validate_documents(self, data):
|
||||||
"""Check if there are or no one before confirmation,
|
"""Check if there are or no one before confirmation,
|
||||||
This is not checked in the view becouse the list of documents is inmutable
|
This is not checked in the view becouse the list of documents is inmutable
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not data['devices'] == OrderedSet():
|
if not data['devices'] == OrderedSet():
|
||||||
|
@ -610,7 +712,7 @@ class ConfirmDocument(ActionWithMultipleDocuments):
|
||||||
@validates_schema
|
@validates_schema
|
||||||
def validate_documents(self, data):
|
def validate_documents(self, data):
|
||||||
"""If there are one device than have one confirmation,
|
"""If there are one device than have one confirmation,
|
||||||
then remove the list this device of the list of devices of this action
|
then remove the list this device of the list of devices of this action
|
||||||
"""
|
"""
|
||||||
if data['documents'] == OrderedSet():
|
if data['documents'] == OrderedSet():
|
||||||
return
|
return
|
||||||
|
@ -636,7 +738,7 @@ class RevokeDocument(ActionWithMultipleDocuments):
|
||||||
@validates_schema
|
@validates_schema
|
||||||
def validate_documents(self, data):
|
def validate_documents(self, data):
|
||||||
"""Check if there are or no one before confirmation,
|
"""Check if there are or no one before confirmation,
|
||||||
This is not checked in the view becouse the list of documents is inmutable
|
This is not checked in the view becouse the list of documents is inmutable
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if data['documents'] == OrderedSet():
|
if data['documents'] == OrderedSet():
|
||||||
|
@ -663,7 +765,7 @@ class ConfirmRevokeDocument(ActionWithMultipleDocuments):
|
||||||
@validates_schema
|
@validates_schema
|
||||||
def validate_documents(self, data):
|
def validate_documents(self, data):
|
||||||
"""Check if there are or no one before confirmation,
|
"""Check if there are or no one before confirmation,
|
||||||
This is not checked in the view becouse the list of documents is inmutable
|
This is not checked in the view becouse the list of documents is inmutable
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if data['documents'] == OrderedSet():
|
if data['documents'] == OrderedSet():
|
||||||
|
@ -691,26 +793,23 @@ class Trade(ActionWithMultipleDevices):
|
||||||
validate=Length(max=STR_SIZE),
|
validate=Length(max=STR_SIZE),
|
||||||
data_key='userToEmail',
|
data_key='userToEmail',
|
||||||
missing='',
|
missing='',
|
||||||
required=False
|
required=False,
|
||||||
)
|
)
|
||||||
user_to = NestedOn(s_user.User, dump_only=True, data_key='userTo')
|
user_to = NestedOn(s_user.User, dump_only=True, data_key='userTo')
|
||||||
user_from_email = SanitizedStr(
|
user_from_email = SanitizedStr(
|
||||||
validate=Length(max=STR_SIZE),
|
validate=Length(max=STR_SIZE),
|
||||||
data_key='userFromEmail',
|
data_key='userFromEmail',
|
||||||
missing='',
|
missing='',
|
||||||
required=False
|
required=False,
|
||||||
)
|
)
|
||||||
user_from = NestedOn(s_user.User, dump_only=True, data_key='userFrom')
|
user_from = NestedOn(s_user.User, dump_only=True, data_key='userFrom')
|
||||||
code = SanitizedStr(validate=Length(max=STR_SIZE), data_key='code', required=False)
|
code = SanitizedStr(validate=Length(max=STR_SIZE), data_key='code', required=False)
|
||||||
confirm = Boolean(
|
confirm = Boolean(
|
||||||
data_key='confirms',
|
data_key='confirms',
|
||||||
missing=True,
|
missing=True,
|
||||||
description="""If you need confirmation of the user you need actevate this field"""
|
description="""If you need confirmation of the user you need actevate this field""",
|
||||||
)
|
)
|
||||||
lot = NestedOn('Lot',
|
lot = NestedOn('Lot', many=False, required=True, only_query='id')
|
||||||
many=False,
|
|
||||||
required=True,
|
|
||||||
only_query='id')
|
|
||||||
|
|
||||||
@pre_load
|
@pre_load
|
||||||
def adding_devices(self, data: dict):
|
def adding_devices(self, data: dict):
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
""" This is the view for Snapshots """
|
""" This is the view for Snapshots """
|
||||||
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from flask import current_app as app, g
|
from flask import current_app as app
|
||||||
|
from flask import g
|
||||||
|
from flask.json import jsonify
|
||||||
from sqlalchemy.util import OrderedSet
|
from sqlalchemy.util import OrderedSet
|
||||||
|
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.resources.action.models import RateComputer, Snapshot
|
from ereuse_devicehub.resources.action.models import RateComputer, Snapshot
|
||||||
from ereuse_devicehub.resources.device.models import Computer
|
|
||||||
from ereuse_devicehub.resources.action.rate.v1_0 import CannotRate
|
from ereuse_devicehub.resources.action.rate.v1_0 import CannotRate
|
||||||
from ereuse_devicehub.resources.enums import SnapshotSoftware, Severity
|
from ereuse_devicehub.resources.action.schemas import Snapshot2
|
||||||
|
from ereuse_devicehub.resources.device.models import Computer
|
||||||
|
from ereuse_devicehub.resources.enums import Severity, SnapshotSoftware
|
||||||
from ereuse_devicehub.resources.user.exceptions import InsufficientPermission
|
from ereuse_devicehub.resources.user.exceptions import InsufficientPermission
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,11 +62,12 @@ def move_json(tmp_snapshots, path_name, user, live=False):
|
||||||
os.remove(path_name)
|
os.remove(path_name)
|
||||||
|
|
||||||
|
|
||||||
class SnapshotView():
|
class SnapshotView:
|
||||||
"""Performs a Snapshot.
|
"""Performs a Snapshot.
|
||||||
|
|
||||||
See `Snapshot` section in docs for more info.
|
See `Snapshot` section in docs for more info.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Note that if we set the device / components into the snapshot
|
# Note that if we set the device / components into the snapshot
|
||||||
# model object, when we flush them to the db we will flush
|
# model object, when we flush them to the db we will flush
|
||||||
# snapshot, and we want to wait to flush snapshot at the end
|
# snapshot, and we want to wait to flush snapshot at the end
|
||||||
|
@ -74,8 +78,12 @@ class SnapshotView():
|
||||||
self.tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
self.tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||||
self.path_snapshot = save_json(snapshot_json, self.tmp_snapshots, g.user.email)
|
self.path_snapshot = save_json(snapshot_json, self.tmp_snapshots, g.user.email)
|
||||||
snapshot_json.pop('debug', None)
|
snapshot_json.pop('debug', None)
|
||||||
self.snapshot_json = resource_def.schema.load(snapshot_json)
|
if snapshot_json.get('version') in ["14.0.0"]:
|
||||||
self.response = self.build()
|
self.validate_json(snapshot_json)
|
||||||
|
self.response = self.build2()
|
||||||
|
else:
|
||||||
|
self.snapshot_json = resource_def.schema.load(snapshot_json)
|
||||||
|
self.response = self.build()
|
||||||
move_json(self.tmp_snapshots, self.path_snapshot, g.user.email)
|
move_json(self.tmp_snapshots, self.path_snapshot, g.user.email)
|
||||||
|
|
||||||
def post(self):
|
def post(self):
|
||||||
|
@ -84,8 +92,12 @@ class SnapshotView():
|
||||||
def build(self):
|
def build(self):
|
||||||
device = self.snapshot_json.pop('device') # type: Computer
|
device = self.snapshot_json.pop('device') # type: Computer
|
||||||
components = None
|
components = None
|
||||||
if self.snapshot_json['software'] == (SnapshotSoftware.Workbench or SnapshotSoftware.WorkbenchAndroid):
|
if self.snapshot_json['software'] == (
|
||||||
components = self.snapshot_json.pop('components', None) # type: List[Component]
|
SnapshotSoftware.Workbench or SnapshotSoftware.WorkbenchAndroid
|
||||||
|
):
|
||||||
|
components = self.snapshot_json.pop(
|
||||||
|
'components', None
|
||||||
|
) # type: List[Component]
|
||||||
if isinstance(device, Computer) and device.hid:
|
if isinstance(device, Computer) and device.hid:
|
||||||
device.add_mac_to_hid(components_snap=components)
|
device.add_mac_to_hid(components_snap=components)
|
||||||
snapshot = Snapshot(**self.snapshot_json)
|
snapshot = Snapshot(**self.snapshot_json)
|
||||||
|
@ -94,7 +106,9 @@ class SnapshotView():
|
||||||
actions_device = set(e for e in device.actions_one)
|
actions_device = set(e for e in device.actions_one)
|
||||||
device.actions_one.clear()
|
device.actions_one.clear()
|
||||||
if components:
|
if components:
|
||||||
actions_components = tuple(set(e for e in c.actions_one) for c in components)
|
actions_components = tuple(
|
||||||
|
set(e for e in c.actions_one) for c in components
|
||||||
|
)
|
||||||
for component in components:
|
for component in components:
|
||||||
component.actions_one.clear()
|
component.actions_one.clear()
|
||||||
|
|
||||||
|
@ -141,3 +155,12 @@ class SnapshotView():
|
||||||
ret.status_code = 201
|
ret.status_code = 201
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def validate_json(self, snapshot_json):
|
||||||
|
self.schema2 = Snapshot2()
|
||||||
|
self.snapshot_json = self.schema2.load(snapshot_json)
|
||||||
|
|
||||||
|
def build2(self):
|
||||||
|
res = jsonify("Ok")
|
||||||
|
res.status_code = 201
|
||||||
|
return res
|
||||||
|
|
|
@ -1,38 +1,48 @@
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import pytest
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from requests.exceptions import HTTPError
|
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
|
import pytest
|
||||||
from boltons import urlutils
|
from boltons import urlutils
|
||||||
from teal.db import UniqueViolation, DBError
|
|
||||||
from teal.marshmallow import ValidationError
|
|
||||||
from ereuse_utils.test import ANY
|
from ereuse_utils.test import ANY
|
||||||
|
from requests.exceptions import HTTPError
|
||||||
|
from teal.db import DBError, UniqueViolation
|
||||||
|
from teal.marshmallow import ValidationError
|
||||||
|
|
||||||
from ereuse_devicehub.client import UserClient
|
from ereuse_devicehub.client import UserClient
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.devicehub import Devicehub
|
from ereuse_devicehub.devicehub import Devicehub
|
||||||
from ereuse_devicehub.resources.action.models import Action, BenchmarkDataStorage, \
|
from ereuse_devicehub.resources.action.models import (
|
||||||
BenchmarkProcessor, EraseSectors, RateComputer, Snapshot, SnapshotRequest, VisualTest, \
|
Action,
|
||||||
EreusePrice, Ready
|
BenchmarkDataStorage,
|
||||||
|
BenchmarkProcessor,
|
||||||
|
EraseSectors,
|
||||||
|
EreusePrice,
|
||||||
|
RateComputer,
|
||||||
|
Ready,
|
||||||
|
Snapshot,
|
||||||
|
SnapshotRequest,
|
||||||
|
VisualTest,
|
||||||
|
)
|
||||||
|
from ereuse_devicehub.resources.action.views.snapshot import save_json
|
||||||
from ereuse_devicehub.resources.device import models as m
|
from ereuse_devicehub.resources.device import models as m
|
||||||
from ereuse_devicehub.resources.device.exceptions import NeedsId
|
from ereuse_devicehub.resources.device.exceptions import NeedsId
|
||||||
from ereuse_devicehub.resources.device.models import SolidStateDrive
|
from ereuse_devicehub.resources.device.models import SolidStateDrive
|
||||||
from ereuse_devicehub.resources.device.sync import MismatchBetweenProperties, \
|
from ereuse_devicehub.resources.device.sync import (
|
||||||
MismatchBetweenTagsAndHid
|
MismatchBetweenProperties,
|
||||||
|
MismatchBetweenTagsAndHid,
|
||||||
|
)
|
||||||
|
from ereuse_devicehub.resources.documents import documents
|
||||||
from ereuse_devicehub.resources.enums import ComputerChassis, SnapshotSoftware
|
from ereuse_devicehub.resources.enums import ComputerChassis, SnapshotSoftware
|
||||||
from ereuse_devicehub.resources.tag import Tag
|
from ereuse_devicehub.resources.tag import Tag
|
||||||
from ereuse_devicehub.resources.user.models import User
|
from ereuse_devicehub.resources.user.models import User
|
||||||
from ereuse_devicehub.resources.action.views.snapshot import save_json
|
|
||||||
from ereuse_devicehub.resources.documents import documents
|
|
||||||
from tests.conftest import file, yaml2json, json_encode
|
|
||||||
from tests import conftest
|
from tests import conftest
|
||||||
|
from tests.conftest import file, json_encode, yaml2json
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -43,18 +53,22 @@ def test_snapshot_model():
|
||||||
"""
|
"""
|
||||||
device = m.Desktop(serial_number='a1', chassis=ComputerChassis.Tower)
|
device = m.Desktop(serial_number='a1', chassis=ComputerChassis.Tower)
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
snapshot = Snapshot(uuid=uuid4(),
|
snapshot = Snapshot(
|
||||||
end_time=datetime.now(timezone.utc),
|
uuid=uuid4(),
|
||||||
version='1.0',
|
end_time=datetime.now(timezone.utc),
|
||||||
software=SnapshotSoftware.DesktopApp,
|
version='1.0',
|
||||||
elapsed=timedelta(seconds=25))
|
software=SnapshotSoftware.DesktopApp,
|
||||||
|
elapsed=timedelta(seconds=25),
|
||||||
|
)
|
||||||
snapshot.device = device
|
snapshot.device = device
|
||||||
snapshot.request = SnapshotRequest(request={'foo': 'bar'})
|
snapshot.request = SnapshotRequest(request={'foo': 'bar'})
|
||||||
db.session.add(snapshot)
|
db.session.add(snapshot)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
device = m.Desktop.query.one() # type: m.Desktop
|
device = m.Desktop.query.one() # type: m.Desktop
|
||||||
e1 = device.actions[0]
|
e1 = device.actions[0]
|
||||||
assert isinstance(e1, Snapshot), 'Creation order must be preserved: 1. snapshot, 2. WR'
|
assert isinstance(
|
||||||
|
e1, Snapshot
|
||||||
|
), 'Creation order must be preserved: 1. snapshot, 2. WR'
|
||||||
db.session.delete(device)
|
db.session.delete(device)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
assert Snapshot.query.one_or_none() is None
|
assert Snapshot.query.one_or_none() is None
|
||||||
|
@ -63,7 +77,9 @@ def test_snapshot_model():
|
||||||
assert m.Desktop.query.one_or_none() is None
|
assert m.Desktop.query.one_or_none() is None
|
||||||
assert m.Device.query.one_or_none() is None
|
assert m.Device.query.one_or_none() is None
|
||||||
# Check properties
|
# Check properties
|
||||||
assert device.url == urlutils.URL('http://localhost/devices/%s' % device.devicehub_id)
|
assert device.url == urlutils.URL(
|
||||||
|
'http://localhost/devices/%s' % device.devicehub_id
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -78,13 +94,12 @@ def test_snapshot_post(user: UserClient):
|
||||||
"""Tests the post snapshot endpoint (validation, etc), data correctness,
|
"""Tests the post snapshot endpoint (validation, etc), data correctness,
|
||||||
and relationship correctness.
|
and relationship correctness.
|
||||||
"""
|
"""
|
||||||
snapshot = snapshot_and_check(user, yaml2json('basic.snapshot'),
|
snapshot = snapshot_and_check(
|
||||||
action_types=(
|
user,
|
||||||
BenchmarkProcessor.t,
|
yaml2json('basic.snapshot'),
|
||||||
VisualTest.t,
|
action_types=(BenchmarkProcessor.t, VisualTest.t, RateComputer.t),
|
||||||
RateComputer.t
|
perform_second_snapshot=False,
|
||||||
),
|
)
|
||||||
perform_second_snapshot=False)
|
|
||||||
assert snapshot['software'] == 'Workbench'
|
assert snapshot['software'] == 'Workbench'
|
||||||
assert snapshot['version'] == '11.0'
|
assert snapshot['version'] == '11.0'
|
||||||
assert snapshot['uuid'] == 'f5efd26e-8754-46bc-87bf-fbccc39d60d9'
|
assert snapshot['uuid'] == 'f5efd26e-8754-46bc-87bf-fbccc39d60d9'
|
||||||
|
@ -98,8 +113,11 @@ def test_snapshot_post(user: UserClient):
|
||||||
device['components'].sort(key=key)
|
device['components'].sort(key=key)
|
||||||
assert snapshot['components'] == device['components']
|
assert snapshot['components'] == device['components']
|
||||||
|
|
||||||
assert {c['type'] for c in snapshot['components']} == {m.GraphicCard.t, m.RamModule.t,
|
assert {c['type'] for c in snapshot['components']} == {
|
||||||
m.Processor.t}
|
m.GraphicCard.t,
|
||||||
|
m.RamModule.t,
|
||||||
|
m.Processor.t,
|
||||||
|
}
|
||||||
rate = next(e for e in snapshot['actions'] if e['type'] == RateComputer.t)
|
rate = next(e for e in snapshot['actions'] if e['type'] == RateComputer.t)
|
||||||
rate, _ = user.get(res=Action, item=rate['id'])
|
rate, _ = user.get(res=Action, item=rate['id'])
|
||||||
assert rate['device']['id'] == snapshot['device']['id']
|
assert rate['device']['id'] == snapshot['device']['id']
|
||||||
|
@ -127,20 +145,26 @@ def test_same_device_tow_users(user: UserClient, user2: UserClient):
|
||||||
assert pc['ownerID'] != pc2['ownerID']
|
assert pc['ownerID'] != pc2['ownerID']
|
||||||
assert pc['hid'] == pc2['hid']
|
assert pc['hid'] == pc2['hid']
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_update_timefield_updated(user: UserClient):
|
def test_snapshot_update_timefield_updated(user: UserClient):
|
||||||
"""
|
"""
|
||||||
Tests for check if one computer have the time mark updated when one component of it is updated
|
Tests for check if one computer have the time mark updated when one component of it is updated
|
||||||
"""
|
"""
|
||||||
computer1 = yaml2json('1-device-with-components.snapshot')
|
computer1 = yaml2json('1-device-with-components.snapshot')
|
||||||
snapshot = snapshot_and_check(user,
|
snapshot = snapshot_and_check(
|
||||||
computer1,
|
user,
|
||||||
action_types=(BenchmarkProcessor.t,
|
computer1,
|
||||||
RateComputer.t),
|
action_types=(BenchmarkProcessor.t, RateComputer.t),
|
||||||
perform_second_snapshot=False)
|
perform_second_snapshot=False,
|
||||||
|
)
|
||||||
computer2 = yaml2json('2-second-device-with-components-of-first.snapshot')
|
computer2 = yaml2json('2-second-device-with-components-of-first.snapshot')
|
||||||
snapshot_and_check(user, computer2, action_types=('Remove', 'RateComputer'),
|
snapshot_and_check(
|
||||||
perform_second_snapshot=False)
|
user,
|
||||||
|
computer2,
|
||||||
|
action_types=('Remove', 'RateComputer'),
|
||||||
|
perform_second_snapshot=False,
|
||||||
|
)
|
||||||
pc1_devicehub_id = snapshot['device']['devicehubID']
|
pc1_devicehub_id = snapshot['device']['devicehubID']
|
||||||
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
||||||
assert pc1['updated'] != snapshot['device']['updated']
|
assert pc1['updated'] != snapshot['device']['updated']
|
||||||
|
@ -165,7 +189,10 @@ def test_snapshot_power_on_hours(user: UserClient):
|
||||||
test_data_storage = ac
|
test_data_storage = ac
|
||||||
break
|
break
|
||||||
|
|
||||||
assert test_data_storage.lifetime.total_seconds()/3600 == test_data_storage.power_on_hours
|
assert (
|
||||||
|
test_data_storage.lifetime.total_seconds() / 3600
|
||||||
|
== test_data_storage.power_on_hours
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
|
@ -176,10 +203,7 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
|
|
||||||
def get_actions_info(actions: List[dict]) -> tuple:
|
def get_actions_info(actions: List[dict]) -> tuple:
|
||||||
return tuple(
|
return tuple(
|
||||||
(
|
(e['type'], [c['serialNumber'] for c in e['components']])
|
||||||
e['type'],
|
|
||||||
[c['serialNumber'] for c in e['components']]
|
|
||||||
)
|
|
||||||
for e in user.get_many(res=Action, resources=actions, key='id')
|
for e in user.get_many(res=Action, resources=actions, key='id')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -198,7 +222,11 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
||||||
update1_pc1 = pc1['updated']
|
update1_pc1 = pc1['updated']
|
||||||
# Parent contains components
|
# Parent contains components
|
||||||
assert tuple(c['serialNumber'] for c in pc1['components']) == ('p1c1s', 'p1c2s', 'p1c3s')
|
assert tuple(c['serialNumber'] for c in pc1['components']) == (
|
||||||
|
'p1c1s',
|
||||||
|
'p1c2s',
|
||||||
|
'p1c3s',
|
||||||
|
)
|
||||||
# Components contain parent
|
# Components contain parent
|
||||||
assert all(c['parent'] == pc1_id for c in pc1['components'])
|
assert all(c['parent'] == pc1_id for c in pc1['components'])
|
||||||
# pc has three actions: Snapshot, BenchmarkProcessor and RateComputer
|
# pc has three actions: Snapshot, BenchmarkProcessor and RateComputer
|
||||||
|
@ -228,7 +256,12 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
# PC1
|
# PC1
|
||||||
assert tuple(c['serialNumber'] for c in pc1['components']) == ('p1c1s', 'p1c3s')
|
assert tuple(c['serialNumber'] for c in pc1['components']) == ('p1c1s', 'p1c3s')
|
||||||
assert all(c['parent'] == pc1_id for c in pc1['components'])
|
assert all(c['parent'] == pc1_id for c in pc1['components'])
|
||||||
assert tuple(e['type'] for e in pc1['actions']) == ('BenchmarkProcessor', 'Snapshot', 'RateComputer', 'Remove')
|
assert tuple(e['type'] for e in pc1['actions']) == (
|
||||||
|
'BenchmarkProcessor',
|
||||||
|
'Snapshot',
|
||||||
|
'RateComputer',
|
||||||
|
'Remove',
|
||||||
|
)
|
||||||
# PC2
|
# PC2
|
||||||
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p1c2s', 'p2c1s')
|
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p1c2s', 'p2c1s')
|
||||||
assert all(c['parent'] == pc2_id for c in pc2['components'])
|
assert all(c['parent'] == pc2_id for c in pc2['components'])
|
||||||
|
@ -236,15 +269,24 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
# p1c2s has two Snapshots, a Remove and an Add
|
# p1c2s has two Snapshots, a Remove and an Add
|
||||||
p1c2s, _ = user.get(res=m.Device, item=pc2['components'][0]['devicehubID'])
|
p1c2s, _ = user.get(res=m.Device, item=pc2['components'][0]['devicehubID'])
|
||||||
assert tuple(e['type'] for e in p1c2s['actions']) == (
|
assert tuple(e['type'] for e in p1c2s['actions']) == (
|
||||||
'BenchmarkProcessor', 'Snapshot', 'RateComputer', 'Snapshot', 'Remove', 'RateComputer'
|
'BenchmarkProcessor',
|
||||||
|
'Snapshot',
|
||||||
|
'RateComputer',
|
||||||
|
'Snapshot',
|
||||||
|
'Remove',
|
||||||
|
'RateComputer',
|
||||||
)
|
)
|
||||||
|
|
||||||
# We register the first device again, but removing motherboard
|
# We register the first device again, but removing motherboard
|
||||||
# and moving processor from the second device to the first.
|
# and moving processor from the second device to the first.
|
||||||
# We have created 1 Remove (from PC2's processor back to PC1)
|
# We have created 1 Remove (from PC2's processor back to PC1)
|
||||||
# PC 0: p1c2s, p1c3s. PC 1: p2c1s
|
# PC 0: p1c2s, p1c3s. PC 1: p2c1s
|
||||||
s3 = yaml2json('3-first-device-but-removing-motherboard-and-adding-processor-from-2.snapshot')
|
s3 = yaml2json(
|
||||||
snapshot_and_check(user, s3, ('Remove', 'RateComputer'), perform_second_snapshot=False)
|
'3-first-device-but-removing-motherboard-and-adding-processor-from-2.snapshot'
|
||||||
|
)
|
||||||
|
snapshot_and_check(
|
||||||
|
user, s3, ('Remove', 'RateComputer'), perform_second_snapshot=False
|
||||||
|
)
|
||||||
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
||||||
pc2, _ = user.get(res=m.Device, item=pc2_devicehub_id)
|
pc2, _ = user.get(res=m.Device, item=pc2_devicehub_id)
|
||||||
# Check if the update_timestamp is updated
|
# Check if the update_timestamp is updated
|
||||||
|
@ -263,7 +305,7 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
('RateComputer', ['p1c1s', 'p1c2s', 'p1c3s']),
|
('RateComputer', ['p1c1s', 'p1c2s', 'p1c3s']),
|
||||||
('Remove', ['p1c2s']), # Remove Processor in Snapshot2
|
('Remove', ['p1c2s']), # Remove Processor in Snapshot2
|
||||||
('Snapshot', ['p1c2s', 'p1c3s']), # This Snapshot3
|
('Snapshot', ['p1c2s', 'p1c3s']), # This Snapshot3
|
||||||
('RateComputer', ['p1c2s', 'p1c3s'])
|
('RateComputer', ['p1c2s', 'p1c3s']),
|
||||||
)
|
)
|
||||||
# PC2
|
# PC2
|
||||||
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p2c1s',)
|
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p2c1s',)
|
||||||
|
@ -271,7 +313,7 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
assert tuple(e['type'] for e in pc2['actions']) == (
|
assert tuple(e['type'] for e in pc2['actions']) == (
|
||||||
'Snapshot', # Second Snapshot
|
'Snapshot', # Second Snapshot
|
||||||
'RateComputer',
|
'RateComputer',
|
||||||
'Remove' # the processor we added in 2.
|
'Remove', # the processor we added in 2.
|
||||||
)
|
)
|
||||||
# p1c2s has Snapshot, Remove and Add
|
# p1c2s has Snapshot, Remove and Add
|
||||||
p1c2s, _ = user.get(res=m.Device, item=pc1['components'][0]['devicehubID'])
|
p1c2s, _ = user.get(res=m.Device, item=pc1['components'][0]['devicehubID'])
|
||||||
|
@ -284,13 +326,17 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
('RateComputer', ['p1c2s', 'p2c1s']),
|
('RateComputer', ['p1c2s', 'p2c1s']),
|
||||||
('Snapshot', ['p1c2s', 'p1c3s']), # The third Snapshot to PC1
|
('Snapshot', ['p1c2s', 'p1c3s']), # The third Snapshot to PC1
|
||||||
('Remove', ['p1c2s']), # ...which caused p1c2 to be removed from PC2
|
('Remove', ['p1c2s']), # ...which caused p1c2 to be removed from PC2
|
||||||
('RateComputer', ['p1c2s', 'p1c3s'])
|
('RateComputer', ['p1c2s', 'p1c3s']),
|
||||||
)
|
)
|
||||||
|
|
||||||
# We register the first device but without the processor,
|
# We register the first device but without the processor,
|
||||||
# adding a graphic card and adding a new component
|
# adding a graphic card and adding a new component
|
||||||
s4 = yaml2json('4-first-device-but-removing-processor.snapshot-and-adding-graphic-card')
|
s4 = yaml2json(
|
||||||
snapshot4 = snapshot_and_check(user, s4, ('RateComputer',), perform_second_snapshot=False)
|
'4-first-device-but-removing-processor.snapshot-and-adding-graphic-card'
|
||||||
|
)
|
||||||
|
snapshot4 = snapshot_and_check(
|
||||||
|
user, s4, ('RateComputer',), perform_second_snapshot=False
|
||||||
|
)
|
||||||
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
||||||
pc2, _ = user.get(res=m.Device, item=pc2_devicehub_id)
|
pc2, _ = user.get(res=m.Device, item=pc2_devicehub_id)
|
||||||
# Check if the update_timestamp is updated
|
# Check if the update_timestamp is updated
|
||||||
|
@ -308,6 +354,7 @@ def test_snapshot_component_add_remove(user: UserClient):
|
||||||
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p2c1s',)
|
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p2c1s',)
|
||||||
assert all(c['parent'] == pc2_id for c in pc2['components'])
|
assert all(c['parent'] == pc2_id for c in pc2['components'])
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_post_without_hid(user: UserClient):
|
def test_snapshot_post_without_hid(user: UserClient):
|
||||||
"""Tests the post snapshot endpoint (validation, etc), data correctness,
|
"""Tests the post snapshot endpoint (validation, etc), data correctness,
|
||||||
|
@ -338,15 +385,18 @@ def test_snapshot_tag_inner_tag(user: UserClient, tag_id: str, app: Devicehub):
|
||||||
b = yaml2json('basic.snapshot')
|
b = yaml2json('basic.snapshot')
|
||||||
b['device']['tags'] = [{'type': 'Tag', 'id': tag_id}]
|
b['device']['tags'] = [{'type': 'Tag', 'id': tag_id}]
|
||||||
|
|
||||||
snapshot_and_check(user, b,
|
snapshot_and_check(
|
||||||
action_types=(RateComputer.t, BenchmarkProcessor.t, VisualTest.t))
|
user, b, action_types=(RateComputer.t, BenchmarkProcessor.t, VisualTest.t)
|
||||||
|
)
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
tag = Tag.query.all()[0] # type: Tag
|
tag = Tag.query.all()[0] # type: Tag
|
||||||
assert tag.device_id == 3, 'Tag should be linked to the first device'
|
assert tag.device_id == 3, 'Tag should be linked to the first device'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_tag_inner_tag_mismatch_between_tags_and_hid(user: UserClient, tag_id: str):
|
def test_snapshot_tag_inner_tag_mismatch_between_tags_and_hid(
|
||||||
|
user: UserClient, tag_id: str
|
||||||
|
):
|
||||||
"""Ensures one device cannot 'steal' the tag from another one."""
|
"""Ensures one device cannot 'steal' the tag from another one."""
|
||||||
pc1 = yaml2json('basic.snapshot')
|
pc1 = yaml2json('basic.snapshot')
|
||||||
pc1['device']['tags'] = [{'type': 'Tag', 'id': tag_id}]
|
pc1['device']['tags'] = [{'type': 'Tag', 'id': tag_id}]
|
||||||
|
@ -396,7 +446,7 @@ def test_snapshot_component_containing_components(user: UserClient):
|
||||||
'type': 'Processor',
|
'type': 'Processor',
|
||||||
'serialNumber': 'foo',
|
'serialNumber': 'foo',
|
||||||
'manufacturer': 'bar',
|
'manufacturer': 'bar',
|
||||||
'model': 'baz'
|
'model': 'baz',
|
||||||
}
|
}
|
||||||
user.post(json_encode(s), res=Snapshot, status=ValidationError)
|
user.post(json_encode(s), res=Snapshot, status=ValidationError)
|
||||||
|
|
||||||
|
@ -435,13 +485,15 @@ def test_not_remove_ram_in_same_computer(user: UserClient):
|
||||||
snap1, _ = user.post(json_encode(s), res=Snapshot)
|
snap1, _ = user.post(json_encode(s), res=Snapshot)
|
||||||
|
|
||||||
s['uuid'] = '74caa7eb-2bad-4333-94f6-6f1b031d0774'
|
s['uuid'] = '74caa7eb-2bad-4333-94f6-6f1b031d0774'
|
||||||
s['components'].append({
|
s['components'].append(
|
||||||
"actions": [],
|
{
|
||||||
"manufacturer": "Intel Corporation",
|
"actions": [],
|
||||||
"model": "NM10/ICH7 Family High Definition Audio Controller",
|
"manufacturer": "Intel Corporation",
|
||||||
"serialNumber": "mp2pc",
|
"model": "NM10/ICH7 Family High Definition Audio Controller",
|
||||||
"type": "SoundCard"
|
"serialNumber": "mp2pc",
|
||||||
})
|
"type": "SoundCard",
|
||||||
|
}
|
||||||
|
)
|
||||||
dev1 = m.Device.query.filter_by(id=snap1['device']['id']).one()
|
dev1 = m.Device.query.filter_by(id=snap1['device']['id']).one()
|
||||||
ram1 = [x.id for x in dev1.components if x.type == 'RamModule'][0]
|
ram1 = [x.id for x in dev1.components if x.type == 'RamModule'][0]
|
||||||
snap2, _ = user.post(json_encode(s), res=Snapshot)
|
snap2, _ = user.post(json_encode(s), res=Snapshot)
|
||||||
|
@ -466,13 +518,18 @@ def test_ereuse_price(user: UserClient):
|
||||||
s = yaml2json('erase-sectors.snapshot')
|
s = yaml2json('erase-sectors.snapshot')
|
||||||
assert s['components'][0]['actions'][0]['endTime'] == '2018-06-01T09:12:06+02:00'
|
assert s['components'][0]['actions'][0]['endTime'] == '2018-06-01T09:12:06+02:00'
|
||||||
s['device']['type'] = 'Server'
|
s['device']['type'] = 'Server'
|
||||||
snapshot = snapshot_and_check(user, s, action_types=(
|
snapshot = snapshot_and_check(
|
||||||
EraseSectors.t,
|
user,
|
||||||
BenchmarkDataStorage.t,
|
s,
|
||||||
BenchmarkProcessor.t,
|
action_types=(
|
||||||
RateComputer.t,
|
EraseSectors.t,
|
||||||
EreusePrice.t
|
BenchmarkDataStorage.t,
|
||||||
), perform_second_snapshot=False)
|
BenchmarkProcessor.t,
|
||||||
|
RateComputer.t,
|
||||||
|
EreusePrice.t,
|
||||||
|
),
|
||||||
|
perform_second_snapshot=False,
|
||||||
|
)
|
||||||
ereuse_price = snapshot['actions'][-1]
|
ereuse_price = snapshot['actions'][-1]
|
||||||
assert len(ereuse_price) > 0
|
assert len(ereuse_price) > 0
|
||||||
|
|
||||||
|
@ -487,33 +544,54 @@ def test_erase_privacy_standards_endtime_sort(user: UserClient):
|
||||||
"""
|
"""
|
||||||
s = yaml2json('erase-sectors.snapshot')
|
s = yaml2json('erase-sectors.snapshot')
|
||||||
assert s['components'][0]['actions'][0]['endTime'] == '2018-06-01T09:12:06+02:00'
|
assert s['components'][0]['actions'][0]['endTime'] == '2018-06-01T09:12:06+02:00'
|
||||||
snapshot = snapshot_and_check(user, s, action_types=(
|
snapshot = snapshot_and_check(
|
||||||
EraseSectors.t,
|
user,
|
||||||
BenchmarkDataStorage.t,
|
s,
|
||||||
BenchmarkProcessor.t,
|
action_types=(
|
||||||
RateComputer.t,
|
EraseSectors.t,
|
||||||
EreusePrice.t
|
BenchmarkDataStorage.t,
|
||||||
), perform_second_snapshot=False)
|
BenchmarkProcessor.t,
|
||||||
|
RateComputer.t,
|
||||||
|
EreusePrice.t,
|
||||||
|
),
|
||||||
|
perform_second_snapshot=False,
|
||||||
|
)
|
||||||
# Perform a new snapshot changing the erasure time, as if
|
# Perform a new snapshot changing the erasure time, as if
|
||||||
# it is a new erasure performed after.
|
# it is a new erasure performed after.
|
||||||
erase = next(e for e in snapshot['actions'] if e['type'] == EraseSectors.t)
|
erase = next(e for e in snapshot['actions'] if e['type'] == EraseSectors.t)
|
||||||
assert erase['endTime'] == '2018-06-01T07:12:06+00:00'
|
assert erase['endTime'] == '2018-06-01T07:12:06+00:00'
|
||||||
s['uuid'] = uuid4()
|
s['uuid'] = uuid4()
|
||||||
s['components'][0]['actions'][0]['endTime'] = '2018-06-01T07:14:00+00:00'
|
s['components'][0]['actions'][0]['endTime'] = '2018-06-01T07:14:00+00:00'
|
||||||
snapshot = snapshot_and_check(user, s, action_types=(
|
snapshot = snapshot_and_check(
|
||||||
EraseSectors.t,
|
user,
|
||||||
BenchmarkDataStorage.t,
|
s,
|
||||||
BenchmarkProcessor.t,
|
action_types=(
|
||||||
RateComputer.t,
|
EraseSectors.t,
|
||||||
EreusePrice.t
|
BenchmarkDataStorage.t,
|
||||||
), perform_second_snapshot=False)
|
BenchmarkProcessor.t,
|
||||||
|
RateComputer.t,
|
||||||
|
EreusePrice.t,
|
||||||
|
),
|
||||||
|
perform_second_snapshot=False,
|
||||||
|
)
|
||||||
|
|
||||||
# The actual test
|
# The actual test
|
||||||
storage = next(e for e in snapshot['components'] if e['type'] == SolidStateDrive.t)
|
storage = next(e for e in snapshot['components'] if e['type'] == SolidStateDrive.t)
|
||||||
storage, _ = user.get(res=m.Device, item=storage['devicehubID']) # Let's get storage actions too
|
storage, _ = user.get(
|
||||||
|
res=m.Device, item=storage['devicehubID']
|
||||||
|
) # Let's get storage actions too
|
||||||
# order: endTime ascending
|
# order: endTime ascending
|
||||||
# erasure1/2 have an user defined time and others actions endTime = created
|
# erasure1/2 have an user defined time and others actions endTime = created
|
||||||
erasure1, erasure2, benchmark_hdd1, _snapshot1, _, _, benchmark_hdd2, _snapshot2 = storage['actions'][:8]
|
(
|
||||||
|
erasure1,
|
||||||
|
erasure2,
|
||||||
|
benchmark_hdd1,
|
||||||
|
_snapshot1,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
benchmark_hdd2,
|
||||||
|
_snapshot2,
|
||||||
|
) = storage['actions'][:8]
|
||||||
assert erasure1['type'] == erasure2['type'] == 'EraseSectors'
|
assert erasure1['type'] == erasure2['type'] == 'EraseSectors'
|
||||||
assert benchmark_hdd1['type'] == benchmark_hdd2['type'] == 'BenchmarkDataStorage'
|
assert benchmark_hdd1['type'] == benchmark_hdd2['type'] == 'BenchmarkDataStorage'
|
||||||
assert _snapshot1['type'] == _snapshot2['type'] == 'Snapshot'
|
assert _snapshot1['type'] == _snapshot2['type'] == 'Snapshot'
|
||||||
|
@ -555,8 +633,7 @@ def test_test_data_storage(user: UserClient):
|
||||||
s = file('erase-sectors-2-hdd.snapshot')
|
s = file('erase-sectors-2-hdd.snapshot')
|
||||||
snapshot, _ = user.post(res=Snapshot, data=s)
|
snapshot, _ = user.post(res=Snapshot, data=s)
|
||||||
incidence_test = next(
|
incidence_test = next(
|
||||||
ev for ev in snapshot['actions']
|
ev for ev in snapshot['actions'] if ev.get('reallocatedSectorCount', None) == 15
|
||||||
if ev.get('reallocatedSectorCount', None) == 15
|
|
||||||
)
|
)
|
||||||
assert incidence_test['severity'] == 'Error'
|
assert incidence_test['severity'] == 'Error'
|
||||||
|
|
||||||
|
@ -584,22 +661,24 @@ def assert_similar_components(components1: List[dict], components2: List[dict]):
|
||||||
assert_similar_device(c1, c2)
|
assert_similar_device(c1, c2)
|
||||||
|
|
||||||
|
|
||||||
def snapshot_and_check(user: UserClient,
|
def snapshot_and_check(
|
||||||
input_snapshot: dict,
|
user: UserClient,
|
||||||
action_types: Tuple[str, ...] = tuple(),
|
input_snapshot: dict,
|
||||||
perform_second_snapshot=True) -> dict:
|
action_types: Tuple[str, ...] = tuple(),
|
||||||
|
perform_second_snapshot=True,
|
||||||
|
) -> dict:
|
||||||
"""Performs a Snapshot and then checks if the result is ok:
|
"""Performs a Snapshot and then checks if the result is ok:
|
||||||
|
|
||||||
- There have been performed the types of actions and in the same
|
- There have been performed the types of actions and in the same
|
||||||
order as described in the passed-in ``action_types``.
|
order as described in the passed-in ``action_types``.
|
||||||
- The inputted devices are similar to the resulted ones.
|
- The inputted devices are similar to the resulted ones.
|
||||||
- There is no Remove action after the first Add.
|
- There is no Remove action after the first Add.
|
||||||
- All input components are now inside the parent device.
|
- All input components are now inside the parent device.
|
||||||
|
|
||||||
Optionally, it can perform a second Snapshot which should
|
Optionally, it can perform a second Snapshot which should
|
||||||
perform an exact result, except for the actions.
|
perform an exact result, except for the actions.
|
||||||
|
|
||||||
:return: The last resulting snapshot.
|
:return: The last resulting snapshot.
|
||||||
"""
|
"""
|
||||||
snapshot, _ = user.post(res=Snapshot, data=json_encode(input_snapshot))
|
snapshot, _ = user.post(res=Snapshot, data=json_encode(input_snapshot))
|
||||||
assert all(e['type'] in action_types for e in snapshot['actions'])
|
assert all(e['type'] in action_types for e in snapshot['actions'])
|
||||||
|
@ -610,18 +689,22 @@ def snapshot_and_check(user: UserClient,
|
||||||
if action['type'] == 'Add':
|
if action['type'] == 'Add':
|
||||||
found_add = True
|
found_add = True
|
||||||
if found_add:
|
if found_add:
|
||||||
assert action['type'] != 'Receive', 'All Remove actions must be before the Add ones'
|
assert (
|
||||||
|
action['type'] != 'Receive'
|
||||||
|
), 'All Remove actions must be before the Add ones'
|
||||||
assert input_snapshot['device']
|
assert input_snapshot['device']
|
||||||
assert_similar_device(input_snapshot['device'], snapshot['device'])
|
assert_similar_device(input_snapshot['device'], snapshot['device'])
|
||||||
if input_snapshot.get('components', None):
|
if input_snapshot.get('components', None):
|
||||||
assert_similar_components(input_snapshot['components'], snapshot['components'])
|
assert_similar_components(input_snapshot['components'], snapshot['components'])
|
||||||
assert all(c['parent'] == snapshot['device']['id'] for c in snapshot['components']), \
|
assert all(
|
||||||
'Components must be in their parent'
|
c['parent'] == snapshot['device']['id'] for c in snapshot['components']
|
||||||
|
), 'Components must be in their parent'
|
||||||
if perform_second_snapshot:
|
if perform_second_snapshot:
|
||||||
if 'uuid' in input_snapshot:
|
if 'uuid' in input_snapshot:
|
||||||
input_snapshot['uuid'] = uuid4()
|
input_snapshot['uuid'] = uuid4()
|
||||||
return snapshot_and_check(user, input_snapshot, action_types,
|
return snapshot_and_check(
|
||||||
perform_second_snapshot=False)
|
user, input_snapshot, action_types, perform_second_snapshot=False
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return snapshot
|
return snapshot
|
||||||
|
|
||||||
|
@ -642,12 +725,12 @@ def test_erase_changing_hdd_between_pcs(user: UserClient):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
assert dev2.components[1].actions[2].parent == dev1
|
assert dev2.components[1].actions[2].parent == dev1
|
||||||
doc1, response = user.get(res=documents.DocumentDef.t,
|
doc1, response = user.get(
|
||||||
item='erasures/{}'.format(dev1.id),
|
res=documents.DocumentDef.t, item='erasures/{}'.format(dev1.id), accept=ANY
|
||||||
accept=ANY)
|
)
|
||||||
doc2, response = user.get(res=documents.DocumentDef.t,
|
doc2, response = user.get(
|
||||||
item='erasures/{}'.format(dev2.id),
|
res=documents.DocumentDef.t, item='erasures/{}'.format(dev2.id), accept=ANY
|
||||||
accept=ANY)
|
)
|
||||||
assert 'dev1' in doc2
|
assert 'dev1' in doc2
|
||||||
assert 'dev2' in doc2
|
assert 'dev2' in doc2
|
||||||
|
|
||||||
|
@ -667,10 +750,9 @@ def test_pc_2(user: UserClient):
|
||||||
snapshot, _ = user.post(res=Snapshot, data=s)
|
snapshot, _ = user.post(res=Snapshot, data=s)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_save_snapshot_in_file(app: Devicehub, user: UserClient):
|
def test_save_snapshot_in_file(app: Devicehub, user: UserClient):
|
||||||
""" This test check if works the function save_snapshot_in_file """
|
"""This test check if works the function save_snapshot_in_file"""
|
||||||
snapshot_no_hid = yaml2json('basic.snapshot.nohid')
|
snapshot_no_hid = yaml2json('basic.snapshot.nohid')
|
||||||
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||||
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
||||||
|
@ -696,7 +778,7 @@ def test_save_snapshot_in_file(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_action_no_snapshot_without_save_file(app: Devicehub, user: UserClient):
|
def test_action_no_snapshot_without_save_file(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the function save_snapshot_in_file not work when we
|
"""This test check if the function save_snapshot_in_file not work when we
|
||||||
send one other action different to snapshot
|
send one other action different to snapshot
|
||||||
"""
|
"""
|
||||||
s = file('laptop-hp_255_g3_notebook-hewlett-packard-cnd52270fw.snapshot')
|
s = file('laptop-hp_255_g3_notebook-hewlett-packard-cnd52270fw.snapshot')
|
||||||
|
@ -712,9 +794,10 @@ def test_action_no_snapshot_without_save_file(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
assert os.path.exists(tmp_snapshots) == False
|
assert os.path.exists(tmp_snapshots) == False
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_save_snapshot_with_debug(app: Devicehub, user: UserClient):
|
def test_save_snapshot_with_debug(app: Devicehub, user: UserClient):
|
||||||
""" This test check if works the function save_snapshot_in_file """
|
"""This test check if works the function save_snapshot_in_file"""
|
||||||
snapshot_file = yaml2json('basic.snapshot.with_debug')
|
snapshot_file = yaml2json('basic.snapshot.with_debug')
|
||||||
debug = snapshot_file['debug']
|
debug = snapshot_file['debug']
|
||||||
user.post(res=Snapshot, data=json_encode(snapshot_file))
|
user.post(res=Snapshot, data=json_encode(snapshot_file))
|
||||||
|
@ -738,7 +821,7 @@ def test_save_snapshot_with_debug(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_backup_snapshot_with_errors(app: Devicehub, user: UserClient):
|
def test_backup_snapshot_with_errors(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the file snapshot is create when some snapshot is wrong """
|
"""This test check if the file snapshot is create when some snapshot is wrong"""
|
||||||
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||||
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
||||||
snapshot_no_hid = yaml2json('basic.snapshot.badly_formed')
|
snapshot_no_hid = yaml2json('basic.snapshot.badly_formed')
|
||||||
|
@ -763,7 +846,7 @@ def test_backup_snapshot_with_errors(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_failed_missing_cpu_benchmark(app: Devicehub, user: UserClient):
|
def test_snapshot_failed_missing_cpu_benchmark(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the file snapshot is create when some snapshot is wrong """
|
"""This test check if the file snapshot is create when some snapshot is wrong"""
|
||||||
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||||
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
||||||
snapshot_error = yaml2json('failed.snapshot.500.missing-cpu-benchmark')
|
snapshot_error = yaml2json('failed.snapshot.500.missing-cpu-benchmark')
|
||||||
|
@ -788,7 +871,7 @@ def test_snapshot_failed_missing_cpu_benchmark(app: Devicehub, user: UserClient)
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_failed_missing_hdd_benchmark(app: Devicehub, user: UserClient):
|
def test_snapshot_failed_missing_hdd_benchmark(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the file snapshot is create when some snapshot is wrong """
|
"""This test check if the file snapshot is create when some snapshot is wrong"""
|
||||||
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||||
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
||||||
snapshot_error = yaml2json('failed.snapshot.500.missing-hdd-benchmark')
|
snapshot_error = yaml2json('failed.snapshot.500.missing-hdd-benchmark')
|
||||||
|
@ -813,7 +896,7 @@ def test_snapshot_failed_missing_hdd_benchmark(app: Devicehub, user: UserClient)
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_not_failed_null_chassis(app: Devicehub, user: UserClient):
|
def test_snapshot_not_failed_null_chassis(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the file snapshot is create when some snapshot is wrong """
|
"""This test check if the file snapshot is create when some snapshot is wrong"""
|
||||||
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||||
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
||||||
snapshot_error = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot')
|
snapshot_error = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot')
|
||||||
|
@ -831,7 +914,7 @@ def test_snapshot_not_failed_null_chassis(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_failed_missing_chassis(app: Devicehub, user: UserClient):
|
def test_snapshot_failed_missing_chassis(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the file snapshot is create when some snapshot is wrong """
|
"""This test check if the file snapshot is create when some snapshot is wrong"""
|
||||||
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||||
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors')
|
||||||
snapshot_error = yaml2json('failed.snapshot.422.missing-chassis')
|
snapshot_error = yaml2json('failed.snapshot.422.missing-chassis')
|
||||||
|
@ -856,7 +939,7 @@ def test_snapshot_failed_missing_chassis(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_failed_end_time_bug(app: Devicehub, user: UserClient):
|
def test_snapshot_failed_end_time_bug(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the end_time = 0001-01-01 00:00:00+00:00
|
"""This test check if the end_time = 0001-01-01 00:00:00+00:00
|
||||||
and then we get a /devices, this create a crash
|
and then we get a /devices, this create a crash
|
||||||
"""
|
"""
|
||||||
snapshot_file = file('asus-end_time_bug88.snapshot')
|
snapshot_file = file('asus-end_time_bug88.snapshot')
|
||||||
|
@ -870,9 +953,10 @@ def test_snapshot_failed_end_time_bug(app: Devicehub, user: UserClient):
|
||||||
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||||
shutil.rmtree(tmp_snapshots)
|
shutil.rmtree(tmp_snapshots)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_not_failed_end_time_bug(app: Devicehub, user: UserClient):
|
def test_snapshot_not_failed_end_time_bug(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the end_time != 0001-01-01 00:00:00+00:00
|
"""This test check if the end_time != 0001-01-01 00:00:00+00:00
|
||||||
and then we get a /devices, this create a crash
|
and then we get a /devices, this create a crash
|
||||||
"""
|
"""
|
||||||
snapshot_file = yaml2json('asus-end_time_bug88.snapshot')
|
snapshot_file = yaml2json('asus-end_time_bug88.snapshot')
|
||||||
|
@ -891,7 +975,7 @@ def test_snapshot_not_failed_end_time_bug(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_bug_smallint_hdd(app: Devicehub, user: UserClient):
|
def test_snapshot_bug_smallint_hdd(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the end_time != 0001-01-01 00:00:00+00:00
|
"""This test check if the end_time != 0001-01-01 00:00:00+00:00
|
||||||
and then we get a /devices, this create a crash
|
and then we get a /devices, this create a crash
|
||||||
"""
|
"""
|
||||||
snapshot_file = file('asus-eee-1000h.snapshot.bug1857')
|
snapshot_file = file('asus-eee-1000h.snapshot.bug1857')
|
||||||
|
@ -907,7 +991,7 @@ def test_snapshot_bug_smallint_hdd(app: Devicehub, user: UserClient):
|
||||||
|
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_snapshot_mobil(app: Devicehub, user: UserClient):
|
def test_snapshot_mobil(app: Devicehub, user: UserClient):
|
||||||
""" This test check if the end_time != 0001-01-01 00:00:00+00:00
|
"""This test check if the end_time != 0001-01-01 00:00:00+00:00
|
||||||
and then we get a /devices, this create a crash
|
and then we get a /devices, this create a crash
|
||||||
"""
|
"""
|
||||||
snapshot_file = file('mobil')
|
snapshot_file = file('mobil')
|
||||||
|
@ -921,8 +1005,24 @@ def test_snapshot_mobil(app: Devicehub, user: UserClient):
|
||||||
@pytest.mark.mvp
|
@pytest.mark.mvp
|
||||||
def test_bug_141(user: UserClient):
|
def test_bug_141(user: UserClient):
|
||||||
"""This test check one bug that create a problem when try to up one snapshot
|
"""This test check one bug that create a problem when try to up one snapshot
|
||||||
with a big number in the parameter command_timeout of the DataStorage
|
with a big number in the parameter command_timeout of the DataStorage
|
||||||
|
|
||||||
"""
|
"""
|
||||||
dev = file('2021-5-4-13-41_time_out_test_datastorage')
|
dev = file('2021-5-4-13-41_time_out_test_datastorage')
|
||||||
user.post(dev, res=Snapshot)
|
user.post(dev, res=Snapshot)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.mvp
|
||||||
|
def test_min_validate_fields(user: UserClient):
|
||||||
|
"""This test check the minimum validation of json that come from snapshot"""
|
||||||
|
snapshot = {
|
||||||
|
"type": "Snapshot",
|
||||||
|
"uuid": "d1b70cb8-8929-4f36-99b7-fe052cec0abd",
|
||||||
|
"version": "14.0.0",
|
||||||
|
"endTime": "2016-11-03T17:17:17.266543+00:00",
|
||||||
|
"dmidecode": '',
|
||||||
|
"smartctl": '',
|
||||||
|
}
|
||||||
|
body, res = user.post(snapshot, res=Snapshot)
|
||||||
|
assert body == 'Ok'
|
||||||
|
assert res.status == '201 CREATED'
|
||||||
|
|
Reference in New Issue