Fix rate related issues

This commit is contained in:
Xavier Bustamante Talavera 2019-02-13 18:59:14 +01:00
parent 15f705dd50
commit 32e696c57c
6 changed files with 337 additions and 18 deletions

View File

@ -36,6 +36,7 @@ class SQLAlchemy(SchemaSQLAlchemy):
# manually import them all the time # manually import them all the time
UUID = postgresql.UUID UUID = postgresql.UUID
CIText = citext.CIText CIText = citext.CIText
PSQL_INT_MAX = 2147483648
def drop_all(self, bind='__all__', app=None, common_schema=True): def drop_all(self, bind='__all__', app=None, common_schema=True):
"""A faster nuke-like option to drop everything.""" """A faster nuke-like option to drop everything."""

View File

@ -593,7 +593,12 @@ class Rate(JoinedWithOneDeviceMixin, EventWithOneDevice):
plus the ``WorkbenchRate`` from 1. plus the ``WorkbenchRate`` from 1.
""" """
rating = Column(Float(decimal_return_scale=2), check_range('rating', *RATE_POSITIVE)) rating = Column(Float(decimal_return_scale=2), check_range('rating', *RATE_POSITIVE))
rating.comment = """The rating for the content.""" rating.comment = """The rating for the content.
This value is automatically set by rating algorithms. In case that
no algorithm is defined per the device and type of rate, this
value is None.
"""
software = Column(DBEnum(RatingSoftware)) software = Column(DBEnum(RatingSoftware))
software.comment = """The algorithm used to produce this rating.""" software.comment = """The algorithm used to produce this rating."""
version = Column(StrictVersionType) version = Column(StrictVersionType)
@ -604,8 +609,7 @@ class Rate(JoinedWithOneDeviceMixin, EventWithOneDevice):
@property @property
def rating_range(self) -> RatingRange: def rating_range(self) -> RatingRange:
if self.rating: return RatingRange.from_score(self.rating) if self.rating else None
return RatingRange.from_score(self.rating)
@declared_attr @declared_attr
def __mapper_args__(cls): def __mapper_args__(cls):
@ -782,13 +786,12 @@ class AggregateRate(Rate):
@classmethod @classmethod
def from_workbench_rate(cls, rate: WorkbenchRate): def from_workbench_rate(cls, rate: WorkbenchRate):
aggregate = cls() aggregate = cls(rating=rate.rating,
aggregate.rating = rate.rating software=rate.software,
aggregate.software = rate.software appearance=rate.appearance,
aggregate.appearance = rate.appearance functionality=rate.functionality,
aggregate.functionality = rate.functionality device=rate.device,
aggregate.device = rate.device workbench=rate)
aggregate.workbench = rate
return aggregate return aggregate
@ -836,7 +839,7 @@ class Price(JoinedWithOneDeviceMixin, EventWithOneDevice):
@classmethod @classmethod
def to_price(cls, value: Union[Decimal, float], rounding=ROUND) -> Decimal: def to_price(cls, value: Union[Decimal, float], rounding=ROUND) -> Decimal:
"""Returns a Decimal value with the correct scale for Price.price.""" """Returns a Decimal value with the correct scale for Price.price."""
if isinstance(value, float): if isinstance(value, (float, int)):
value = Decimal(value) value = Decimal(value)
# equation from marshmallow.fields.Decimal # equation from marshmallow.fields.Decimal
return value.quantize(Decimal((0, (1,), -cls.SCALE)), rounding=rounding) return value.quantize(Decimal((0, (1,), -cls.SCALE)), rounding=rounding)
@ -920,8 +923,8 @@ class EreusePrice(Price):
self.warranty2 = EreusePrice.Type(rate[self.WARRANTY2][role], price) self.warranty2 = EreusePrice.Type(rate[self.WARRANTY2][role], price)
def __init__(self, rating: AggregateRate, **kwargs) -> None: def __init__(self, rating: AggregateRate, **kwargs) -> None:
if rating.rating_range == RatingRange.VERY_LOW: if not rating.rating_range or rating.rating_range == RatingRange.VERY_LOW:
raise ValueError('Cannot compute price for Range.VERY_LOW') raise InvalidRangeForPrice()
# We pass ROUND_UP strategy so price is always greater than what refurbisher... amounts # We pass ROUND_UP strategy so price is always greater than what refurbisher... amounts
price = self.to_price(rating.rating * self.MULTIPLIER[rating.device.__class__], ROUND_UP) price = self.to_price(rating.rating * self.MULTIPLIER[rating.device.__class__], ROUND_UP)
super().__init__(rating=rating, super().__init__(rating=rating,
@ -993,7 +996,7 @@ class TestDataStorage(Test):
assessment = Column(Boolean) assessment = Column(Boolean)
reallocated_sector_count = Column(SmallInteger) reallocated_sector_count = Column(SmallInteger)
power_cycle_count = Column(SmallInteger) power_cycle_count = Column(SmallInteger)
reported_uncorrectable_errors = Column(SmallInteger) _reported_uncorrectable_errors = Column('reported_uncorrectable_errors', Integer)
command_timeout = Column(Integer) command_timeout = Column(Integer)
current_pending_sector_count = Column(SmallInteger) current_pending_sector_count = Column(SmallInteger)
offline_uncorrectable = Column(SmallInteger) offline_uncorrectable = Column(SmallInteger)
@ -1021,6 +1024,16 @@ class TestDataStorage(Test):
t += self.description t += self.description
return t return t
@property
def reported_uncorrectable_errors(self):
return self._reported_uncorrectable_errors
@reported_uncorrectable_errors.setter
def reported_uncorrectable_errors(self, value):
# There is no value for a stratospherically big number
self._reported_uncorrectable_errors = min(value, db.PSQL_INT_MAX)
class StressTest(Test): class StressTest(Test):
"""The act of stressing (putting to the maximum capacity) """The act of stressing (putting to the maximum capacity)
@ -1401,3 +1414,7 @@ def update_parent(target: Union[EraseBasic, Test, Install], device: Device, _, _
target.parent = None target.parent = None
if isinstance(device, Component): if isinstance(device, Component):
target.parent = device.parent target.parent = device.parent
class InvalidRangeForPrice(ValueError):
pass

View File

@ -4,8 +4,8 @@ from typing import Set, Union
from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.device.models import Device
from ereuse_devicehub.resources.enums import RatingSoftware from ereuse_devicehub.resources.enums import RatingSoftware
from ereuse_devicehub.resources.event.models import AggregateRate, EreusePrice, Rate, \ from ereuse_devicehub.resources.event.models import AggregateRate, EreusePrice, \
WorkbenchRate InvalidRangeForPrice, Rate, WorkbenchRate
from ereuse_devicehub.resources.event.rate.workbench import v1_0 from ereuse_devicehub.resources.event.rate.workbench import v1_0
RATE_TYPES = { RATE_TYPES = {
@ -72,7 +72,6 @@ def main(rating_model: WorkbenchRate,
if soft == software and vers == version: if soft == software and vers == version:
aggregation = AggregateRate.from_workbench_rate(rating) aggregation = AggregateRate.from_workbench_rate(rating)
events.add(aggregation) events.add(aggregation)
with suppress(ValueError): with suppress(InvalidRangeForPrice): # We will have exception if range == VERY_LOW
# We will have exception if range == VERY_LOW
events.add(EreusePrice(aggregation)) events.add(EreusePrice(aggregation))
return events return events

View File

@ -0,0 +1,121 @@
{
"closed": true,
"components": [
{
"events": [],
"manufacturer": "Intel Corporation",
"model": "NM10/ICH7 Family High Definition Audio Controller",
"serialNumber": null,
"type": "SoundCard"
},
{
"events": [],
"manufacturer": "Broadcom Inc. and subsidiaries",
"model": "NetLink BCM5786 Gigabit Ethernet PCI Express",
"serialNumber": "00:1a:6b:5e:7f:10",
"speed": 1000,
"type": "NetworkAdapter",
"wireless": false
},
{
"events": [],
"format": "DIMM",
"interface": "DDR",
"manufacturer": null,
"model": null,
"serialNumber": null,
"size": 1024,
"speed": 133.0,
"type": "RamModule"
},
{
"events": [],
"format": "DIMM",
"interface": "DDR",
"manufacturer": null,
"model": null,
"serialNumber": null,
"size": 1024,
"speed": 133.0,
"type": "RamModule"
},
{
"address": 64,
"events": [
{
"elapsed": 33,
"rate": 32.9274,
"type": "BenchmarkProcessorSysbench"
},
{
"elapsed": 0,
"rate": 8771.5,
"type": "BenchmarkProcessor"
}
],
"manufacturer": "Intel Corp.",
"model": "Intel Core2 Duo CPU E4500 @ 2.20GHz",
"serialNumber": null,
"speed": 1.1,
"threads": 2,
"type": "Processor"
},
{
"events": [],
"manufacturer": "Intel Corporation",
"memory": 256.0,
"model": "82946GZ/GL Integrated Graphics Controller",
"serialNumber": null,
"type": "GraphicCard"
},
{
"events": [],
"firewire": 0,
"manufacturer": "LENOVO",
"model": "LENOVO",
"pcmcia": 0,
"serial": 1,
"serialNumber": null,
"slots": 0,
"type": "Motherboard",
"usb": 5
}
],
"device": {
"chassis": "Microtower",
"events": [
{
"appearanceRange": "D",
"biosRange": "E",
"functionalityRange": "D",
"type": "WorkbenchRate"
},
{
"elapsed": 300,
"severity": "Info",
"type": "StressTest"
},
{
"elapsed": 2,
"rate": 1.4968,
"type": "BenchmarkRamSysbench"
}
],
"manufacturer": "LENOVO",
"model": "9644W8N",
"serialNumber": "0169622",
"type": "Desktop"
},
"elapsed": 338,
"endTime": "2019-02-13T11:57:31.378330+00:00",
"expectedEvents": [
"Benchmark",
"TestDataStorage",
"StressTest",
"Install"
],
"software": "Workbench",
"type": "Snapshot",
"uuid": "d7904bd3-7d0f-4918-86b1-e21bfab738f9",
"version": "11.0b5"
}

View File

@ -0,0 +1,170 @@
{
"closed": true,
"components": [
{
"events": [],
"manufacturer": "Qualcomm Atheros",
"model": "QCA9565 / AR9565 Wireless Network Adapter",
"serialNumber": "ac:e0:10:c2:e3:ac",
"type": "NetworkAdapter",
"wireless": true
},
{
"events": [],
"manufacturer": "Realtek Semiconductor Co., Ltd.",
"model": "RTL810xE PCI Express Fast Ethernet controller",
"serialNumber": "30:8d:99:25:6c:d9",
"speed": 100,
"type": "NetworkAdapter",
"wireless": false
},
{
"events": [],
"manufacturer": "Advanced Micro Devices, Inc. AMD/ATI",
"model": "Kabini HDMI/DP Audio",
"serialNumber": null,
"type": "SoundCard"
},
{
"events": [],
"manufacturer": "Chicony Electronics Co.,Ltd.",
"model": "HP Webcam",
"serialNumber": "0x0001",
"type": "SoundCard"
},
{
"events": [],
"manufacturer": "Advanced Micro Devices, Inc. AMD",
"model": "FCH Azalia Controller",
"serialNumber": null,
"type": "SoundCard"
},
{
"events": [],
"format": "SODIMM",
"interface": "DDR3",
"manufacturer": "Hynix",
"model": "HMT451S6AFR8A-PB",
"serialNumber": "11743764",
"size": 4096,
"speed": 667.0,
"type": "RamModule"
},
{
"address": 64,
"cores": 2,
"events": [
{
"elapsed": 0,
"rate": 3992.32,
"type": "BenchmarkProcessor"
},
{
"elapsed": 65,
"rate": 65.3007,
"type": "BenchmarkProcessorSysbench"
}
],
"manufacturer": "Advanced Micro Devices AMD",
"model": "AMD E1-2100 APU with Radeon HD Graphics",
"serialNumber": null,
"speed": 0.9,
"threads": 2,
"type": "Processor"
},
{
"events": [
{
"elapsed": 12,
"readSpeed": 90.0,
"type": "BenchmarkDataStorage",
"writeSpeed": 30.7
},
{
"assessment": true,
"commandTimeout": 1341,
"currentPendingSectorCount": 0,
"elapsed": 113,
"length": "Short",
"lifetime": 1782,
"offlineUncorrectable": 0,
"powerCycleCount": 806,
"reallocatedSectorCount": 224,
"reportedUncorrectableErrors": 9961472,
"severity": "Info",
"status": "Completed without error",
"type": "TestDataStorage"
},
{
"address": 32,
"elapsed": 690,
"name": "LinuxMint-19-x86-es-2018-12.fsa",
"severity": "Info",
"type": "Install"
}
],
"interface": "ATA",
"manufacturer": null,
"model": "HGST HTS545050A7",
"serialNumber": "TE85134N34LNSN",
"size": 476940,
"type": "HardDrive"
},
{
"events": [],
"manufacturer": "Advanced Micro Devices, Inc. AMD/ATI",
"memory": 256.0,
"model": "Kabini Radeon HD 8210",
"serialNumber": null,
"type": "GraphicCard"
},
{
"events": [],
"firewire": 0,
"manufacturer": "Hewlett-Packard",
"model": "21F7",
"pcmcia": 0,
"serial": 1,
"serialNumber": "PEHERF41U8P9TV",
"slots": 0,
"type": "Motherboard",
"usb": 5
}
],
"device": {
"chassis": "Netbook",
"events": [
{
"appearanceRange": "A",
"functionalityRange": "A",
"type": "WorkbenchRate"
},
{
"elapsed": 300,
"severity": "Info",
"type": "StressTest"
},
{
"elapsed": 6,
"rate": 5.8783,
"type": "BenchmarkRamSysbench"
}
],
"manufacturer": "Hewlett-Packard",
"model": "HP 255 G3 Notebook",
"serialNumber": "CND52270FW",
"type": "Laptop"
},
"elapsed": 1194,
"endTime": "2019-02-13T10:13:50.535387+00:00",
"expectedEvents": [
"Benchmark",
"TestDataStorage",
"StressTest",
"Install"
],
"software": "Workbench",
"type": "Snapshot",
"uuid": "ca564895-567e-4ac2-9a0d-2d1402528687",
"version": "11.0b5"
}

View File

@ -453,3 +453,14 @@ def test_snapshot_keyboard(user: UserClient):
snapshot = snapshot_and_check(user, s, event_types=('ManualRate',)) snapshot = snapshot_and_check(user, s, event_types=('ManualRate',))
keyboard = snapshot['device'] keyboard = snapshot['device']
assert keyboard['layout'] == 'ES' assert keyboard['layout'] == 'ES'
def test_pc_rating_rate_none(user: UserClient):
"""Tests a Snapshot with EraseSectors."""
s = file('desktop-9644w8n-lenovo-0169622.snapshot')
snapshot, _ = user.post(res=Snapshot, data=s)
def test_pc_2(user: UserClient):
s = file('laptop-hp_255_g3_notebook-hewlett-packard-cnd52270fw.snapshot')
snapshot, _ = user.post(res=Snapshot, data=s)