From 42b0b0ebbc654f5c81df7e6d2d7a920730a23c13 Mon Sep 17 00:00:00 2001 From: Xavier Bustamante Talavera Date: Fri, 3 Aug 2018 18:15:08 +0200 Subject: [PATCH] Complete events and agents. Bump to 0.2.0a11. --- docs/{events.puml => actions.puml} | 28 +- docs/actions.rst | 443 ++++++++++++++++++ docs/agents.puml | 25 + docs/agents.rst | 4 + docs/association-events.puml | 81 +--- docs/conf.py | 2 +- docs/etag.rst | 1 - docs/events.rst | 197 -------- docs/index.rst | 7 +- docs/states.puml | 43 ++ ereuse_devicehub/__init__.py | 2 +- ereuse_devicehub/client.py | 5 + ereuse_devicehub/config.py | 7 +- ereuse_devicehub/dummy/dummy.py | 11 +- .../files/computer-monitor.snapshot.yaml | 8 +- .../files/dell-optiplexgx520.snapshot.11.yaml | 248 +++++----- .../dummy/files/hp1.snapshot.11.yaml | 228 ++++----- .../dummy/files/hp2.snapshot.11.yaml | 304 ++++++------ .../files/lenovo-3493BAG.snapshot.11.yaml | 228 ++++----- .../dummy/files/nec.snapshot.11.yaml | 250 +++++----- .../files/real-eee-1001pxd.snapshot.11.yaml | 260 +++++----- .../files/real-hp-quad-core.snapshot.11.yaml | 188 ++++---- .../dummy/files/real-hp.snapshot.11.yaml | 266 +++++------ .../dummy/files/real-toshiba.snapshot.11.yaml | 226 ++++----- .../dummy/files/smart.snapshot.11.yaml | 282 +++++------ .../files/workbench-server-1.snapshot.yaml | 180 +++---- ereuse_devicehub/marshmallow.py | 6 +- ereuse_devicehub/resources/agent/__init__.py | 68 +++ ereuse_devicehub/resources/agent/models.py | 131 ++++++ ereuse_devicehub/resources/agent/models.pyi | 79 ++++ ereuse_devicehub/resources/agent/schemas.py | 40 ++ ereuse_devicehub/resources/device/models.py | 16 +- ereuse_devicehub/resources/device/schemas.py | 11 +- ereuse_devicehub/resources/enums.py | 12 + ereuse_devicehub/resources/event/__init__.py | 66 ++- ereuse_devicehub/resources/event/models.py | 244 ++++++++-- ereuse_devicehub/resources/event/models.pyi | 159 +++++-- ereuse_devicehub/resources/event/schemas.py | 115 ++++- ereuse_devicehub/resources/event/views.py | 14 +- ereuse_devicehub/resources/models.pyi | 7 - ereuse_devicehub/resources/tag/model.py | 2 +- ereuse_devicehub/resources/tag/view.py | 2 +- ereuse_devicehub/resources/user/__init__.py | 35 +- ereuse_devicehub/resources/user/models.py | 38 +- ereuse_devicehub/resources/user/models.pyi | 27 ++ ereuse_devicehub/resources/user/schemas.py | 3 + setup.py | 6 +- tests/conftest.py | 9 +- .../1-device-with-components.snapshot.yaml | 28 +- ...ice-with-components-of-first.snapshot.yaml | 20 +- ...-and-adding-processor-from-2.snapshot.yaml | 22 +- ...ssor.snapshot-and-adding-graphic-card.yaml | 20 +- tests/files/basic.snapshot.yaml | 44 +- tests/files/computer-monitor.snapshot.yaml | 8 +- tests/files/erase-sectors-2-hdd.snapshot.yaml | 260 +++++----- tests/files/erase-sectors.snapshot.yaml | 52 +- tests/files/pc-components.db.yaml | 16 +- tests/files/real-custom.snapshot.11.yaml | 202 ++++---- tests/files/real-eee-1001pxd.snapshot.11.yaml | 260 +++++----- .../files/real-hp-quad-core.snapshot.11.yaml | 188 ++++---- tests/files/real-hp.snapshot.11.yaml | 266 +++++------ tests/files/real-toshiba.snapshot.11.yaml | 226 ++++----- tests/files/workbench-10.snapshot.yaml | 160 +++---- tests/files/workbench-server-1.snapshot.yaml | 126 ++--- tests/files/workbench-server-3.erase.yaml | 8 +- tests/test_agent.py | 129 +++++ tests/test_basic.py | 2 +- tests/test_device.py | 2 + tests/test_event.py | 116 ++++- tests/test_organization.py | 18 - tests/test_price.py | 6 - tests/test_snapshot.py | 3 +- tests/test_tag.py | 2 +- tests/test_user.py | 48 +- tests/test_workbench.py | 2 +- 75 files changed, 4016 insertions(+), 2832 deletions(-) rename docs/{events.puml => actions.puml} (83%) create mode 100644 docs/actions.rst create mode 100644 docs/agents.puml create mode 100644 docs/agents.rst delete mode 100644 docs/events.rst create mode 100644 docs/states.puml create mode 100644 ereuse_devicehub/resources/agent/__init__.py create mode 100644 ereuse_devicehub/resources/agent/models.py create mode 100644 ereuse_devicehub/resources/agent/models.pyi create mode 100644 ereuse_devicehub/resources/agent/schemas.py create mode 100644 ereuse_devicehub/resources/user/models.pyi create mode 100644 tests/test_agent.py delete mode 100644 tests/test_organization.py delete mode 100644 tests/test_price.py diff --git a/docs/events.puml b/docs/actions.puml similarity index 83% rename from docs/events.puml rename to docs/actions.puml index 73ec91b2..13ea723b 100644 --- a/docs/events.puml +++ b/docs/actions.puml @@ -1,4 +1,8 @@ @startuml +left to right direction +skinparam nodesep 20 +skinparam ranksep 1 + abstract class Rate abstract class Event abstract class Test @@ -38,13 +42,13 @@ EventWithOneDevice <|--- EraseBasic EraseBasic <|- EraseSectors Step <|-- StepZero -Step <|-- StepRandom -Snapshot "1" -- "1" SnapshotRequest +Step <|-- "Step\nRandom" +Snapshot "1" -- "1" "Snapshot\nRequest" Event "*" -> "0..1" Snapshot : InSnapshot > Event "*" -> "0..1" Component : affectedComponents > -Device "1" *-- "*" EventWithOneDevice : EventOn < -Device "1..*" *-- "1" EventWithMultipleDevices : EventOn < -EraseBasic "1" *-- "1..*" Step +Device "1" *- "*" EventWithOneDevice : EventOn < +Device "1..*" *- "1" EventWithMultipleDevices : EventOn < +EraseBasic "1" *- "1..*" Step PhotoboxRate <|-- PhotoboxSystemRate PhotoboxRate <|-- PhotoboxPersonRate @@ -84,18 +88,14 @@ Plan <|-- CancelReservation package Agents { - abstract class User + abstract class User <> abstract class Agent + Event "*" -> "1" User : Author > Event "*" - "0..1" Agent : agent > + Trade "*" - "0..1" Agent : to > - Agent <|-- User - - User <|-- Person - User <|-- System - Agent <|-- Organization - User "*" -o "0..1" Organization : WorksIn > - User "*" -o "0..1" Organization : activeOrganization > + User - Agent } -@enduml \ No newline at end of file +@enduml diff --git a/docs/actions.rst b/docs/actions.rst new file mode 100644 index 00000000..639835ce --- /dev/null +++ b/docs/actions.rst @@ -0,0 +1,443 @@ +Actions and states +################## + +Actions are events performed to devices, changing their **state**. +Actions can have attributes defining +**where** it happened, **who** performed them, **when**, etc. +Actions are stored in a log for each device. An exemplifying action +can be ``Repair``, which dictates that a device has been repaired, +after this action, the device is in the ``repaired`` state. + +Actions and states affect devices in different ways or **dimensions**. +For example, ``Repair`` affects the **physical** dimension of a device, +and ``Sell`` the **political** dimension of a device. A device +can be in several states at the same time, one per dimension; ie. a +device can be ``repaired`` (physical) and ``reserved`` (political), +but not ``repaired`` and ``disposed`` at the same time. + +Devicehub actions inherit from `schema actions +`_, are written in Pascal case and using +a verb in infinitive. Some verbs represent the willingness or +assignment to perform an action; ``ToRepair`` states that the device +is going to be / must be repaired, whereas ``Repair`` states +that the reparation happened. The former actions have the preposition +*To* prefixing the verb. + +In the following section we define the actions and states. +To see how to perform actions to the Devicehub API head +to the `Swagger docs +`_. + +.. toctree:: + :maxdepth: 4 + + actions + +.. uml:: actions.puml + + +Physical Actions +**************** +The following actions describe and react on the physical condition +of the devices. + +ToPrepare, Prepare +================== +Work has been performed to the device to a defined point of +acceptance. Users using this event have to agree what is this point +of acceptance; for some is when the device just works, for others +when some testing has been performed. + +**Prepare** dictates that the device has been prepared, whereas +**ToPrepare** that the device has been selected to be prepared. + +Usually **ToPrepare** is the next event done after registering the +device. + +ToRepair, Repair +================ +ToRepair is the act of selecting a device to be repaired, and +Repair the act of performing the actual reparations. If a repair +without an error is performed, it represents that the reparation +has been successful. + +ReadyToUse +========== +The device is ready to be used. This involves greater preparation +from the ``Prepare`` event, and users should only use a device +after this event is performed. + +Users usually require devices with this event before shipping them +to costumers. + +Live +==== +A keep-alive from a device connected to the Internet with information +about its state (in the form of a ``Snapshot`` event) and usage +statistics. + +DisposeWaste, Recover +===================== +``RecyclingCenter`` users have two extra special events: + - ``DisposeWaste``: The device has been disposed in an unspecified + manner. + - ``Recover``: The device has been scrapped and its materials have + been recovered under a new product. + +See `ToDisposeProduct, DisposeProduct`_. + +Association actions +******************* +Actions that change the associations users have with devices; +ie. the **owners**, **usufructuarees**, **reservees**, +and **physical possessors**. + +There are three sub-dimensions: **trade**, **transfer**, +and **organize** actions. + +.. uml:: association-events.puml + +Trade actions +============= +Trade actions log the political exchange of devices between users, +stating **owner** xor **usufructuaree**. Every time a trade event +is performed, the old user looses its political possession in favor +of another one. + +Sell +---- +The act of taking money from a buyer in exchange of a device. + +Donate +------ +The act of giving devices without compensation. + +Rent +---- +The act of giving money in return for temporary use, but not +ownership, of a device. + +CancelTrade +----------- +The act of cancelling a `Sell`_, `Donate`_ or `Rent`_. + +ToDisposeProduct, DisposeProduct +------------------------- +``ToDispose`` and ``DisposeProduct`` manage the process of getting +rid of devices by giving (selling, donating) to another organization +like a waste manager. + +``ToDispose`` marks a device for being disposed, and +``DisposeProduct`` dictates that the device has been disposed. + +See `DisposeWaste, Recover`_ events for disposing without trading +the device. + +.. note:: For usability purposes, users might not directly perform + ``Dispose``, but this could automatically be done when + performing ``ToDispose`` + ``Receive`` to a ``RecyclingCenter``. + +Transfer actions +================ +The act of transferring/moving devices from one place to another. + +Receive +------- +The act of physically taking delivery of a device. The receiver +confirms that the devices have arrived, and thus, they +**physically possess** them. Note that +there can only be one **physical possessor** per device, and +``Receive`` changes it. + +The receiver can optionally take a role in the reception, giving +it meaning; an user that takes the ``FinalUser`` role in the +reception express that it will use the device, whereas a role +``Transporter`` is used by intermediaries in shipping. + +.. todo:: how do we ensure users specify type of reception? + +Organize actions +================ +The act of manipulating/administering/supervising/controlling one or +more devices. + +Reserve, CancelReservation +-------------------------- +The act of reserving devices and cancelling them. + +After this event is performed, the user is the **reservee** of the +devices. There can only be one non-cancelled reservation for +a device, and a reservation can only have one reservee. + +Assign, Accept, Reject +---------------------- +``Assign`` allocates devices to an user. The purpose or meaning +of the association is defined by the users. + +``Accept`` and ``Reject`` allow users to accept and reject the +assignments. + +.. todo:: shall we add ``Deassign`` or make ``Assign`` + always define all active users? + +.. todo:: Assign won't be developed until further notice. + + +Internal state actions +********************** +Actions providing metadata about devices that don't usually change +their state. + +Snapshot +======== +The Snapshot sets the physical information of the device (S/N, model...) +and updates it with erasures, benchmarks, ratings, and tests; updates the +composition of its components (adding / removing them), and links tags +to the device. + +When receiving a Snapshot, the DeviceHub creates, adds and removes +components to match the Snapshot. For example, if a Snapshot of a computer +contains a new component, the system searches for the component in its +database and, if not found, its creates it; finally linking it to the +computer. + +A Snapshot is used with Remove to represent changes in components for +a device: + +1. ``Snapshot`` creates a device if it does not exist, and the same + for its components. This is all done in one ``Snapshot``. +2. If the device exists, it updates its component composition by + *adding* and *removing* them. If, + for example, this new Snasphot doesn't have a component, it means that + this component is not present anymore in the device, thus removing it + from it. Then we have that: + + - Components that are added to the device: snapshot2.components - + snapshot1.components + - Components that are removed to the device: snapshot1.components - + snapshot2.components + + When adding a component, there may be the case this component existed + before and it was inside another device. In such case, DeviceHub will + perform ``Remove`` on the old parent. + +Snapshots from Workbench +------------------------ +When processing a device from the Workbench, this one performs a Snapshot +and then performs more events (like testings, benchmarking...). + +There are two ways of sending this information. In an async way, +this is, submitting events as soon as Workbench performs then, or +submitting only one Snapshot event with all the other events embedded. + +Asynced +^^^^^^^ +The use case, which is represented in the ``test_workbench_phases``, +is as follows: + +1. In **T1**, WorkbenchServer (as the middleware from Workbench and + Devicehub) submits: + + - A ``Snapshot`` event with the required information to **synchronize** + and **rate** the device. This is: + + - Identification information about the device and components + (S/N, model, physical characteristics...) + - ``Tags`` in a ``tags`` property in the ``device``. + - ``Rate`` in an ``events`` property in the ``device``. + - ``Benchmarks`` in an ``events`` property in each ``component`` + or ``device``. + - ``TestDataStorage`` as in ``Benchmarks``. + - An ordered set of **expected events**, defining which are the next + events that Workbench will perform to the device in ideal + conditions (device doesn't fail, no Internet drop...). + + Devicehub **syncs** the device with the database and perform the + ``Benchmark``, the ``TestDataStorage``, and finally the ``Rate``. + This leaves the Snapshot **open** to wait for the next events + to come. +2. Assuming that we expect all events, in **T2**, WorkbenchServer + submits a ``StressTest`` with a ``snapshot`` field containing the + ID of the Snapshot in 1, and Devicehub links the event with such + ``Snapshot``. +3. In **T3**, WorkbenchServer submits the ``Erase`` with the ``Snapshot`` + and ``component`` IDs from 1, linking it to them. It repeats + this for all the erased data storage devices; **T3+Tn** being + *n* the erased data storage devices. +4. WorkbenchServer does like in 3. but for the event ``Install``, + finishing in **T3+Tn+Tx**, being *x* the number of data storage + devices with an OS installed into. +5. In **T3+Tn+Tx**, when all *expected events* have been performed, + Devicehub **closes** the ``Snapshot`` from 1. + +Synced +^^^^^^ +Optionally, Devicehub understands receiving a ``Snapshot`` with all +the events in an ``events`` property inside each affected ``component`` +or ``device``. + +Add, Remove +=========== +The act of adding and removing components of and from a device. + +These are usually used internally from `Snapshot`_, or manually, for +example, when removing a component (like a ``DataStorage`` unit) from +a broken computer. + +EraseBasic, EraseSectors +======================== +An erasure attempt to a ``DataStorage``. The event contains +information about success and nature of the erasure. + +``EraseBasic`` is a fast non-secured way of erasing data storage, and +``EraseSectors`` is a slower secured, sector-by-sector, erasure +method. + +Users can generate erasure certificates from successful erasures. + +Erasures are an accumulation of **erasure steps**, that are performed +as separate actions, called ``StepRandom``, for an erasure step +that has overwritten data with random bits, and ``StepZero``, +for an erasure step that has overwritten data with zeros. + +Install +======= +The action of install an Operative System to a data storage unit. + +Test +==== +The act of testing the physical condition of a device and its +components. + +TestDataStorage +--------------- +The act of testing the data storage. + +Testing is done using the `S.M.A.R.T self test +`_. Note +that not all data storage units, specially some new PCIe ones, do not +support SMART testing. + +The test takes to other SMART values indicators of the overall health +of the data storage. + +StressTest +---------- +The act of stressing (putting to the maximum capacity) +a device for an amount of minutes. If the device is not in great +condition won't probably survive such test. + +Benchmark +========= +The act of gauging the performance of a device. + +BenchmarkDataStorage +-------------------- +Benchmarks the data storage unit reading and writing speeds. + +BenchmarkWithRate +----------------- +The act of benchmarking a device with a single rate. + +BenchmarkProcessor +------------------ +Benchmarks a processor by executing `BogoMips +`_. Note that this is not +a reliable way of rating processors and we keep it for compatibility +purposes. + +BenchmarkProcessorSysbench +-------------------------- +Benchmarks a processor by using the processor benchmarking utility of +`sysbench `_. + + +Rate +==== +Devicehub generates an rating for a device taking into consideration the +visual, functional, and performance. + +A Workflow is as follows: + +1. An agent generates feedback from the device in the form of benchmark, + visual, and functional information; which is filled in a ``Rate`` + event. This is done through a **software**, defining the type + of ``Rate`` event. At the moment we have two rates: ``WorkbenchRate`` + and ``PhotoboxRate``. +2. Devicehub gathers this information and computes a score that updates + the ``Rate`` event. +3. Devicehub aggregates different rates and computes a final score for + the device by performing a new ``AggregateRating`` event. + +There are three **types** of ``Rate``: ``WorkbenchRate``, +``AppRate``, and ``PhotoboxRate``. ``WorkbenchRate`` can have different +**software** algorithms, and each software algorithm can have several +**versions**. So, we have 3 dimensions for ``WorkbenchRate``: +type, software, version. + +Devicehub generates a rate event for each software and version. So, +if an agent fulfills a ``WorkbenchRate`` and there are 2 software +algorithms and each has two versions, Devicehub will generate 4 rates. +Devicehub understands that only one software and version are the +**oficial** (set in the settings of each inventory), +and it will generate an ``AggregateRating`` for only the official +versions. At the same time, ``Price`` only computes the price of +the **oficial** version. + +The technical Workflow in Devicehub is as follows: + +1. In **T1**, the user performs a ``Snapshot`` by processing the device + through the Workbench. From the benchmarks and the visual and + functional ratings the user does in the device, the system generates + many ``WorkbenchRate`` (as many as software and versions defined). + With only this information, the system generates an ``AggregateRating``, + which is the event that the user will see in the web. +2. In **T2**, the user takes pictures from the device through the + Photobox, and DeviceHub crates an ``ImageSet`` with multiple + ``Image`` with information from the photobox. +3. In **T3**, an agent (user or AI) rates the pictures, creating a + ``PhotoboxRate`` **for each** picture. When Devicehub receives the + first ``PhotoboxRate`` it creates an ``AggregateRating`` linked + to such ``PhotoboxRate``. So, the agent will perform as many + ``PhotoboxRate`` as pictures are in the ``ImageSet``, and Devicehub + will link each ``PhotoboxRate`` to the same ``AggregateRating``. + This will end in **T3+Tn**, being *n* the number of photos to rate. +4. In **T3+Tn**, after the last photo is rated, Devicehub will generate + a new rate for the device: it takes the ``AggregateRating`` from 3. + and computes a rate from all the linked ``PhotoboxRate`` plus the + last available ``WorkbenchRate`` for that device. + +If the agent in 3. is an user, Devicehub creates ``PhotoboxUserRate`` +and if it is an AI it creates ``PhotoboxAIRate``. + +The same ``ImageSet`` can be rated multiple times, generating a new +``AggregateRating`` each time. + +Price +===== +Price states a selling price for the device, but not necessariliy the +final price this was sold (which is set in the Sell event). + +Devicehub automatically computes a price from ``AggregateRating`` +events. As in a **Rate**, price can have **software** and **version**, +and there is an **official** price that is used to automatically +compute the price from an ``AggregateRating``. Only the official price +is computed from an ``AggregateRating``. + +Migrate +======= +Moves the devices to a new database/inventory. Devices cannot be +modified anymore at the previous database. + +Donation +======== +.. todo:: nextcloud/eReuse/99. Tasks/224. Definir datos necesarios + configuraciĆ³n licencia + + +States +****** +.. todo:: work on september. + +.. uml:: states.puml + diff --git a/docs/agents.puml b/docs/agents.puml new file mode 100644 index 00000000..543c1bde --- /dev/null +++ b/docs/agents.puml @@ -0,0 +1,25 @@ +@startuml + +abstract class User <> +abstract class Individual +abstract class Agent + +Event "*" --> "1" User : Author > +Event "*" -- "0..1" Agent : agent > +Trade "*" -- "0..1" Agent : to > + +User "0..1" - "0..1" Agent : user < + +Agent <|-- Individual +Individual <|-- Person +Individual <|-- System +Agent <|-- Organization +Individual "*" -o "0..1" Organization +(Individual, Organization) .. Membership +class Membership { + member_id +} + + +Individual "*" -o "0..1" Organization : activeOrg > +@enduml diff --git a/docs/agents.rst b/docs/agents.rst new file mode 100644 index 00000000..bba13beb --- /dev/null +++ b/docs/agents.rst @@ -0,0 +1,4 @@ +Agents +###### + +.. uml:: agents.puml diff --git a/docs/association-events.puml b/docs/association-events.puml index 34ef9f69..3a909538 100644 --- a/docs/association-events.puml +++ b/docs/association-events.puml @@ -1,72 +1,25 @@ @startuml -ChangeAssociation <|-- Organize -ChangeAssociation <|-- Transfer -Organize <|-- Plan -Organize <|-- Allocate -Allocate <|-- Accept -Allocate <|-- Reject -Allocate <|-- Assign -Allocate <|-- Authorize -Plan <|-- Reserve -Plan <|-- Cancel +skinparam nodesep 10 +skinparam ranksep 30 + +abstract class Trade { + to: Agent +} +abstract class Transfer +abstract class Organize + + +"Associate" <|-- Organize +"Associate" <|-- Transfer +Organize <|-- Reserve +Organize <|--- "Cancel\nReservation" Transfer <|-- Receive -ChangeAssociation <|-- Trade +"Associate" <|-- Trade Trade <|-- Sell Trade <|-- Donate Trade <|-- Pay Trade <|-- Rent -Trade <|-- DisposeProduct - -class ChangeAssociation { - agent: who did it -} - -class Receive { - sender - recipient -} - -class Reserve { - reservee -} - -class Cancel { - reservee -} - -class Trade { - -} - -class Allocate { - purpose -} - -class Sell { - buyer -} - -class Donate { - recipient -} - -class Pay { - purpose - recipient -} - -class Rent { - recipient -} +Trade <|-- "Dispose\nProduct" -Association <|-- PhysicalPossessor -Association <|-- TradeAssociation -TradeAssociation <|-- Usufructuary -TradeAssociation <|-- Ownership - -Sell - TradeAssociation -Donate - TradeAssociation -Rent -- Usufructuary : Sure? -Receive - PhysicalPossessor -@enduml \ No newline at end of file +@enduml diff --git a/docs/conf.py b/docs/conf.py index a1aec88c..84540ff3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -167,7 +167,7 @@ intersphinx_mapping = {'https://docs.python.org/': None} todo_include_todos = True # Plantuml -plantuml_output_format = 'svg' +plantuml_output_format = 'svg_img' # favicon html_favicon = 'img/favicon.ico' diff --git a/docs/etag.rst b/docs/etag.rst index fe7a126a..61039284 100644 --- a/docs/etag.rst +++ b/docs/etag.rst @@ -15,7 +15,6 @@ Actors - Photochromic tag manufacturer. - User: organization that uses the tags. - Requirements ************ diff --git a/docs/events.rst b/docs/events.rst deleted file mode 100644 index d021bb91..00000000 --- a/docs/events.rst +++ /dev/null @@ -1,197 +0,0 @@ -Events -###### - -.. toctree:: -:maxdepth: 4 - - event-diagram - - -Rate -**** -Devicehub generates an rating for a device taking into consideration the -visual, functional, and performance. - -.. todo:: add performance as a result of component fusion + general -tests in `here `_. - -A Workflow is as follows: - -1. An agent generates feedback from the device in the form of benchmark, - visual, and functional information; which is filled in a ``Rate`` - event. This is done through a **software**, defining the type - of ``Rate`` event. At the moment we have two rates: ``WorkbenchRate`` - and ``PhotoboxRate``. -2. Devicehub gathers this information and computes a score that updates - the ``Rate`` event. -3. Devicehub aggregates different rates and computes a final score for - the device by performing a new ``AggregateRating`` event. - -There are three **types** of ``Rate``: ``WorkbenchRate``, -``AppRate``, and ``PhotoboxRate``. ``WorkbenchRate`` can have different -**software** algorithms, and each software algorithm can have several -**versions**. So, we have 3 dimensions for ``WorkbenchRate``: -type, software, version. - -Devicehub generates a rate event for each software and version. So, -if an agent fulfills a ``WorkbenchRate`` and there are 2 software -algorithms and each has two versions, Devicehub will generate 4 rates. -Devicehub understands that only one software and version are the -**oficial** (set in the settings of each inventory), -and it will generate an ``AggregateRating`` for only the official -versions. At the same time, ``Price`` only computes the price of -the **oficial** version. - -The technical Workflow in Devicehub is as follows: - -1. In **T1**, the user performs a ``Snapshot`` by processing the device - through the Workbench. From the benchmarks and the visual and - functional ratings the user does in the device, the system generates - many ``WorkbenchRate`` (as many as software and versions defined). - With only this information, the system generates an ``AggregateRating``, - which is the event that the user will see in the web. -2. In **T2**, the user takes pictures from the device through the - Photobox, and DeviceHub crates an ``ImageSet`` with multiple - ``Image`` with information from the photobox. -3. In **T3**, an agent (user or AI) rates the pictures, creating a - ``PhotoboxRate`` **for each** picture. When Devicehub receives the - first ``PhotoboxRate`` it creates an ``AggregateRating`` linked - to such ``PhotoboxRate``. So, the agent will perform as many - ``PhotoboxRate`` as pictures are in the ``ImageSet``, and Devicehub - will link each ``PhotoboxRate`` to the same ``AggregateRating``. - This will end in **T3+Tn**, being *n* the number of photos to rate. -4. In **T3+Tn**, after the last photo is rated, Devicehub will generate - a new rate for the device: it takes the ``AggregateRating`` from 3. - and computes a rate from all the linked ``PhotoboxRate`` plus the - last available ``WorkbenchRate`` for that device. - -If the agent in 3. is an user, Devicehub creates ``PhotoboxUserRate`` -and if it is an AI it creates ``PhotoboxAIRate``. - -The same ``ImageSet`` can be rated multiple times, generating a new -``AggregateRating`` each time. - -.. todo:: which info does photobox provide for each picture? - -Price -***** -Price states a selling price for the device, but not necessariliy the -final price this was sold (which is set in the Sell event). - -Devicehub automatically computes a price from ``AggregateRating`` -events. As in a **Rate**, price can have **software** and **version**, -and there is an **official** price that is used to automatically -compute the price from an ``AggregateRating``. Only the official price -is computed from an ``AggregateRating``. - -Snapshot -******** -The Snapshot sets the physical information of the device (S/N, model...) -and updates it with erasures, benchmarks, ratings, and tests; updates the -composition of its components (adding / removing them), and links tags -to the device. - -When receiving a Snapshot, the DeviceHub creates, adds and removes -components to match the Snapshot. For example, if a Snapshot of a computer -contains a new component, the system searches for the component in its -database and, if not found, its creates it; finally linking it to the -computer. - -A Snapshot is used with Remove to represent changes in components for -a device: - -1. ``Snapshot`` creates a device if it does not exist, and the same - for its components. This is all done in one ``Snapshot``. -2. If the device exists, it updates its component composition by - *adding* and *removing* them. If, - for example, this new Snasphot doesn't have a component, it means that - this component is not present anymore in the device, thus removing it - from it. Then we have that: - - - Components that are added to the device: snapshot2.components - - snapshot1.components - - Components that are removed to the device: snapshot1.components - - snapshot2.components - - When adding a component, there may be the case this component existed - before and it was inside another device. In such case, DeviceHub will - perform ``Remove`` on the old parent. - -Snapshots from Workbench -======================== -When processing a device from the Workbench, this one performs a Snapshot -and then performs more events (like testings, benchmarking...). - -There are two ways of sending this information. In an async way, -this is, submitting events as soon as Workbench performs then, or -submitting only one Snapshot event with all the other events embedded. - -Asynced -------- -The use case, which is represented in the ``test_workbench_phases``, -is as follows: - -1. In **T1**, WorkbenchServer (as the middleware from Workbench and - Devicehub) submits: - - - A ``Snapshot`` event with the required information to **synchronize** - and **rate** the device. This is: - - - Identification information about the device and components - (S/N, model, physical characteristics...) - - ``Tags`` in a ``tags`` property in the ``device``. - - ``Rate`` in an ``events`` property in the ``device``. - - ``Benchmarks`` in an ``events`` property in each ``component`` - or ``device``. - - ``TestDataStorage`` as in ``Benchmarks``. - - An ordered set of **expected events**, defining which are the next - events that Workbench will perform to the device in ideal - conditions (device doesn't fail, no Internet drop...). - - Devicehub **syncs** the device with the database and perform the - ``Benchmark``, the ``TestDataStorage``, and finally the ``Rate``. - This leaves the Snapshot **open** to wait for the next events - to come. -2. Assuming that we expect all events, in **T2**, WorkbenchServer - submits a ``StressTest`` with a ``snapshot`` field containing the - ID of the Snapshot in 1, and Devicehub links the event with such - ``Snapshot``. -3. In **T3**, WorkbenchServer submits the ``Erase`` with the ``Snapshot`` - and ``component`` IDs from 1, linking it to them. It repeats - this for all the erased data storage devices; **T3+Tn** being - *n* the erased data storage devices. -4. WorkbenchServer does like in 3. but for the event ``Install``, - finishing in **T3+Tn+Tx**, being *x* the number of data storage - devices with an OS installed into. -5. In **T3+Tn+Tx**, when all *expected events* have been performed, - Devicehub **closes** the ``Snapshot`` from 1. - -Synced ------- -Optionally, Devicehub understands receiving a ``Snapshot`` with all -the events in an ``events`` property inside each affected ``component`` -or ``device``. - -ToDispose and DisposeProduct -**************************** -There are four events for getting rid of devices: - -- ``ToDispose``: The device is marked to be disposed. -- ``DisposeProduct``: The device has been disposed. This is a ``Trade`` - event, which means that you can optionally ``DisposeProduct`` - to someone. -- ``RecyclingCenter`` have two extra special events: - - ``DisposeWaste``: The device has been disposed in an unspecified - manner. - - ``Recover``: The device has been scrapped and its materials have - been recovered under a new product. - -.. note:: For usability purposes, users might not directly perform -``Dispose``, but this could automatically be done when - performing ``ToDispose`` + ``Receive`` to a ``RecyclingCenter``. - -.. todo:: Ensure that ``Dispose`` is a ``Trade`` event. An Org could -``Sell`` or ``Donate`` a device with the objective of disposing them. - Is ``Dispose`` ok, or do we want to keep that extra ``Sell`` or - ``Donate`` event? Could dispose be a synonym of any of those? diff --git a/docs/index.rst b/docs/index.rst index d3013aae..71763de2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,11 +10,12 @@ This is the documentation and API of the `eReuse.org DeviceHub .. toctree:: - :maxdepth: 4 + :maxdepth: 2 - events - tags + actions + agents inventory + tags etag * :ref:`genindex` diff --git a/docs/states.puml b/docs/states.puml new file mode 100644 index 00000000..3582b829 --- /dev/null +++ b/docs/states.puml @@ -0,0 +1,43 @@ +@startuml +skinparam nodesep 10 +skinparam ranksep 1 + + +[*] -> Registered + +state Attributes { + + state Broken : cannot turn on + state Owners + state Usufructuarees + state Reservees + state "Physical\nPossessor" +} + +state Physical { + Registered --> Preparing : ToPrepare + Registered --> ToBeRepaired : ToRepair + ToBeRepaired --> Repaired : Repair + Repaired -> Preparing : ToPrepare + Preparing --> Prepared : Prepare + Prepared --> ReadyToBeUsed : ReadyToUse + ReadyToBeUsed --> InUse : Live + InUse -> InUse : Live + state DisposeWaste + state Recover + +} + +state Trading { + Registered --> Reserved : Reserve + Registered --> Sold : Sell + Reserved -> Sold : Sell + Reserved --> Cancelled : Cancel + Sold --> Cancelled : Cancel + Sold --> Payed : Pay + Registered --> ToBeDisposed + ToBeDisposed --> Disposed : DisposeProduct +} + + +@enduml diff --git a/ereuse_devicehub/__init__.py b/ereuse_devicehub/__init__.py index 6a37c560..4755c9a1 100644 --- a/ereuse_devicehub/__init__.py +++ b/ereuse_devicehub/__init__.py @@ -1,4 +1,4 @@ from distutils.version import StrictVersion -__version__ = '0.2.0a11' +__version__ = '0.2.0a12' version = StrictVersion(__version__) diff --git a/ereuse_devicehub/client.py b/ereuse_devicehub/client.py index dd5d9c2f..420e6388 100644 --- a/ereuse_devicehub/client.py +++ b/ereuse_devicehub/client.py @@ -109,3 +109,8 @@ class UserClient(Client): **kw) -> Tuple[Union[Dict[str, object], str], Response]: return super().open(uri, res, status, query, accept, content_type, item, headers, self.user['token'] if self.user else token, **kw) + + def login(self): + response = super().login(self.email, self.password) + self.user = response[0] + return response diff --git a/ereuse_devicehub/config.py b/ereuse_devicehub/config.py index f82e83f4..4aa65f45 100644 --- a/ereuse_devicehub/config.py +++ b/ereuse_devicehub/config.py @@ -2,11 +2,11 @@ from distutils.version import StrictVersion from itertools import chain from typing import Set -from ereuse_devicehub.resources import device, event, inventory, tag, user +from ereuse_devicehub.resources import agent, device, event, inventory, tag, user from ereuse_devicehub.resources.enums import PriceSoftware, RatingSoftware from teal.auth import TokenAuth from teal.config import Config -from teal.currency import Currency +from teal.enums import Currency from teal.utils import import_resource @@ -15,7 +15,8 @@ class DevicehubConfig(Config): import_resource(event), import_resource(user), import_resource(tag), - import_resource(inventory))) + import_resource(inventory), + import_resource(agent))) PASSWORD_SCHEMES = {'pbkdf2_sha256'} # type: Set[str] SQLALCHEMY_DATABASE_URI = 'postgresql://dhub:ereuse@localhost/devicehub' # type: str SCHEMA = 'dhub' diff --git a/ereuse_devicehub/dummy/dummy.py b/ereuse_devicehub/dummy/dummy.py index a1307410..4c0d7ba6 100644 --- a/ereuse_devicehub/dummy/dummy.py +++ b/ereuse_devicehub/dummy/dummy.py @@ -3,8 +3,10 @@ from pathlib import Path import click import click_spinner import yaml + from ereuse_devicehub.client import UserClient from ereuse_devicehub.db import db +from ereuse_devicehub.resources.agent.models import Person from ereuse_devicehub.resources.event.models import Snapshot from ereuse_devicehub.resources.inventory import Inventory from ereuse_devicehub.resources.tag.model import Tag @@ -49,11 +51,10 @@ class Dummy: def user_client(self, email: str, password: str): user = User(email=email, password=password) + user.individuals.add(Person(name='Timmy')) db.session.add(user) db.session.commit() - client = UserClient(application=self.app, - response_wrapper=self.app.response_class, - email=user.email, - password=password) - client.user, _ = client.login(client.email, client.password) + client = UserClient(self.app, user.email, password, + response_wrapper=self.app.response_class) + client.login() return client diff --git a/ereuse_devicehub/dummy/files/computer-monitor.snapshot.yaml b/ereuse_devicehub/dummy/files/computer-monitor.snapshot.yaml index aefc5817..c4988cf8 100644 --- a/ereuse_devicehub/dummy/files/computer-monitor.snapshot.yaml +++ b/ereuse_devicehub/dummy/files/computer-monitor.snapshot.yaml @@ -11,7 +11,7 @@ device: resolutionHeight: 1080 size: 21.5 events: - - type: AppRate - appearanceRange: A - functionalityRange: C - labelling: False + - type: AppRate + appearanceRange: A + functionalityRange: C + labelling: False diff --git a/ereuse_devicehub/dummy/files/dell-optiplexgx520.snapshot.11.yaml b/ereuse_devicehub/dummy/files/dell-optiplexgx520.snapshot.11.yaml index d732e595..2769489e 100644 --- a/ereuse_devicehub/dummy/files/dell-optiplexgx520.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/dell-optiplexgx520.snapshot.11.yaml @@ -3,16 +3,16 @@ "chassis": "Tower", "serialNumber": "6G0772J", "events": [ - { - "rate": 2.1341, - "type": "BenchmarkRamSysbench", - "elapsed": 2 - }, - { - "error": false, - "type": "StressTest", - "elapsed": 60 - } + { + "rate": 2.1341, + "type": "BenchmarkRamSysbench", + "elapsed": 2 + }, + { + "error": false, + "type": "StressTest", + "elapsed": 60 + } ], "type": "Desktop", "manufacturer": "Dell Inc.", @@ -21,127 +21,127 @@ "uuid": "bb848528-d708-4bb6-8a91-3d139d76b20f", "software": "Workbench", "components": [ + { + "serialNumber": null, + "address": 64, + "events": [ { - "serialNumber": null, - "address": 64, - "events": [ - { - "rate": 11970.92, - "type": "BenchmarkProcessor", - "elapsed": 0 - }, - { - "rate": 100.4242, - "type": "BenchmarkProcessorSysbench", - "elapsed": 101 - } - ], - "type": "Processor", - "manufacturer": "Intel Corp.", - "speed": 3.0, - "model": "Intel Pentium 4 CPU 3.00GHz" + "rate": 11970.92, + "type": "BenchmarkProcessor", + "elapsed": 0 }, { - "serialNumber": null, - "events": [], - "type": "SoundCard", - "manufacturer": "Intel Corporation", - "model": "82801G AC'97 Audio Controller" - }, - { - "size": 512, - "serialNumber": "4A7012A1", - "events": [], - "speed": 533.0, - "type": "RamModule", - "format": "DIMM", - "manufacturer": "Nanya Technology", - "interface": "DDR", - "model": "NT512T64U88A0BY-37" - }, - { - "size": 512, - "serialNumber": null, - "events": [], - "speed": 533.0, - "type": "RamModule", - "format": "DIMM", - "manufacturer": null, - "interface": "DDR", - "model": null - }, - { - "serialNumber": "00:13:72:78:53:12", - "events": [], - "type": "NetworkAdapter", - "manufacturer": "Broadcom Limited", - "speed": 1000, - "model": "NetXtreme BCM5751 Gigabit Ethernet PCI Express", - "wireless": false - }, - { - "serialNumber": "5LR30DTZ", - "events": [ - { - "steps": [ - { - "error": false, - "type": "StepRandom", - "startTime": "2018-07-11T11:20:01.005336", - "endTime": "2018-07-11T11:42:12.971177" - } - ], - "zeros": false, - "error": false, - "type": "EraseBasic", - "endTime": "2018-07-11T11:42:12.975358", - "startTime": "2018-07-11T11:20:01.004892" - }, - { - "writeSpeed": 26.6, - "type": "BenchmarkDataStorage", - "readSpeed": 73.9, - "elapsed": 14 - }, - { - "length": "Short", - "error": true, - "type": "TestDataStorage", - "status": "Unspecified Error. Self-test not started.", - "elapsed": 0 - } - ], - "type": "HardDrive", - "size": 76293, - "manufacturer": "Seagate", - "interface": "ATA", - "model": "ST3808110AS" - }, - { - "serialNumber": null, - "events": [], - "type": "GraphicCard", - "manufacturer": "Intel Corporation", - "memory": 256.0, - "model": "82945G/GZ Integrated Graphics Controller" - }, - { - "slots": 0, - "usb": 5, - "serial": 1, - "events": [], - "serialNumber": "..CN1374063201S5.", - "pcmcia": 0, - "type": "Motherboard", - "firewire": 0, - "manufacturer": "Dell Inc.", - "model": "0UG982" + "rate": 100.4242, + "type": "BenchmarkProcessorSysbench", + "elapsed": 101 } + ], + "type": "Processor", + "manufacturer": "Intel Corp.", + "speed": 3.0, + "model": "Intel Pentium 4 CPU 3.00GHz" + }, + { + "serialNumber": null, + "events": [], + "type": "SoundCard", + "manufacturer": "Intel Corporation", + "model": "82801G AC'97 Audio Controller" + }, + { + "size": 512, + "serialNumber": "4A7012A1", + "events": [], + "speed": 533.0, + "type": "RamModule", + "format": "DIMM", + "manufacturer": "Nanya Technology", + "interface": "DDR", + "model": "NT512T64U88A0BY-37" + }, + { + "size": 512, + "serialNumber": null, + "events": [], + "speed": 533.0, + "type": "RamModule", + "format": "DIMM", + "manufacturer": null, + "interface": "DDR", + "model": null + }, + { + "serialNumber": "00:13:72:78:53:12", + "events": [], + "type": "NetworkAdapter", + "manufacturer": "Broadcom Limited", + "speed": 1000, + "model": "NetXtreme BCM5751 Gigabit Ethernet PCI Express", + "wireless": false + }, + { + "serialNumber": "5LR30DTZ", + "events": [ + { + "steps": [ + { + "error": false, + "type": "StepRandom", + "startTime": "2018-07-11T11:20:01.005336", + "endTime": "2018-07-11T11:42:12.971177" + } + ], + "zeros": false, + "error": false, + "type": "EraseBasic", + "endTime": "2018-07-11T11:42:12.975358", + "startTime": "2018-07-11T11:20:01.004892" + }, + { + "writeSpeed": 26.6, + "type": "BenchmarkDataStorage", + "readSpeed": 73.9, + "elapsed": 14 + }, + { + "length": "Short", + "error": true, + "type": "TestDataStorage", + "status": "Unspecified Error. Self-test not started.", + "elapsed": 0 + } + ], + "type": "HardDrive", + "size": 76293, + "manufacturer": "Seagate", + "interface": "ATA", + "model": "ST3808110AS" + }, + { + "serialNumber": null, + "events": [], + "type": "GraphicCard", + "manufacturer": "Intel Corporation", + "memory": 256.0, + "model": "82945G/GZ Integrated Graphics Controller" + }, + { + "slots": 0, + "usb": 5, + "serial": 1, + "events": [], + "serialNumber": "..CN1374063201S5.", + "pcmcia": 0, + "type": "Motherboard", + "firewire": 0, + "manufacturer": "Dell Inc.", + "model": "0UG982" + } ], "version": "11.0a3", "closed": false, "elapsed": 1512, - "date": "2018-07-11T11:17:00.888231", + "endTime": "2018-07-11T11:17:00.888231", "type": "Snapshot", "expectedEvents": [ "Benchmark", @@ -149,4 +149,4 @@ "StressTest", "EraseBasic" ] -} \ No newline at end of file +} diff --git a/ereuse_devicehub/dummy/files/hp1.snapshot.11.yaml b/ereuse_devicehub/dummy/files/hp1.snapshot.11.yaml index 1fadfcb4..e622d238 100644 --- a/ereuse_devicehub/dummy/files/hp1.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/hp1.snapshot.11.yaml @@ -9,134 +9,134 @@ "closed": false, "elapsed": -3058, "uuid": "106930cd-e948-4cca-a8c8-1e39d6192ad6", - "date": "2018-07-11T10:47:50.822380", + "endTime": "2018-07-11T10:47:50.822380", "components": [ + { + "type": "Processor", + "speed": 1.199, + "events": [ { - "type": "Processor", - "speed": 1.199, - "events": [ - { - "type": "BenchmarkProcessor", - "rate": 23409.32, - "elapsed": 0 - }, - { - "type": "BenchmarkProcessorSysbench", - "rate": 17.0196, - "elapsed": 17 - } - ], - "serialNumber": null, - "address": 64, - "cores": 2, - "model": "Intel Core i3 CPU 530 @ 2.93GHz", - "manufacturer": "Intel Corp." + "type": "BenchmarkProcessor", + "rate": 23409.32, + "elapsed": 0 }, { - "memory": 256.0, - "type": "GraphicCard", - "events": [], - "serialNumber": null, - "model": "Core Processor Integrated Graphics Controller", - "manufacturer": "Intel Corporation" - }, - { - "type": "NetworkAdapter", - "speed": 1000, - "events": [], - "serialNumber": "6c:62:6d:81:22:65", - "model": "82578DM Gigabit Network Connection", - "manufacturer": "Intel Corporation", - "wireless": false - }, - { - "type": "SoundCard", - "events": [], - "serialNumber": null, - "model": "5 Series/3400 Series Chipset High Definition Audio", - "manufacturer": "Intel Corporation" - }, - { - "speed": 1333.0, - "type": "RamModule", - "format": "DIMM", - "events": [], - "size": 2048, - "serialNumber": "E6002F30", - "interface": "DDR3", - "model": "16JTF25664AZ-1G4F", - "manufacturer": "JEDEC ID:80 2C" - }, - { - "type": "HardDrive", - "events": [ - { - "type": "EraseBasic", - "zeros": false, - "endTime": "2018-07-11T11:56:52.390306", - "error": false, - "startTime": "2018-07-11T10:49:31.998217", - "steps": [ - { - "type": "StepRandom", - "endTime": "2018-07-11T11:56:52.386505", - "error": false, - "startTime": "2018-07-11T10:49:31.998609" - } - ] - }, - { - "length": "Short", - "type": "TestDataStorage", - "status": "Unspecified Error. Self-test not started.", - "error": true, - "elapsed": 0 - }, - { - "type": "BenchmarkDataStorage", - "readSpeed": 61.1, - "writeSpeed": 17.1, - "elapsed": 20 - } - ], - "size": 190782, - "serialNumber": "5ND202LZ", - "interface": "ATA", - "model": "ST3200826AS", - "manufacturer": "Seagate" - }, - { - "pcmcia": 0, - "serial": 0, - "type": "Motherboard", - "slots": 0, - "events": [], - "serialNumber": "CZC0408YNC", - "usb": 2, - "firewire": 0, - "model": "304Ah", - "manufacturer": "Hewlett-Packard" + "type": "BenchmarkProcessorSysbench", + "rate": 17.0196, + "elapsed": 17 } + ], + "serialNumber": null, + "address": 64, + "cores": 2, + "model": "Intel Core i3 CPU 530 @ 2.93GHz", + "manufacturer": "Intel Corp." + }, + { + "memory": 256.0, + "type": "GraphicCard", + "events": [], + "serialNumber": null, + "model": "Core Processor Integrated Graphics Controller", + "manufacturer": "Intel Corporation" + }, + { + "type": "NetworkAdapter", + "speed": 1000, + "events": [], + "serialNumber": "6c:62:6d:81:22:65", + "model": "82578DM Gigabit Network Connection", + "manufacturer": "Intel Corporation", + "wireless": false + }, + { + "type": "SoundCard", + "events": [], + "serialNumber": null, + "model": "5 Series/3400 Series Chipset High Definition Audio", + "manufacturer": "Intel Corporation" + }, + { + "speed": 1333.0, + "type": "RamModule", + "format": "DIMM", + "events": [], + "size": 2048, + "serialNumber": "E6002F30", + "interface": "DDR3", + "model": "16JTF25664AZ-1G4F", + "manufacturer": "JEDEC ID:80 2C" + }, + { + "type": "HardDrive", + "events": [ + { + "type": "EraseBasic", + "zeros": false, + "endTime": "2018-07-11T11:56:52.390306", + "error": false, + "startTime": "2018-07-11T10:49:31.998217", + "steps": [ + { + "type": "StepRandom", + "endTime": "2018-07-11T11:56:52.386505", + "error": false, + "startTime": "2018-07-11T10:49:31.998609" + } + ] + }, + { + "length": "Short", + "type": "TestDataStorage", + "status": "Unspecified Error. Self-test not started.", + "error": true, + "elapsed": 0 + }, + { + "type": "BenchmarkDataStorage", + "readSpeed": 61.1, + "writeSpeed": 17.1, + "elapsed": 20 + } + ], + "size": 190782, + "serialNumber": "5ND202LZ", + "interface": "ATA", + "model": "ST3200826AS", + "manufacturer": "Seagate" + }, + { + "pcmcia": 0, + "serial": 0, + "type": "Motherboard", + "slots": 0, + "events": [], + "serialNumber": "CZC0408YNC", + "usb": 2, + "firewire": 0, + "model": "304Ah", + "manufacturer": "Hewlett-Packard" + } ], "type": "Snapshot", "device": { "type": "Desktop", "chassis": "Tower", "events": [ - { - "type": "BenchmarkRamSysbench", - "rate": 0.9767, - "elapsed": 1 - }, - { - "type": "StressTest", - "error": false, - "elapsed": 60 - } + { + "type": "BenchmarkRamSysbench", + "rate": 0.9767, + "elapsed": 1 + }, + { + "type": "StressTest", + "error": false, + "elapsed": 60 + } ], "serialNumber": "CZC0408YNC", "model": "HP Compaq 8100 Elite SFF", "manufacturer": "Hewlett-Packard" }, "version": "11.0a3" -} \ No newline at end of file +} diff --git a/ereuse_devicehub/dummy/files/hp2.snapshot.11.yaml b/ereuse_devicehub/dummy/files/hp2.snapshot.11.yaml index 99ea49ae..eaf9e783 100644 --- a/ereuse_devicehub/dummy/files/hp2.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/hp2.snapshot.11.yaml @@ -2,150 +2,150 @@ "type": "Snapshot", "uuid": "1ced0f87-9e6e-4452-92a6-7a529df76738", "components": [ + { + "speed": 1.199, + "cores": 2, + "model": "Intel Core i3 CPU 530 @ 2.93GHz", + "manufacturer": "Intel Corp.", + "type": "Processor", + "serialNumber": null, + "address": 64, + "events": [ { - "speed": 1.199, - "cores": 2, - "model": "Intel Core i3 CPU 530 @ 2.93GHz", - "manufacturer": "Intel Corp.", - "type": "Processor", - "serialNumber": null, - "address": 64, - "events": [ - { - "elapsed": 0, - "rate": 23408.76, - "type": "BenchmarkProcessor" - }, - { - "elapsed": 17, - "rate": 17.0164, - "type": "BenchmarkProcessorSysbench" - } - ] + "elapsed": 0, + "rate": 23408.76, + "type": "BenchmarkProcessor" }, { - "model": "Core Processor Integrated Graphics Controller", - "manufacturer": "Intel Corporation", - "type": "GraphicCard", - "serialNumber": null, - "memory": 256.0, - "events": [] - }, - { - "speed": 1000, - "model": "82578DM Gigabit Network Connection", - "manufacturer": "Intel Corporation", - "type": "NetworkAdapter", - "wireless": false, - "serialNumber": "6c:62:6d:81:21:7f", - "events": [] - }, - { - "model": "5 Series/3400 Series Chipset High Definition Audio", - "manufacturer": "Intel Corporation", - "type": "SoundCard", - "serialNumber": null, - "events": [] - }, - { - "interface": "DDR3", - "size": 2048, - "serialNumber": "E1482E29", - "model": "16JTF25664AZ-1G4F", - "format": "DIMM", - "manufacturer": "JEDEC ID:80 2C", - "type": "RamModule", - "speed": 1333.0, - "events": [] - }, - { - "interface": "ATA", - "size": 78533, - "model": "HDS72168", - "manufacturer": "Hitachi", - "type": "HardDrive", - "serialNumber": "PVB200Z30JWXRF", - "events": [ - { - "elapsed": 1, - "type": "TestDataStorage", - "error": true, - "status": "Unspecified Error. Self-test not started.", - "length": "Short" - }, - { - "writeSpeed": 25.3, - "elapsed": 14, - "type": "BenchmarkDataStorage", - "readSpeed": 77.7 - }, - { - "startTime": "2018-07-11T10:32:14.445306", - "zeros": false, - "type": "EraseBasic", - "error": false, - "endTime": "2018-07-11T10:53:46.442123", - "steps": [ - { - "startTime": "2018-07-11T10:32:14.445496", - "type": "StepRandom", - "error": false, - "endTime": "2018-07-11T10:53:46.438901" - } - ] - } - ] - }, - { - "interface": "ATA", - "size": 76324, - "model": "ST380815AS", - "manufacturer": "Seagate", - "type": "HardDrive", - "serialNumber": "9QZCVLJX", - "events": [ - { - "elapsed": 0, - "type": "TestDataStorage", - "error": true, - "status": "Unspecified Error. Self-test not started.", - "length": "Short" - }, - { - "startTime": "2018-07-11T10:53:46.442187", - "zeros": false, - "type": "EraseBasic", - "error": false, - "endTime": "2018-07-11T11:16:28.469899", - "steps": [ - { - "startTime": "2018-07-11T10:53:46.442343", - "type": "StepRandom", - "error": false, - "endTime": "2018-07-11T11:16:28.463789" - } - ] - }, - { - "writeSpeed": 22.8, - "elapsed": 15, - "type": "BenchmarkDataStorage", - "readSpeed": 74.7 - } - ] - }, - { - "firewire": 0, - "pcmcia": 0, - "model": "304Ah", - "serial": 0, - "manufacturer": "Hewlett-Packard", - "type": "Motherboard", - "serialNumber": "CZC0408YP6", - "slots": 0, - "usb": 2, - "events": [] + "elapsed": 17, + "rate": 17.0164, + "type": "BenchmarkProcessorSysbench" } + ] + }, + { + "model": "Core Processor Integrated Graphics Controller", + "manufacturer": "Intel Corporation", + "type": "GraphicCard", + "serialNumber": null, + "memory": 256.0, + "events": [] + }, + { + "speed": 1000, + "model": "82578DM Gigabit Network Connection", + "manufacturer": "Intel Corporation", + "type": "NetworkAdapter", + "wireless": false, + "serialNumber": "6c:62:6d:81:21:7f", + "events": [] + }, + { + "model": "5 Series/3400 Series Chipset High Definition Audio", + "manufacturer": "Intel Corporation", + "type": "SoundCard", + "serialNumber": null, + "events": [] + }, + { + "interface": "DDR3", + "size": 2048, + "serialNumber": "E1482E29", + "model": "16JTF25664AZ-1G4F", + "format": "DIMM", + "manufacturer": "JEDEC ID:80 2C", + "type": "RamModule", + "speed": 1333.0, + "events": [] + }, + { + "interface": "ATA", + "size": 78533, + "model": "HDS72168", + "manufacturer": "Hitachi", + "type": "HardDrive", + "serialNumber": "PVB200Z30JWXRF", + "events": [ + { + "elapsed": 1, + "type": "TestDataStorage", + "error": true, + "status": "Unspecified Error. Self-test not started.", + "length": "Short" + }, + { + "writeSpeed": 25.3, + "elapsed": 14, + "type": "BenchmarkDataStorage", + "readSpeed": 77.7 + }, + { + "startTime": "2018-07-11T10:32:14.445306", + "zeros": false, + "type": "EraseBasic", + "error": false, + "endTime": "2018-07-11T10:53:46.442123", + "steps": [ + { + "startTime": "2018-07-11T10:32:14.445496", + "type": "StepRandom", + "error": false, + "endTime": "2018-07-11T10:53:46.438901" + } + ] + } + ] + }, + { + "interface": "ATA", + "size": 76324, + "model": "ST380815AS", + "manufacturer": "Seagate", + "type": "HardDrive", + "serialNumber": "9QZCVLJX", + "events": [ + { + "elapsed": 0, + "type": "TestDataStorage", + "error": true, + "status": "Unspecified Error. Self-test not started.", + "length": "Short" + }, + { + "startTime": "2018-07-11T10:53:46.442187", + "zeros": false, + "type": "EraseBasic", + "error": false, + "endTime": "2018-07-11T11:16:28.469899", + "steps": [ + { + "startTime": "2018-07-11T10:53:46.442343", + "type": "StepRandom", + "error": false, + "endTime": "2018-07-11T11:16:28.463789" + } + ] + }, + { + "writeSpeed": 22.8, + "elapsed": 15, + "type": "BenchmarkDataStorage", + "readSpeed": 74.7 + } + ] + }, + { + "firewire": 0, + "pcmcia": 0, + "model": "304Ah", + "serial": 0, + "manufacturer": "Hewlett-Packard", + "type": "Motherboard", + "serialNumber": "CZC0408YP6", + "slots": 0, + "usb": 2, + "events": [] + } ], "closed": false, "version": "11.0a3", @@ -156,16 +156,16 @@ "serialNumber": "CZC0408YP6", "chassis": "Tower", "events": [ - { - "error": false, - "elapsed": 60, - "type": "StressTest" - }, - { - "elapsed": 1, - "rate": 0.9783, - "type": "BenchmarkRamSysbench" - } + { + "error": false, + "elapsed": 60, + "type": "StressTest" + }, + { + "elapsed": 1, + "rate": 0.9783, + "type": "BenchmarkRamSysbench" + } ] }, "expectedEvents": [ @@ -175,6 +175,6 @@ "EraseBasic" ], "software": "Workbench", - "date": "2018-07-11T10:30:22.395958", + "endTime": "2018-07-11T10:30:22.395958", "elapsed": 2766 -} \ No newline at end of file +} diff --git a/ereuse_devicehub/dummy/files/lenovo-3493BAG.snapshot.11.yaml b/ereuse_devicehub/dummy/files/lenovo-3493BAG.snapshot.11.yaml index 6f020866..eb1c6e05 100644 --- a/ereuse_devicehub/dummy/files/lenovo-3493BAG.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/lenovo-3493BAG.snapshot.11.yaml @@ -2,21 +2,21 @@ "uuid": "9c3560a9-371c-4392-b586-37090b5f79c6", "version": "11.0a3", "closed": false, - "date": "2018-07-11T13:26:29.365504", + "endTime": "2018-07-11T13:26:29.365504", "type": "Snapshot", "device": { "serialNumber": "PB357N0", "events": [ - { - "elapsed": 60, - "type": "StressTest", - "error": false - }, - { - "elapsed": 1, - "type": "BenchmarkRamSysbench", - "rate": 0.8438 - } + { + "elapsed": 60, + "type": "StressTest", + "error": false + }, + { + "elapsed": 1, + "type": "BenchmarkRamSysbench", + "rate": 0.8438 + } ], "chassis": "Tower", "model": "3493BAG", @@ -26,112 +26,112 @@ "elapsed": 2255, "software": "Workbench", "components": [ + { + "events": [], + "speed": 1000, + "serialNumber": "d4:3d:7e:41:c4:c4", + "model": "RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller", + "manufacturer": "Realtek Semiconductor Co., Ltd.", + "type": "NetworkAdapter", + "wireless": false + }, + { + "cores": 2, + "events": [ { - "events": [], - "speed": 1000, - "serialNumber": "d4:3d:7e:41:c4:c4", - "model": "RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller", - "manufacturer": "Realtek Semiconductor Co., Ltd.", - "type": "NetworkAdapter", - "wireless": false + "elapsed": 0, + "type": "BenchmarkProcessor", + "rate": 11573.64 }, { - "cores": 2, - "events": [ - { - "elapsed": 0, - "type": "BenchmarkProcessor", - "rate": 11573.64 - }, - { - "elapsed": 19, - "type": "BenchmarkProcessorSysbench", - "rate": 19.1558 - } - ], - "speed": 1.665234, - "serialNumber": null, - "address": 64, - "model": "Intel Pentium CPU G645 @ 2.90GHz", - "manufacturer": "Intel Corp.", - "type": "Processor" - }, - { - "events": [], - "memory": 256.0, - "serialNumber": null, - "model": "2nd Generation Core Processor Family Integrated Graphics Controller", - "manufacturer": "Intel Corporation", - "type": "GraphicCard" - }, - { - "events": [], - "serialNumber": null, - "model": "6 Series/C200 Series Chipset Family High Definition Audio Controller", - "manufacturer": "Intel Corporation", - "type": "SoundCard" - }, - { - "serialNumber": "292E48DA", - "events": [], - "speed": 1333.0, - "size": 2048, - "format": "DIMM", - "interface": "DDR3", - "model": "16JTF25664AZ-1G4F1", - "manufacturer": "Micron", - "type": "RamModule" - }, - { - "serialNumber": "Z2AYPLNP", - "events": [ - { - "writeSpeed": 20.4, - "type": "BenchmarkDataStorage", - "readSpeed": 139.0, - "elapsed": 15 - }, - { - "error": true, - "type": "TestDataStorage", - "elapsed": 0, - "length": "Short", - "status": "Unspecified Error. Self-test not started." - }, - { - "startTime": "2018-07-11T13:28:07.319948", - "type": "EraseBasic", - "endTime": "2018-07-11T14:04:04.864425", - "error": false, - "steps": [ - { - "startTime": "2018-07-11T13:28:07.320244", - "type": "StepRandom", - "endTime": "2018-07-11T14:04:04.861590", - "error": false - } - ], - "zeros": false - } - ], - "size": 238475, - "interface": "ATA", - "model": "ST250DM000-1BD14", - "manufacturer": "Seagate", - "type": "HardDrive" - }, - { - "serial": 1, - "usb": 2, - "pcmcia": 0, - "events": [], - "slots": 2, - "serialNumber": null, - "firewire": 0, - "model": null, - "manufacturer": "LENOVO", - "type": "Motherboard" + "elapsed": 19, + "type": "BenchmarkProcessorSysbench", + "rate": 19.1558 } + ], + "speed": 1.665234, + "serialNumber": null, + "address": 64, + "model": "Intel Pentium CPU G645 @ 2.90GHz", + "manufacturer": "Intel Corp.", + "type": "Processor" + }, + { + "events": [], + "memory": 256.0, + "serialNumber": null, + "model": "2nd Generation Core Processor Family Integrated Graphics Controller", + "manufacturer": "Intel Corporation", + "type": "GraphicCard" + }, + { + "events": [], + "serialNumber": null, + "model": "6 Series/C200 Series Chipset Family High Definition Audio Controller", + "manufacturer": "Intel Corporation", + "type": "SoundCard" + }, + { + "serialNumber": "292E48DA", + "events": [], + "speed": 1333.0, + "size": 2048, + "format": "DIMM", + "interface": "DDR3", + "model": "16JTF25664AZ-1G4F1", + "manufacturer": "Micron", + "type": "RamModule" + }, + { + "serialNumber": "Z2AYPLNP", + "events": [ + { + "writeSpeed": 20.4, + "type": "BenchmarkDataStorage", + "readSpeed": 139.0, + "elapsed": 15 + }, + { + "error": true, + "type": "TestDataStorage", + "elapsed": 0, + "length": "Short", + "status": "Unspecified Error. Self-test not started." + }, + { + "startTime": "2018-07-11T13:28:07.319948", + "type": "EraseBasic", + "endTime": "2018-07-11T14:04:04.864425", + "error": false, + "steps": [ + { + "startTime": "2018-07-11T13:28:07.320244", + "type": "StepRandom", + "endTime": "2018-07-11T14:04:04.861590", + "error": false + } + ], + "zeros": false + } + ], + "size": 238475, + "interface": "ATA", + "model": "ST250DM000-1BD14", + "manufacturer": "Seagate", + "type": "HardDrive" + }, + { + "serial": 1, + "usb": 2, + "pcmcia": 0, + "events": [], + "slots": 2, + "serialNumber": null, + "firewire": 0, + "model": null, + "manufacturer": "LENOVO", + "type": "Motherboard" + } ], "expectedEvents": [ "Benchmark", @@ -139,4 +139,4 @@ "StressTest", "EraseBasic" ] -} \ No newline at end of file +} diff --git a/ereuse_devicehub/dummy/files/nec.snapshot.11.yaml b/ereuse_devicehub/dummy/files/nec.snapshot.11.yaml index f65ef095..54c645ea 100644 --- a/ereuse_devicehub/dummy/files/nec.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/nec.snapshot.11.yaml @@ -5,139 +5,139 @@ "serialNumber": "SN 123456789ABC", "manufacturer": "NEC Computers SAS", "events": [ - { - "error": false, - "elapsed": 60, - "type": "StressTest" - }, - { - "rate": 0.9323, - "elapsed": 1, - "type": "BenchmarkRamSysbench" - } + { + "error": false, + "elapsed": 60, + "type": "StressTest" + }, + { + "rate": 0.9323, + "elapsed": 1, + "type": "BenchmarkRamSysbench" + } ], "type": "Desktop", "chassis": "Tower", "model": "Powermate MLxxx" }, "components": [ + { + "serialNumber": "00:24:21:7a:90:02", + "manufacturer": "Intel Corporation", + "speed": 1000, + "events": [], + "type": "NetworkAdapter", + "wireless": false, + "model": "82566DM-2 Gigabit Network Connection" + }, + { + "serialNumber": null, + "manufacturer": "Intel Corp.", + "speed": 3.0, + "cores": 2, + "events": [ { - "serialNumber": "00:24:21:7a:90:02", - "manufacturer": "Intel Corporation", - "speed": 1000, - "events": [], - "type": "NetworkAdapter", - "wireless": false, - "model": "82566DM-2 Gigabit Network Connection" + "rate": 20.1309, + "elapsed": 20, + "type": "BenchmarkProcessorSysbench" }, { - "serialNumber": null, - "manufacturer": "Intel Corp.", - "speed": 3.0, - "cores": 2, - "events": [ - { - "rate": 20.1309, - "elapsed": 20, - "type": "BenchmarkProcessorSysbench" - }, - { - "rate": 11999.24, - "elapsed": 0, - "type": "BenchmarkProcessor" - } - ], - "type": "Processor", - "model": "Intel Core2 Duo CPU E8400 @ 3.00GHz", - "address": 64 - }, - { - "serialNumber": null, - "manufacturer": "Intel Corporation", - "memory": 256.0, - "events": [], - "type": "GraphicCard", - "model": "82Q35 Express Integrated Graphics Controller" - }, - { - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [], - "type": "SoundCard", - "model": "82801I HD Audio Controller" - }, - { - "serialNumber": "253C8F0C", - "manufacturer": "Samsung", - "speed": 667.0, - "interface": "DDR2", - "format": "DIMM", - "size": 1024, - "events": [], - "type": "RamModule", - "model": "M3 78T2863QZS-CE6" - }, - { - "serialNumber": "253C8DE7", - "manufacturer": "Samsung", - "speed": 667.0, - "interface": "DDR2", - "format": "DIMM", - "size": 1024, - "events": [], - "type": "RamModule", - "model": "M3 78T2863QZS-CE6" - }, - { - "serialNumber": "STA2L7MV39LL6D", - "manufacturer": "Hitachi", - "interface": "ATA", - "size": 305245, - "events": [ - { - "error": false, - "endTime": "2018-07-11T11:33:41.531918", - "startTime": "2018-07-11T10:30:35.643855", - "zeros": false, - "type": "EraseBasic", - "steps": [ - { - "type": "StepRandom", - "endTime": "2018-07-11T11:33:41.529224", - "startTime": "2018-07-11T10:30:35.644043", - "error": false - } - ] - }, - { - "writeSpeed": 24.1, - "elapsed": 14, - "type": "BenchmarkDataStorage", - "readSpeed": 105.0 - }, - { - "type": "TestDataStorage", - "length": "Short", - "elapsed": 1, - "error": true, - "status": "Unspecified Error. Self-test not started." - } - ], - "type": "HardDrive", - "model": "HDT72103" - }, - { - "serialNumber": "9516777584", - "manufacturer": "Micro-Star International Co Ltd", - "serial": 1, - "pcmcia": 0, - "usb": 8, - "events": [], - "type": "Motherboard", - "model": "MS-7377", - "firewire": 1, - "slots": 4 + "rate": 11999.24, + "elapsed": 0, + "type": "BenchmarkProcessor" } + ], + "type": "Processor", + "model": "Intel Core2 Duo CPU E8400 @ 3.00GHz", + "address": 64 + }, + { + "serialNumber": null, + "manufacturer": "Intel Corporation", + "memory": 256.0, + "events": [], + "type": "GraphicCard", + "model": "82Q35 Express Integrated Graphics Controller" + }, + { + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [], + "type": "SoundCard", + "model": "82801I HD Audio Controller" + }, + { + "serialNumber": "253C8F0C", + "manufacturer": "Samsung", + "speed": 667.0, + "interface": "DDR2", + "format": "DIMM", + "size": 1024, + "events": [], + "type": "RamModule", + "model": "M3 78T2863QZS-CE6" + }, + { + "serialNumber": "253C8DE7", + "manufacturer": "Samsung", + "speed": 667.0, + "interface": "DDR2", + "format": "DIMM", + "size": 1024, + "events": [], + "type": "RamModule", + "model": "M3 78T2863QZS-CE6" + }, + { + "serialNumber": "STA2L7MV39LL6D", + "manufacturer": "Hitachi", + "interface": "ATA", + "size": 305245, + "events": [ + { + "error": false, + "endTime": "2018-07-11T11:33:41.531918", + "startTime": "2018-07-11T10:30:35.643855", + "zeros": false, + "type": "EraseBasic", + "steps": [ + { + "type": "StepRandom", + "endTime": "2018-07-11T11:33:41.529224", + "startTime": "2018-07-11T10:30:35.644043", + "error": false + } + ] + }, + { + "writeSpeed": 24.1, + "elapsed": 14, + "type": "BenchmarkDataStorage", + "readSpeed": 105.0 + }, + { + "type": "TestDataStorage", + "length": "Short", + "elapsed": 1, + "error": true, + "status": "Unspecified Error. Self-test not started." + } + ], + "type": "HardDrive", + "model": "HDT72103" + }, + { + "serialNumber": "9516777584", + "manufacturer": "Micro-Star International Co Ltd", + "serial": 1, + "pcmcia": 0, + "usb": 8, + "events": [], + "type": "Motherboard", + "model": "MS-7377", + "firewire": 1, + "slots": 4 + } ], "version": "11.0a3", "expectedEvents": [ @@ -146,8 +146,8 @@ "StressTest", "EraseBasic" ], - "date": "2018-07-11T10:28:55.879745", + "endTime": "2018-07-11T10:28:55.879745", "type": "Snapshot", "elapsed": 3886, "closed": false -} \ No newline at end of file +} diff --git a/ereuse_devicehub/dummy/files/real-eee-1001pxd.snapshot.11.yaml b/ereuse_devicehub/dummy/files/real-eee-1001pxd.snapshot.11.yaml index b924ac06..47bf9d8f 100644 --- a/ereuse_devicehub/dummy/files/real-eee-1001pxd.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/real-eee-1001pxd.snapshot.11.yaml @@ -1,134 +1,134 @@ { "components": [ + { + "type": "NetworkAdapter", + "model": "AR9285 Wireless Network Adapter", + "serialNumber": "74:2f:68:8b:fd:c8", + "manufacturer": "Qualcomm Atheros", + "wireless": true, + "events": [] + }, + { + "type": "NetworkAdapter", + "model": "AR8152 v2.0 Fast Ethernet", + "serialNumber": "14:da:e9:42:f6:7c", + "manufacturer": "Qualcomm Atheros", + "speed": 100, + "wireless": false, + "events": [] + }, + { + "type": "Processor", + "cores": 1, + "threads": 1, + "address": 64, + "model": "Intel Atom CPU N455 @ 1.66GHz", + "serialNumber": null, + "manufacturer": "Intel Corp.", + "speed": 1.667, + "events": [ { - "type": "NetworkAdapter", - "model": "AR9285 Wireless Network Adapter", - "serialNumber": "74:2f:68:8b:fd:c8", - "manufacturer": "Qualcomm Atheros", - "wireless": true, - "events": [] + "type": "BenchmarkProcessorSysbench", + "rate": 164.0803, + "elapsed": 164 }, { - "type": "NetworkAdapter", - "model": "AR8152 v2.0 Fast Ethernet", - "serialNumber": "14:da:e9:42:f6:7c", - "manufacturer": "Qualcomm Atheros", - "speed": 100, - "wireless": false, - "events": [] - }, - { - "type": "Processor", - "cores": 1, - "threads": 1, - "address": 64, - "model": "Intel Atom CPU N455 @ 1.66GHz", - "serialNumber": null, - "manufacturer": "Intel Corp.", - "speed": 1.667, - "events": [ - { - "type": "BenchmarkProcessorSysbench", - "rate": 164.0803, - "elapsed": 164 - }, - { - "type": "BenchmarkProcessor", - "rate": 6666.24, - "elapsed": 0 - } - ] - }, - { - "type": "GraphicCard", - "model": "Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller", - "serialNumber": null, - "memory": 256.0, - "manufacturer": "Intel Corporation", - "events": [] - }, - { - "type": "SoundCard", - "model": "NM10/ICH7 Family High Definition Audio Controller", - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [] - }, - { - "type": "SoundCard", - "model": "USB 2.0 UVC VGA WebCam", - "serialNumber": "0x0001", - "manufacturer": "Azurewave", - "events": [] - }, - { - "type": "RamModule", - "format": "DIMM", - "model": null, - "size": 1024, - "interface": "DDR2", - "serialNumber": null, - "manufacturer": null, - "speed": 667.0, - "events": [] - }, - { - "type": "HardDrive", - "model": "HTS54322", - "size": 238475, - "interface": "ATA", - "serialNumber": "E2024242CV86HJ", - "manufacturer": "Hitachi", - "events": [ - { - "type": "BenchmarkDataStorage", - "elapsed": 16, - "writeSpeed": 21.8, - "readSpeed": 66.2 - }, - { - "type": "TestDataStorage", - "length": "Short", - "elapsed": 2, - "error": true, - "status": "Unspecified Error. Self-test not started." - }, - { - "type": "EraseBasic", - "steps": [ - { - "type": "StepRandom", - "startTime": "2018-07-03T09:15:22.257059", - "error": false, - "endTime": "2018-07-03T10:32:11.843190" - } - ], - "startTime": "2018-07-03T09:15:22.256074", - "error": false, - "zeros": false, - "endTime": "2018-07-03T10:32:11.848455" - } - ] - }, - { - "type": "Motherboard", - "serial": 1, - "firewire": 0, - "model": "1001PXD", - "slots": 2, - "pcmcia": 0, - "serialNumber": "Eee0123456789", - "usb": 5, - "manufacturer": "ASUSTeK Computer INC.", - "events": [] + "type": "BenchmarkProcessor", + "rate": 6666.24, + "elapsed": 0 } + ] + }, + { + "type": "GraphicCard", + "model": "Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller", + "serialNumber": null, + "memory": 256.0, + "manufacturer": "Intel Corporation", + "events": [] + }, + { + "type": "SoundCard", + "model": "NM10/ICH7 Family High Definition Audio Controller", + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [] + }, + { + "type": "SoundCard", + "model": "USB 2.0 UVC VGA WebCam", + "serialNumber": "0x0001", + "manufacturer": "Azurewave", + "events": [] + }, + { + "type": "RamModule", + "format": "DIMM", + "model": null, + "size": 1024, + "interface": "DDR2", + "serialNumber": null, + "manufacturer": null, + "speed": 667.0, + "events": [] + }, + { + "type": "HardDrive", + "model": "HTS54322", + "size": 238475, + "interface": "ATA", + "serialNumber": "E2024242CV86HJ", + "manufacturer": "Hitachi", + "events": [ + { + "type": "BenchmarkDataStorage", + "elapsed": 16, + "writeSpeed": 21.8, + "readSpeed": 66.2 + }, + { + "type": "TestDataStorage", + "length": "Short", + "elapsed": 2, + "error": true, + "status": "Unspecified Error. Self-test not started." + }, + { + "type": "EraseBasic", + "steps": [ + { + "type": "StepRandom", + "startTime": "2018-07-03T09:15:22.257059", + "error": false, + "endTime": "2018-07-03T10:32:11.843190" + } + ], + "startTime": "2018-07-03T09:15:22.256074", + "error": false, + "zeros": false, + "endTime": "2018-07-03T10:32:11.848455" + } + ] + }, + { + "type": "Motherboard", + "serial": 1, + "firewire": 0, + "model": "1001PXD", + "slots": 2, + "pcmcia": 0, + "serialNumber": "Eee0123456789", + "usb": 5, + "manufacturer": "ASUSTeK Computer INC.", + "events": [] + } ], "elapsed": 4875, "uuid": "c058e8d2-fb92-47cb-a4b7-522b75561135", "version": "11.0a2", "type": "Snapshot", "software": "Workbench", - "date": "2018-07-03T09:10:57.034598", + "endTime": "2018-07-03T09:10:57.034598", "device": { "type": "Laptop", "model": "1001PXD", @@ -136,16 +136,16 @@ "manufacturer": "ASUSTeK Computer INC.", "chassis": "Netbook", "events": [ - { - "type": "BenchmarkRamSysbench", - "rate": 15.7188, - "elapsed": 16 - }, - { - "type": "StressTest", - "error": false, - "elapsed": 60 - } + { + "type": "BenchmarkRamSysbench", + "rate": 15.7188, + "elapsed": 16 + }, + { + "type": "StressTest", + "error": false, + "elapsed": 60 + } ] }, "expectedEvents": [ @@ -155,4 +155,4 @@ "EraseBasic" ], "closed": false -} \ No newline at end of file +} diff --git a/ereuse_devicehub/dummy/files/real-hp-quad-core.snapshot.11.yaml b/ereuse_devicehub/dummy/files/real-hp-quad-core.snapshot.11.yaml index 5cd33be3..86a38a0c 100644 --- a/ereuse_devicehub/dummy/files/real-hp-quad-core.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/real-hp-quad-core.snapshot.11.yaml @@ -4,102 +4,102 @@ "uuid": "0c822fb7-6e51-4781-86cf-994bd306212e", "software": "Workbench", "closed": false, - "date": "2018-07-05T11:57:17.284891", + "endTime": "2018-07-05T11:57:17.284891", "components": [ + { + "type": "NetworkAdapter", + "model": "82567LM-3 Gigabit Network Connection", + "speed": 1000, + "serialNumber": "00:23:24:0d:86:28", + "manufacturer": "Intel Corporation", + "wireless": false, + "events": [] + }, + { + "type": "NetworkAdapter", + "model": "82541PI Gigabit Ethernet Controller", + "speed": 1000, + "serialNumber": "00:0e:0c:b6:f2:91", + "manufacturer": "Intel Corporation", + "wireless": false, + "events": [] + }, + { + "cores": 4, + "type": "Processor", + "model": "Intel Core2 Quad CPU Q8400 @ 2.66GHz", + "speed": 1.9980000000000002, + "serialNumber": null, + "manufacturer": "Intel Corp.", + "events": [], + "address": 64 + }, + { + "type": "GraphicCard", + "model": "4 Series Chipset Integrated Graphics Controller", + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [], + "memory": 256.0 + }, + { + "type": "SoundCard", + "model": "82801JD/DO HD Audio Controller", + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [] + }, + { + "size": 2048, + "interface": "DDR3", + "type": "RamModule", + "model": "16JTF25664AZ-1G4F", + "speed": 1333.0, + "serialNumber": "F8482E29", + "format": "DIMM", + "manufacturer": "JEDEC ID:80 2C", + "events": [] + }, + { + "size": 2048, + "interface": "DDR3", + "type": "RamModule", + "model": "16JTF25664AZ-1G4F", + "speed": 1333.0, + "serialNumber": "62072F30", + "format": "DIMM", + "manufacturer": "JEDEC ID:80 2C", + "events": [] + }, + { + "size": 238475, + "interface": "ATA", + "type": "HardDrive", + "model": "ST3250318AS", + "serialNumber": "9VY6HBKE", + "manufacturer": "Seagate", + "events": [ { - "type": "NetworkAdapter", - "model": "82567LM-3 Gigabit Network Connection", - "speed": 1000, - "serialNumber": "00:23:24:0d:86:28", - "manufacturer": "Intel Corporation", - "wireless": false, - "events": [] - }, - { - "type": "NetworkAdapter", - "model": "82541PI Gigabit Ethernet Controller", - "speed": 1000, - "serialNumber": "00:0e:0c:b6:f2:91", - "manufacturer": "Intel Corporation", - "wireless": false, - "events": [] - }, - { - "cores": 4, - "type": "Processor", - "model": "Intel Core2 Quad CPU Q8400 @ 2.66GHz", - "speed": 1.9980000000000002, - "serialNumber": null, - "manufacturer": "Intel Corp.", - "events": [], - "address": 64 - }, - { - "type": "GraphicCard", - "model": "4 Series Chipset Integrated Graphics Controller", - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [], - "memory": 256.0 - }, - { - "type": "SoundCard", - "model": "82801JD/DO HD Audio Controller", - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [] - }, - { - "size": 2048, - "interface": "DDR3", - "type": "RamModule", - "model": "16JTF25664AZ-1G4F", - "speed": 1333.0, - "serialNumber": "F8482E29", - "format": "DIMM", - "manufacturer": "JEDEC ID:80 2C", - "events": [] - }, - { - "size": 2048, - "interface": "DDR3", - "type": "RamModule", - "model": "16JTF25664AZ-1G4F", - "speed": 1333.0, - "serialNumber": "62072F30", - "format": "DIMM", - "manufacturer": "JEDEC ID:80 2C", - "events": [] - }, - { - "size": 238475, - "interface": "ATA", - "type": "HardDrive", - "model": "ST3250318AS", - "serialNumber": "9VY6HBKE", - "manufacturer": "Seagate", - "events": [ - { - "elapsed": 0, - "type": "TestDataStorage", - "status": "Unspecified Error. Self-test not started.", - "error": true, - "length": "Short" - } - ] - }, - { - "slots": 0, - "pcmcia": 0, - "type": "Motherboard", - "model": "3646h", - "serialNumber": "CZC03217S7", - "firewire": 0, - "manufacturer": "Hewlett-Packard", - "events": [], - "serial": 0, - "usb": 8 + "elapsed": 0, + "type": "TestDataStorage", + "status": "Unspecified Error. Self-test not started.", + "error": true, + "length": "Short" } + ] + }, + { + "slots": 0, + "pcmcia": 0, + "type": "Motherboard", + "model": "3646h", + "serialNumber": "CZC03217S7", + "firewire": 0, + "manufacturer": "Hewlett-Packard", + "events": [], + "serial": 0, + "usb": 8 + } ], "version": "11.0a3", "device": { @@ -113,4 +113,4 @@ "expectedEvents": [ "SmartTest" ] -} \ No newline at end of file +} diff --git a/ereuse_devicehub/dummy/files/real-hp.snapshot.11.yaml b/ereuse_devicehub/dummy/files/real-hp.snapshot.11.yaml index 7a96075a..30b3e122 100644 --- a/ereuse_devicehub/dummy/files/real-hp.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/real-hp.snapshot.11.yaml @@ -2,132 +2,132 @@ "closed": false, "uuid": "f9e5e587-baee-44e1-9a94-255d216bbda9", "components": [ + { + "events": [], + "serialNumber": "6c:62:6d:81:22:9f", + "type": "NetworkAdapter", + "manufacturer": "Intel Corporation", + "speed": 1000, + "model": "82578DM Gigabit Network Connection", + "wireless": false + }, + { + "format": "DIMM", + "events": [ + ], + "interface": "DDR3", + "serialNumber": "B4012F30", + "size": 2048, + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "speed": 1333.0, + "model": "16JTF25664AZ-1G4F" + }, + { + "format": "DIMM", + "events": [], + "interface": "DDR3", + "serialNumber": "8E9F2E29", + "size": 2048, + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "speed": 1333.0, + "model": "16JTF25664AZ-1G4F" + }, + { + "format": "DIMM", + "events": [], + "interface": "DDR3", + "serialNumber": "9A012F30", + "size": 2048, + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "speed": 1333.0, + "model": "16JTF25664AZ-1G4F" + }, + { + "format": "DIMM", + "events": [ + ], + "interface": "DDR3", + "serialNumber": "8F9F2E29", + "size": 2048, + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "speed": 1333.0, + "model": "16JTF25664AZ-1G4F" + }, + { + "cores": 2, + "events": [ { - "events": [], - "serialNumber": "6c:62:6d:81:22:9f", - "type": "NetworkAdapter", - "manufacturer": "Intel Corporation", - "speed": 1000, - "model": "82578DM Gigabit Network Connection", - "wireless": false + "rate": 23410.76, + "type": "BenchmarkProcessor", + "elapsed": 1 }, { - "format": "DIMM", - "events": [ - ], - "interface": "DDR3", - "serialNumber": "B4012F30", - "size": 2048, - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "speed": 1333.0, - "model": "16JTF25664AZ-1G4F" - }, - { - "format": "DIMM", - "events": [], - "interface": "DDR3", - "serialNumber": "8E9F2E29", - "size": 2048, - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "speed": 1333.0, - "model": "16JTF25664AZ-1G4F" - }, - { - "format": "DIMM", - "events": [], - "interface": "DDR3", - "serialNumber": "9A012F30", - "size": 2048, - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "speed": 1333.0, - "model": "16JTF25664AZ-1G4F" - }, - { - "format": "DIMM", - "events": [ - ], - "interface": "DDR3", - "serialNumber": "8F9F2E29", - "size": 2048, - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "speed": 1333.0, - "model": "16JTF25664AZ-1G4F" - }, - { - "cores": 2, - "events": [ - { - "rate": 23410.76, - "type": "BenchmarkProcessor", - "elapsed": 1 - }, - { - "rate": 17.0186, - "type": "BenchmarkProcessorSysbench", - "elapsed": 18 - } - ], - "serialNumber": null, - "type": "Processor", - "manufacturer": "Intel Corp.", - "address": 64, - "speed": 1.199, - "model": "Intel Core i3 CPU 530 @ 2.93GHz" - }, - { - "events": [ - { - "writeSpeed": 24.5, - "readSpeed": 111.0, - "type": "BenchmarkDataStorage", - "elapsed": 14 - }, - { - "status": "Unspecified Error. Self-test not started.", - "error": true, - "type": "TestDataStorage", - "elapsed": 1, - "length": Short - } - ], - "interface": "ATA", - "serialNumber": "WD-WCAV2U909540", - "size": 305245, - "type": "HardDrive", - "manufacturer": "Western Digital", - "model": "WDC WD3200AAJS-6" - }, - { - "events": [], - "serialNumber": null, - "type": "SoundCard", - "manufacturer": "Intel Corporation", - "model": "5 Series/3400 Series Chipset High Definition Audio" - }, - { - "memory": 256.0, - "events": [], - "serialNumber": null, - "type": "GraphicCard", - "manufacturer": "Intel Corporation", - "model": "Core Processor Integrated Graphics Controller" - }, - { - "events": [], - "firewire": 0, - "pcmcia": 0, - "serialNumber": "CZC0408YJG", - "slots": 0, - "type": "Motherboard", - "manufacturer": "Hewlett-Packard", - "usb": 2, - "serial": 0, - "model": "304Ah" + "rate": 17.0186, + "type": "BenchmarkProcessorSysbench", + "elapsed": 18 } + ], + "serialNumber": null, + "type": "Processor", + "manufacturer": "Intel Corp.", + "address": 64, + "speed": 1.199, + "model": "Intel Core i3 CPU 530 @ 2.93GHz" + }, + { + "events": [ + { + "writeSpeed": 24.5, + "readSpeed": 111.0, + "type": "BenchmarkDataStorage", + "elapsed": 14 + }, + { + "status": "Unspecified Error. Self-test not started.", + "error": true, + "type": "TestDataStorage", + "elapsed": 1, + "length": Short + } + ], + "interface": "ATA", + "serialNumber": "WD-WCAV2U909540", + "size": 305245, + "type": "HardDrive", + "manufacturer": "Western Digital", + "model": "WDC WD3200AAJS-6" + }, + { + "events": [], + "serialNumber": null, + "type": "SoundCard", + "manufacturer": "Intel Corporation", + "model": "5 Series/3400 Series Chipset High Definition Audio" + }, + { + "memory": 256.0, + "events": [], + "serialNumber": null, + "type": "GraphicCard", + "manufacturer": "Intel Corporation", + "model": "Core Processor Integrated Graphics Controller" + }, + { + "events": [], + "firewire": 0, + "pcmcia": 0, + "serialNumber": "CZC0408YJG", + "slots": 0, + "type": "Motherboard", + "manufacturer": "Hewlett-Packard", + "usb": 2, + "serial": 0, + "model": "304Ah" + } ], "software": "Workbench", "elapsed": 96, @@ -139,16 +139,16 @@ ], "device": { "events": [ - { - "type": "StressTest", - "elapsed": 60, - "error": false - }, - { - "rate": 0.9759, - "type": "BenchmarkRamSysbench", - "elapsed": 1 - } + { + "type": "StressTest", + "elapsed": 60, + "error": false + }, + { + "rate": 0.9759, + "type": "BenchmarkRamSysbench", + "elapsed": 1 + } ], "serialNumber": "CZC0408YJG", "type": "Desktop", @@ -157,5 +157,5 @@ "model": "HP Compaq 8100 Elite SFF" }, "type": "Snapshot", - "date": "2018-06-29T12:28:54.508266" + "endTime": "2018-06-29T12:28:54.508266" } diff --git a/ereuse_devicehub/dummy/files/real-toshiba.snapshot.11.yaml b/ereuse_devicehub/dummy/files/real-toshiba.snapshot.11.yaml index bb899521..1ea7be17 100644 --- a/ereuse_devicehub/dummy/files/real-toshiba.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/real-toshiba.snapshot.11.yaml @@ -4,132 +4,132 @@ "Benchmark", "StressTest" ], - "date": "2018-06-29T15:29:29.322424", + "endTime": "2018-06-29T15:29:29.322424", "elapsed": 391, "software": "Workbench", "components": [ + { + "serialNumber": null, + "interface": "DDR", + "size": 1024, + "manufacturer": null, + "format": "SODIMM", + "events": [ + ], + "speed": 533.0, + "type": "RamModule", + "model": null + }, + { + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [], + "type": "SoundCard", + "model": "NM10/ICH7 Family High Definition Audio Controller" + }, + { + "serialNumber": null, + "manufacturer": "Chicony Electronics Co., Ltd.", + "events": [], + "type": "SoundCard", + "model": "USB2.0 UVC WebCam" + }, + { + "serialNumber": "00:23:08:a5:07:6d", + "manufacturer": "Qualcomm Atheros", + "events": [], + "type": "NetworkAdapter", + "wireless": true, + "model": "AR9285 Wireless Network Adapter" + }, + { + "serialNumber": "00:23:5a:fe:d7:14", + "manufacturer": "Realtek Semiconductor Co., Ltd.", + "events": [], + "speed": 100, + "type": "NetworkAdapter", + "wireless": false, + "model": "RTL810xE PCI Express Fast Ethernet controller" + }, + { + "serialNumber": null, + "address": 32, + "manufacturer": "Intel Corp.", + "events": [ { - "serialNumber": null, - "interface": "DDR", - "size": 1024, - "manufacturer": null, - "format": "SODIMM", - "events": [ - ], - "speed": 533.0, - "type": "RamModule", - "model": null + "rate": 171.3049, + "type": "BenchmarkProcessorSysbench", + "elapsed": 171 }, { - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [], - "type": "SoundCard", - "model": "NM10/ICH7 Family High Definition Audio Controller" - }, - { - "serialNumber": null, - "manufacturer": "Chicony Electronics Co., Ltd.", - "events": [], - "type": "SoundCard", - "model": "USB2.0 UVC WebCam" - }, - { - "serialNumber": "00:23:08:a5:07:6d", - "manufacturer": "Qualcomm Atheros", - "events": [], - "type": "NetworkAdapter", - "wireless": true, - "model": "AR9285 Wireless Network Adapter" - }, - { - "serialNumber": "00:23:5a:fe:d7:14", - "manufacturer": "Realtek Semiconductor Co., Ltd.", - "events": [], - "speed": 100, - "type": "NetworkAdapter", - "wireless": false, - "model": "RTL810xE PCI Express Fast Ethernet controller" - }, - { - "serialNumber": null, - "address": 32, - "manufacturer": "Intel Corp.", - "events": [ - { - "rate": 171.3049, - "type": "BenchmarkProcessorSysbench", - "elapsed": 171 - }, - { - "rate": 6383.9, - "type": "BenchmarkProcessor", - "elapsed": 1 - } - ], - "speed": 1.3330000000000002, - "type": "Processor", - "model": "Intel Atom CPU N270 @ 1.60GHz" - }, - { - "memory": 256.0, - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [], - "type": "GraphicCard", - "model": "Mobile 945GSE Express Integrated Graphics Controller" - }, - { - "serialNumber": "090623PB5B00QCGREMAH", - "interface": "ATA", - "size": 152627, - "manufacturer": "Hitachi", - "events": [ - { - "elapsed": 71, - "readSpeed": 19.1, - "type": "BenchmarkDataStorage", - "writeSpeed": 4.7 - }, - { - "elapsed": 2, - "status": "Unspecified Error. Self-test not started.", - "type": "TestDataStorage", - "length": Short, - "error": true - } - ], - "type": "HardDrive", - "model": "HTS54501" - }, - { - "slots": 0, - "serialNumber": "0123456789AB", - "manufacturer": "TOSHIBA", - "firewire": 0, - "events": [], - "pcmcia": 0, - "usb": 5, - "serial": 1, - "type": "Motherboard", - "model": "KAVAA" + "rate": 6383.9, + "type": "BenchmarkProcessor", + "elapsed": 1 } + ], + "speed": 1.3330000000000002, + "type": "Processor", + "model": "Intel Atom CPU N270 @ 1.60GHz" + }, + { + "memory": 256.0, + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [], + "type": "GraphicCard", + "model": "Mobile 945GSE Express Integrated Graphics Controller" + }, + { + "serialNumber": "090623PB5B00QCGREMAH", + "interface": "ATA", + "size": 152627, + "manufacturer": "Hitachi", + "events": [ + { + "elapsed": 71, + "readSpeed": 19.1, + "type": "BenchmarkDataStorage", + "writeSpeed": 4.7 + }, + { + "elapsed": 2, + "status": "Unspecified Error. Self-test not started.", + "type": "TestDataStorage", + "length": Short, + "error": true + } + ], + "type": "HardDrive", + "model": "HTS54501" + }, + { + "slots": 0, + "serialNumber": "0123456789AB", + "manufacturer": "TOSHIBA", + "firewire": 0, + "events": [], + "pcmcia": 0, + "usb": 5, + "serial": 1, + "type": "Motherboard", + "model": "KAVAA" + } ], "version": "11.0a1", "device": { "serialNumber": "79545417K", "manufacturer": "TOSHIBA", "events": [ - { - "type": "StressTest", - "error": false, - "elapsed": 120 - }, - { - "rate": 19.0443, - "type": "BenchmarkRamSysbench", - "elapsed": 19 - } + { + "type": "StressTest", + "error": false, + "elapsed": 120 + }, + { + "rate": 19.0443, + "type": "BenchmarkRamSysbench", + "elapsed": 19 + } ], "type": "Laptop", "chassis": "Netbook", diff --git a/ereuse_devicehub/dummy/files/smart.snapshot.11.yaml b/ereuse_devicehub/dummy/files/smart.snapshot.11.yaml index 62861217..4b622cd5 100644 --- a/ereuse_devicehub/dummy/files/smart.snapshot.11.yaml +++ b/ereuse_devicehub/dummy/files/smart.snapshot.11.yaml @@ -7,16 +7,16 @@ "device": { "model": "HP Compaq 8100 Elite SFF", "events": [ - { - "type": "BenchmarkRamSysbench", - "elapsed": 1, - "rate": 0.979 - }, - { - "type": "StressTest", - "elapsed": 300, - "error": false - } + { + "type": "BenchmarkRamSysbench", + "elapsed": 1, + "rate": 0.979 + }, + { + "type": "StressTest", + "elapsed": 300, + "error": false + } ], "serialNumber": "CZC0408YJG", "type": "Desktop", @@ -24,145 +24,145 @@ "chassis": "Tower" }, "components": [ + { + "model": "Intel Core i3 CPU 530 @ 2.93GHz", + "address": 64, + "events": [ { - "model": "Intel Core i3 CPU 530 @ 2.93GHz", - "address": 64, - "events": [ - { - "type": "BenchmarkProcessor", - "elapsed": 0, - "rate": 23408.68 - }, - { - "type": "BenchmarkProcessorSysbench", - "elapsed": 17, - "rate": 17.0138 - } - ], - "cores": 2, - "type": "Processor", - "manufacturer": "Intel Corp.", - "threads": 4, - "serialNumber": null, - "speed": 1.199 + "type": "BenchmarkProcessor", + "elapsed": 0, + "rate": 23408.68 }, { - "model": "Core Processor Integrated Graphics Controller", - "events": [], - "serialNumber": null, - "type": "GraphicCard", - "manufacturer": "Intel Corporation", - "memory": 256.0 - }, - { - "model": "5 Series/3400 Series Chipset High Definition Audio", - "events": [], - "serialNumber": null, - "type": "SoundCard", - "manufacturer": "Intel Corporation" - }, - { - "model": "16JTF25664AZ-1G4F", - "interface": "DDR3", - "events": [], - "serialNumber": "B4012F30", - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "format": "DIMM", - "size": 2048, - "speed": 1333.0 - }, - { - "model": "16JTF25664AZ-1G4F", - "interface": "DDR3", - "events": [], - "serialNumber": "8E9F2E29", - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "format": "DIMM", - "size": 2048, - "speed": 1333.0 - }, - { - "model": "16JTF25664AZ-1G4F", - "interface": "DDR3", - "events": [], - "serialNumber": "9A012F30", - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "format": "DIMM", - "size": 2048, - "speed": 1333.0 - }, - { - "model": "16JTF25664AZ-1G4F", - "interface": "DDR3", - "events": [], - "serialNumber": "8F9F2E29", - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "format": "DIMM", - "size": 2048, - "speed": 1333.0 - }, - { - "model": "82578DM Gigabit Network Connection", - "events": [], - "serialNumber": "6c:62:6d:81:22:9f", - "type": "NetworkAdapter", - "wireless": false, - "manufacturer": "Intel Corporation", - "speed": 1000 - }, - { - "model": "WDC WD3200AAJS-6", - "interface": "ATA", - "events": [ - { - "currentPendingSectorCount": 0, - "commandTimeout": 0, - "status": "Completed without error", - "offlineUncorrectable": 1, - "powerCycleCount": 1838, - "assessment": true, - "error": false, - "type": "TestDataStorage", - "lifetime": 10546, - "reallocatedSectorCount": 0, - "reportedUncorrectableErrors": 0, - "elapsed": 115, - "length": "Short" - }, - { - "type": "BenchmarkDataStorage", - "writeSpeed": 24.6, - "readSpeed": 112.0, - "elapsed": 13 - } - ], - "serialNumber": "WD-WCAV2U909540", - "type": "HardDrive", - "manufacturer": "Western Digital", - "size": 305245 - }, - { - "model": "304Ah", - "pcmcia": 0, - "events": [], - "usb": 2, - "firewire": 0, - "type": "Motherboard", - "slots": 0, - "manufacturer": "Hewlett-Packard", - "serial": 0, - "serialNumber": "CZC0408YJG" + "type": "BenchmarkProcessorSysbench", + "elapsed": 17, + "rate": 17.0138 } + ], + "cores": 2, + "type": "Processor", + "manufacturer": "Intel Corp.", + "threads": 4, + "serialNumber": null, + "speed": 1.199 + }, + { + "model": "Core Processor Integrated Graphics Controller", + "events": [], + "serialNumber": null, + "type": "GraphicCard", + "manufacturer": "Intel Corporation", + "memory": 256.0 + }, + { + "model": "5 Series/3400 Series Chipset High Definition Audio", + "events": [], + "serialNumber": null, + "type": "SoundCard", + "manufacturer": "Intel Corporation" + }, + { + "model": "16JTF25664AZ-1G4F", + "interface": "DDR3", + "events": [], + "serialNumber": "B4012F30", + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "format": "DIMM", + "size": 2048, + "speed": 1333.0 + }, + { + "model": "16JTF25664AZ-1G4F", + "interface": "DDR3", + "events": [], + "serialNumber": "8E9F2E29", + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "format": "DIMM", + "size": 2048, + "speed": 1333.0 + }, + { + "model": "16JTF25664AZ-1G4F", + "interface": "DDR3", + "events": [], + "serialNumber": "9A012F30", + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "format": "DIMM", + "size": 2048, + "speed": 1333.0 + }, + { + "model": "16JTF25664AZ-1G4F", + "interface": "DDR3", + "events": [], + "serialNumber": "8F9F2E29", + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "format": "DIMM", + "size": 2048, + "speed": 1333.0 + }, + { + "model": "82578DM Gigabit Network Connection", + "events": [], + "serialNumber": "6c:62:6d:81:22:9f", + "type": "NetworkAdapter", + "wireless": false, + "manufacturer": "Intel Corporation", + "speed": 1000 + }, + { + "model": "WDC WD3200AAJS-6", + "interface": "ATA", + "events": [ + { + "currentPendingSectorCount": 0, + "commandTimeout": 0, + "status": "Completed without error", + "offlineUncorrectable": 1, + "powerCycleCount": 1838, + "assessment": true, + "error": false, + "type": "TestDataStorage", + "lifetime": 10546, + "reallocatedSectorCount": 0, + "reportedUncorrectableErrors": 0, + "elapsed": 115, + "length": "Short" + }, + { + "type": "BenchmarkDataStorage", + "writeSpeed": 24.6, + "readSpeed": 112.0, + "elapsed": 13 + } + ], + "serialNumber": "WD-WCAV2U909540", + "type": "HardDrive", + "manufacturer": "Western Digital", + "size": 305245 + }, + { + "model": "304Ah", + "pcmcia": 0, + "events": [], + "usb": 2, + "firewire": 0, + "type": "Motherboard", + "slots": 0, + "manufacturer": "Hewlett-Packard", + "serial": 0, + "serialNumber": "CZC0408YJG" + } ], - "date": "2018-07-11T16:11:43.467824", + "endTime": "2018-07-11T16:11:43.467824", "version": "11.0a3", "software": "Workbench", "type": "Snapshot", "closed": false, "uuid": "c0c57946-d779-4e4e-b3e1-e63bd54cf939", "elapsed": 449 -} \ No newline at end of file +} diff --git a/ereuse_devicehub/dummy/files/workbench-server-1.snapshot.yaml b/ereuse_devicehub/dummy/files/workbench-server-1.snapshot.yaml index 36a4dbd2..aaec6d5f 100644 --- a/ereuse_devicehub/dummy/files/workbench-server-1.snapshot.yaml +++ b/ereuse_devicehub/dummy/files/workbench-server-1.snapshot.yaml @@ -17,95 +17,95 @@ device: model: d1ml manufacturer: d1mr tags: - - type: Tag - id: tag1 + - type: Tag + id: tag1 events: - - type: WorkbenchRate - appearanceRange: A - functionalityRange: B - - type: BenchmarkRamSysbench - rate: 2444 - - type: StressTest - elapsed: 300 - error: False + - type: WorkbenchRate + appearanceRange: A + functionalityRange: B + - type: BenchmarkRamSysbench + rate: 2444 + - type: StressTest + elapsed: 300 + error: False components: - - type: GraphicCard - serialNumber: gc1-1s - model: gc1-1ml - manufacturer: gc1-1mr - - type: RamModule - serialNumber: rm1-1s - model: rm1-1ml - manufacturer: rm1-1mr - - type: RamModule - serialNumber: rm2-1s - model: rm2-1ml - manufacturer: rm2-1mr - - type: Processor - model: p1-1s - manufacturer: p1-1mr - events: - - type: BenchmarkProcessor - rate: 2410 - - type: BenchmarkProcessorSysbench - rate: 4400 - - type: SolidStateDrive - serialNumber: ssd1-1s - model: ssd1-1ml - manufacturer: ssd1-1mr - events: - - type: BenchmarkDataStorage - readSpeed: 20 - writeSpeed: 15 - elapsed: 21 - - type: TestDataStorage - elapsed: 233 - error: False - status: Completed without error - length: Short - lifetime: 99 - assessment: True - powerCycleCount: 11 - reallocatedSectorCount: 2 - powerCycleCount: 4 - reportedUncorrectableErrors: 1 - commandTimeout: 11 - currentPendingSectorCount: 1 - offlineUncorrectable: 33 - remainingLifetimePercentage: 1 - - type: EraseSectors - error: False - zeros: False - startTime: 2018-01-01T10:10:10 - endTime: 2018-01-01T12:10:10 - steps: - - type: StepRandom - startTime: 2018-01-01T10:10:10 - endTime: 2018-01-01T12:10:10 - error: False - - type: HardDrive - serialNumber: hdd1-1s - model: hdd1-1ml - manufacturer: hdd1-1mr - events: - - type: BenchmarkDataStorage - readSpeed: 10 - writeSpeed: 5 - - type: EraseSectors - error: False - zeros: False - startTime: 2018-01-01T10:10:10 - endTime: 2018-01-01T12:10:10 - steps: - - type: StepRandom - startTime: 2018-01-01T10:10:10 - endTime: 2018-01-01T12:10:10 - error: False - - type: Install - elapsed: 420 - error: False - name: LinuxMint 18.01 32b - - type: Motherboard - serialNumber: mb1-1s - model: mb1-1ml - manufacturer: mb1-1mr +- type: GraphicCard + serialNumber: gc1-1s + model: gc1-1ml + manufacturer: gc1-1mr +- type: RamModule + serialNumber: rm1-1s + model: rm1-1ml + manufacturer: rm1-1mr +- type: RamModule + serialNumber: rm2-1s + model: rm2-1ml + manufacturer: rm2-1mr +- type: Processor + model: p1-1s + manufacturer: p1-1mr + events: + - type: BenchmarkProcessor + rate: 2410 + - type: BenchmarkProcessorSysbench + rate: 4400 +- type: SolidStateDrive + serialNumber: ssd1-1s + model: ssd1-1ml + manufacturer: ssd1-1mr + events: + - type: BenchmarkDataStorage + readSpeed: 20 + writeSpeed: 15 + elapsed: 21 + - type: TestDataStorage + elapsed: 233 + error: False + status: Completed without error + length: Short + lifetime: 99 + assessment: True + powerCycleCount: 11 + reallocatedSectorCount: 2 + powerCycleCount: 4 + reportedUncorrectableErrors: 1 + commandTimeout: 11 + currentPendingSectorCount: 1 + offlineUncorrectable: 33 + remainingLifetimePercentage: 1 + - type: EraseSectors + error: False + zeros: False + startTime: 2018-01-01T10:10:10 + endTime: 2018-01-01T12:10:10 + steps: + - type: StepRandom + startTime: 2018-01-01T10:10:10 + endTime: 2018-01-01T12:10:10 + error: False +- type: HardDrive + serialNumber: hdd1-1s + model: hdd1-1ml + manufacturer: hdd1-1mr + events: + - type: BenchmarkDataStorage + readSpeed: 10 + writeSpeed: 5 + - type: EraseSectors + error: False + zeros: False + startTime: 2018-01-01T10:10:10 + endTime: 2018-01-01T12:10:10 + steps: + - type: StepRandom + startTime: 2018-01-01T10:10:10 + endTime: 2018-01-01T12:10:10 + error: False + - type: Install + elapsed: 420 + error: False + name: LinuxMint 18.01 32b +- type: Motherboard + serialNumber: mb1-1s + model: mb1-1ml + manufacturer: mb1-1mr diff --git a/ereuse_devicehub/marshmallow.py b/ereuse_devicehub/marshmallow.py index 3a754336..c21d240d 100644 --- a/ereuse_devicehub/marshmallow.py +++ b/ereuse_devicehub/marshmallow.py @@ -9,6 +9,6 @@ class NestedOn(TealNestedOn): __doc__ = TealNestedOn.__doc__ def __init__(self, nested, polymorphic_on='type', db: SQLAlchemy = db, collection_class=list, - default=missing_, exclude=tuple(), only=None, **kwargs): - super().__init__(nested, polymorphic_on, db, collection_class, default, exclude, only, - **kwargs) + default=missing_, exclude=tuple(), only_query: str = None, only=None, **kwargs): + super().__init__(nested, polymorphic_on, db, collection_class, default, exclude, + only_query, only, **kwargs) diff --git a/ereuse_devicehub/resources/agent/__init__.py b/ereuse_devicehub/resources/agent/__init__.py new file mode 100644 index 00000000..c85167f2 --- /dev/null +++ b/ereuse_devicehub/resources/agent/__init__.py @@ -0,0 +1,68 @@ +import click +from flask import current_app as app + +from ereuse_devicehub.db import db +from ereuse_devicehub.resources.agent import models, schemas +from teal.db import SQLAlchemy +from teal.resource import Converters, Resource + + +class AgentDef(Resource): + SCHEMA = schemas.Agent + VIEW = None + AUTH = True + ID_CONVERTER = Converters.uuid + + +class OrganizationDef(AgentDef): + SCHEMA = schemas.Organization + VIEW = None + + def __init__(self, app, import_name=__package__, static_folder=None, static_url_path=None, + template_folder=None, url_prefix=None, subdomain=None, url_defaults=None, + root_path=None): + cli_commands = ((self.create_org, 'create-org'),) + super().__init__(app, import_name, static_folder, static_url_path, template_folder, + url_prefix, subdomain, url_defaults, root_path, cli_commands) + + @click.argument('name') + @click.argument('tax_id') + @click.argument('country') + def create_org(self, name: str, tax_id: str = None, country: str = None) -> dict: + """Creates an organization.""" + org = models.Organization(**self.schema.load( + { + 'name': name, + 'taxId': tax_id, + 'country': country + } + )) + db.session.add(org) + db.session.commit() + return self.schema.dump(org) + + def init_db(self, db: SQLAlchemy): + """Creates the default organization.""" + org = models.Organization(**app.config.get_namespace('ORGANIZATION_')) + db.session.add(org) + + +class Membership(Resource): + SCHEMA = schemas.Membership + VIEW = None + ID_CONVERTER = Converters.string + + +class IndividualDef(AgentDef): + SCHEMA = schemas.Individual + VIEW = None + + +class PersonDef(IndividualDef): + SCHEMA = schemas.Person + VIEW = None + + +class SystemDef(IndividualDef): + SCHEMA = schemas.System + VIEW = None diff --git a/ereuse_devicehub/resources/agent/models.py b/ereuse_devicehub/resources/agent/models.py new file mode 100644 index 00000000..b7218eb7 --- /dev/null +++ b/ereuse_devicehub/resources/agent/models.py @@ -0,0 +1,131 @@ +from itertools import chain +from operator import attrgetter +from uuid import uuid4 + +from flask import current_app as app, g +from sqlalchemy import Column, Enum as DBEnum, ForeignKey, Unicode, UniqueConstraint +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.ext.declarative import declared_attr +from sqlalchemy.orm import backref, relationship +from sqlalchemy_utils import EmailType, PhoneNumberType + +from ereuse_devicehub.resources.models import STR_SIZE, STR_SM_SIZE, Thing +from ereuse_devicehub.resources.user.models import User +from teal import enums +from teal.db import INHERIT_COND, POLYMORPHIC_ID, \ + POLYMORPHIC_ON + + +class JoinedTableMixin: + # noinspection PyMethodParameters + @declared_attr + def id(cls): + return Column(UUID(as_uuid=True), ForeignKey(Agent.id), primary_key=True) + + +class Agent(Thing): + id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4) + type = Column(Unicode, nullable=False) + name = Column(Unicode(length=STR_SM_SIZE)) + name.comment = """ + The name of the organization or person. + """ + tax_id = Column(Unicode(length=STR_SM_SIZE)) + tax_id.comment = """ + The Tax / Fiscal ID of the organization, + e.g. the TIN in the US or the CIF/NIF in Spain. + """ + country = Column(DBEnum(enums.Country)) + country.comment = """ + Country issuing the tax_id number. + """ + telephone = Column(PhoneNumberType()) + email = Column(EmailType, unique=True) + + user_id = Column(UUID(as_uuid=True), ForeignKey(User.id), unique=True) + user = relationship(User, + backref=backref('individuals', lazy=True, collection_class=set), + primaryjoin=user_id == User.id) + + __table_args__ = ( + UniqueConstraint(tax_id, country, name='Registration Number per country.'), + ) + + @declared_attr + def __mapper_args__(cls): + """ + Defines inheritance. + + From `the guide `_ + """ + args = {POLYMORPHIC_ID: cls.t} + if cls.t == 'Agent': + args[POLYMORPHIC_ON] = cls.type + if JoinedTableMixin in cls.mro(): + args[INHERIT_COND] = cls.id == Agent.id + return args + + @property + def events(self) -> list: + # todo test + return sorted(chain(self.events_agent, self.events_to), key=attrgetter('created')) + + def __repr__(self) -> str: + return '<{0.t} {0.name}>'.format(self) + + +class Organization(JoinedTableMixin, Agent): + def __init__(self, name: str, **kwargs) -> None: + super().__init__(**kwargs, name=name) + + @classmethod + def get_default_org_id(cls) -> UUID: + """Retrieves the default organization.""" + return g.setdefault('org_id', + Organization.query.filter_by( + **app.config.get_namespace('ORGANIZATION_') + ).one().id) + + +class Individual(JoinedTableMixin, Agent): + active_org_id = Column(UUID(as_uuid=True), ForeignKey(Organization.id)) + active_org = relationship(Organization, primaryjoin=active_org_id == Organization.id) + + +class Membership(Thing): + """Organizations that are related to the Individual. + + For example, because the individual works in or because is a member of. + """ + id = Column(Unicode(length=STR_SIZE)) + organization_id = Column(UUID(as_uuid=True), ForeignKey(Organization.id), primary_key=True) + organization = relationship(Organization, + backref=backref('members', collection_class=set, lazy=True), + primaryjoin=organization_id == Organization.id) + individual_id = Column(UUID(as_uuid=True), ForeignKey(Individual.id), primary_key=True) + individual = relationship(Individual, + backref=backref('member_of', collection_class=set, lazy=True), + primaryjoin=individual_id == Individual.id) + + def __init__(self, organization: Organization, individual: Individual, id: str = None) -> None: + super().__init__(organization=organization, + individual=individual, + id=id) + + __table_args__ = ( + UniqueConstraint(id, organization_id, name='One member id per organization.'), + ) + + +class Person(Individual): + """ + A person in the system. There can be several persons pointing to + a real. + """ + pass + + +class System(Individual): + pass diff --git a/ereuse_devicehub/resources/agent/models.pyi b/ereuse_devicehub/resources/agent/models.pyi new file mode 100644 index 00000000..0207a8cf --- /dev/null +++ b/ereuse_devicehub/resources/agent/models.pyi @@ -0,0 +1,79 @@ +import uuid +from typing import List, Set + +from sqlalchemy import Column +from sqlalchemy.orm import relationship +from sqlalchemy_utils import PhoneNumber + +from ereuse_devicehub.resources.event.models import Event, Trade +from ereuse_devicehub.resources.models import Thing +from ereuse_devicehub.resources.user import User +from teal import enums + + +class Agent(Thing): + id = ... # type: Column + name = ... # type: Column + tax_id = ... # type: Column + country = ... # type: Column + telephone = ... # type: Column + email = ... # type: Column + + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.id = ... # type: uuid.UUID + self.name = ... # type: str + self.tax_id = ... # type: str + self.country = ... # type: enums.Country + self.telephone = ... # type: PhoneNumber + self.email = ... # type: str + self.events_agent = ... # type: Set[Event] # Ordered + self.events_to = ... # type: Set[Trade] # Ordered + + @property + def events(self) -> List[Event]: + pass + + +class Organization(Agent): + def __init__(self, name: str, **kwargs): + super().__init__(**kwargs) + self.members = ... # type: Set[Membership] + + @classmethod + def get_default_org_id(cls) -> uuid.UUID: + pass + + +class Individual(Agent): + member_of = ... # type:relationship + active_org_id = ... # type:Column + active_org = ... # type:relationship + user_id = ... # type:Column + user = ... # type:relationship + + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.member_of = ... # type: Set[Membership] + self.active_org = ... # type: Organization + self.user = ... # type: User + + +class Membership(Thing): + organization = ... # type: Column + individual = ... # type: Column + id = ... # type: Column + + def __init__(self, organization: Organization, individual: Individual, id: str = None) -> None: + super().__init__() + self.organization = ... # type: Organization + self.individual = ... # type: Individual + self.id = ... # type: str + + +class Person(Individual): + pass + + +class System(Individual): + pass diff --git a/ereuse_devicehub/resources/agent/schemas.py b/ereuse_devicehub/resources/agent/schemas.py new file mode 100644 index 00000000..3e4736c7 --- /dev/null +++ b/ereuse_devicehub/resources/agent/schemas.py @@ -0,0 +1,40 @@ +from marshmallow import fields as ma_fields, validate as ma_validate +from marshmallow.fields import Email + +from ereuse_devicehub.marshmallow import NestedOn +from ereuse_devicehub.resources.models import STR_SIZE, STR_SM_SIZE +from ereuse_devicehub.resources.schemas import Thing +from teal import enums +from teal.marshmallow import EnumField, Phone + + +class Agent(Thing): + id = ma_fields.UUID(dump_only=True) + name = ma_fields.String(validate=ma_validate.Length(max=STR_SM_SIZE)) + tax_id = ma_fields.String(validate=ma_validate.Length(max=STR_SM_SIZE), + data_key='taxId') + country = EnumField(enums.Country) + telephone = Phone() + email = Email() + + +class Organization(Agent): + members = NestedOn('Membership') + + +class Membership(Thing): + organization = NestedOn(Organization) + individual = NestedOn('Individual') + id = ma_fields.String(validate=ma_validate.Length(max=STR_SIZE)) + + +class Individual(Agent): + member_of = NestedOn(Membership, many=True) + + +class Person(Individual): + pass + + +class System(Individual): + pass diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index f1598bb9..9e280b99 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -1,23 +1,23 @@ from contextlib import suppress +from itertools import chain from operator import attrgetter from typing import Dict, Set -from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \ - RamFormat, RamInterface -from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE, STR_SM_SIZE, Thing -from itertools import chain -from sqlalchemy import BigInteger, Column, Enum as DBEnum, Float, ForeignKey, Integer, Sequence, \ - SmallInteger, Unicode, inspect, Boolean +from sqlalchemy import BigInteger, Boolean, Column, Enum as DBEnum, Float, ForeignKey, Integer, \ + Sequence, SmallInteger, Unicode, inspect from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.orm import ColumnProperty, backref, relationship, validates from sqlalchemy.util import OrderedSet from sqlalchemy_utils import ColorType from stdnum import imei, meid + +from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \ + RamFormat, RamInterface +from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE, STR_SM_SIZE, Thing +from ereuse_utils.naming import Naming from teal.db import CASCADE, POLYMORPHIC_ID, POLYMORPHIC_ON, ResourceNotFound, check_range from teal.marshmallow import ValidationError -from ereuse_utils.naming import Naming - class Device(Thing): """ diff --git a/ereuse_devicehub/resources/device/schemas.py b/ereuse_devicehub/resources/device/schemas.py index 5b186232..79e0f28f 100644 --- a/ereuse_devicehub/resources/device/schemas.py +++ b/ereuse_devicehub/resources/device/schemas.py @@ -1,14 +1,15 @@ +from marshmallow import post_load, pre_load +from marshmallow.fields import Boolean, Float, Integer, Str +from marshmallow.validate import Length, OneOf, Range +from sqlalchemy.util import OrderedSet +from stdnum import imei, meid + from ereuse_devicehub.marshmallow import NestedOn from ereuse_devicehub.resources.device import models as m from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \ RamFormat, RamInterface from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE from ereuse_devicehub.resources.schemas import Thing, UnitCodes -from marshmallow import post_load, pre_load -from marshmallow.fields import Float, Integer, Str, Boolean -from marshmallow.validate import Length, OneOf, Range -from sqlalchemy.util import OrderedSet -from stdnum import imei, meid from teal.marshmallow import EnumField, ValidationError diff --git a/ereuse_devicehub/resources/enums.py b/ereuse_devicehub/resources/enums.py index 7bb7dbef..3b34fa77 100644 --- a/ereuse_devicehub/resources/enums.py +++ b/ereuse_devicehub/resources/enums.py @@ -195,3 +195,15 @@ class ComputerChassis(Enum): Detachable = 'Detachable' Tablet = 'Tablet' Virtual = 'Virtual: A device with no chassis, probably non-physical.' + + +class ReceiverRole(Enum): + """ + The role that the receiver takes in the reception; + the meaning of the reception. + """ + Intermediary = 'Generic user in the workflow of the device.' + FinalUser = 'The user that will use the device.' + CollectionPoint = 'A collection point.' + RecyclingPoint = 'A recycling point.' + Transporter = 'An user that ships the devices to another one.' diff --git a/ereuse_devicehub/resources/event/__init__.py b/ereuse_devicehub/resources/event/__init__.py index 7a64eea5..4d092541 100644 --- a/ereuse_devicehub/resources/event/__init__.py +++ b/ereuse_devicehub/resources/event/__init__.py @@ -94,9 +94,8 @@ class InstallDef(EventDef): class SnapshotDef(EventDef): - VIEW = None - SCHEMA = schemas.Snapshot VIEW = SnapshotView + SCHEMA = schemas.Snapshot def __init__(self, app, import_name=__package__, static_folder=None, static_url_path=None, template_folder=None, url_prefix=None, subdomain=None, url_defaults=None, @@ -161,6 +160,11 @@ class RepairDef(EventDef): SCHEMA = schemas.Repair +class ReadyToUse(EventDef): + VIEW = None + SCHEMA = schemas.ReadyToUse + + class ToPrepareDef(EventDef): VIEW = None SCHEMA = schemas.ToPrepare @@ -171,11 +175,61 @@ class PrepareDef(EventDef): SCHEMA = schemas.Prepare -class ToDisposeDef(EventDef): +class LiveDef(EventDef): VIEW = None - SCHEMA = schemas.ToDispose + SCHEMA = schemas.Live -class DisposeDef(EventDef): +class ReserveDef(EventDef): VIEW = None - SCHEMA = schemas.Dispose + SCHEMA = schemas.Reserve + + +class CancelReservationDef(EventDef): + VIEW = None + SCHEMA = schemas.CancelReservation + + +class SellDef(EventDef): + VIEW = None + SCHEMA = schemas.Sell + + +class DonateDef(EventDef): + VIEW = None + SCHEMA = schemas.Donate + + +class RentDef(EventDef): + VIEW = None + SCHEMA = schemas.Rent + + +class CancelTradeDef(EventDef): + VIEW = None + SCHEMA = schemas.CancelTrade + + +class ToDisposeProductDef(EventDef): + VIEW = None + SCHEMA = schemas.ToDisposeProduct + + +class DisposeProductDef(EventDef): + VIEW = None + SCHEMA = schemas.DisposeProduct + + +class ReceiveDef(EventDef): + VIEW = None + SCHEMA = schemas.Receive + + +class MigrateToDef(EventDef): + VIEW = None + SCHEMA = schemas.MigrateTo + + +class MigrateFromDef(EventDef): + VIEW = None + SCHEMA = schemas.MigrateFrom diff --git a/ereuse_devicehub/resources/event/models.py b/ereuse_devicehub/resources/event/models.py index 65335c35..766c8bea 100644 --- a/ereuse_devicehub/resources/event/models.py +++ b/ereuse_devicehub/resources/event/models.py @@ -1,11 +1,11 @@ from collections import Iterable -from datetime import timedelta +from datetime import datetime, timedelta from typing import Set, Union from uuid import uuid4 from flask import current_app as app, g from sqlalchemy import BigInteger, Boolean, CheckConstraint, Column, DateTime, Enum as DBEnum, \ - Float, ForeignKey, Interval, JSON, SmallInteger, Unicode, event, orm + Float, ForeignKey, Interval, JSON, Numeric, SmallInteger, Unicode, event, orm from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.orderinglist import ordering_list @@ -14,17 +14,23 @@ from sqlalchemy.orm.events import AttributeEvents as Events from sqlalchemy.util import OrderedSet from ereuse_devicehub.db import db +from ereuse_devicehub.resources.agent.models import Agent from ereuse_devicehub.resources.device.models import Component, Computer, DataStorage, Desktop, \ Device, Laptop, Server from ereuse_devicehub.resources.enums import AppearanceRange, BOX_RATE_3, BOX_RATE_5, Bios, \ FunctionalityRange, PriceSoftware, RATE_NEGATIVE, RATE_POSITIVE, RatingRange, RatingSoftware, \ - SnapshotExpectedEvents, SnapshotSoftware, TestHardDriveLength + ReceiverRole, 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.currency import Currency -from teal.db import ArrayOfEnum, CASCADE, CASCADE_OWN, INHERIT_COND, POLYMORPHIC_ID, \ - POLYMORPHIC_ON, StrictVersionType, check_range +from teal.db import ArrayOfEnum, CASCADE, CASCADE_OWN, INHERIT_COND, IP, POLYMORPHIC_ID, \ + POLYMORPHIC_ON, StrictVersionType, URL, check_range +from teal.enums import Country, Currency, Subdivision +from teal.marshmallow import ValidationError + +""" +A quantity of money with a currency. +""" class JoinedTableMixin: @@ -36,11 +42,11 @@ class JoinedTableMixin: class Event(Thing): id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4) + type = Column(Unicode, nullable=False) name = Column(Unicode(STR_BIG_SIZE), default='', nullable=False) name.comment = """ A name or title for the event. Used when searching for events. """ - type = Column(Unicode) incidence = Column(Boolean, default=False, nullable=False) incidence.comment = """ Should this event be reviewed due some anomaly? @@ -61,13 +67,21 @@ class Event(Thing): description.comment = """ A comment about the event. """ - date = Column(DateTime) - date.comment = """ - When this event happened. - Leave it blank if it is happening now - (the field ``created`` is used instead). - This is used for example when creating events retroactively. + start_time = Column(DateTime) + start_time.comment = """ + When the action starts. For some actions like reservations + the time when they are available, for others like renting + when the renting starts. """ + end_time = Column(DateTime) + end_time.comment = """ + When the action ends. For some actions like reservations + the time when they expire, for others like renting + the time the end rents. For punctual actions it is the time + they are performed; it differs with ``created`` in which + created is the where the system received the action. + """ + snapshot_id = Column(UUID(as_uuid=True), ForeignKey('snapshot.id', use_alter=True, name='snapshot_events')) @@ -82,9 +96,36 @@ class Event(Thing): ForeignKey(User.id), nullable=False, default=lambda: g.user.id) + # todo compute the org author = relationship(User, - backref=backref('events', lazy=True, collection_class=set), + backref=backref('authored_events', lazy=True, collection_class=set), primaryjoin=author_id == User.id) + """ + The user that recorded this action in the system. + + This does not necessarily has to be the person that produced + the action in the real world. For that purpose see + ``agent``. + """ + + agent_id = Column(UUID(as_uuid=True), + ForeignKey(Agent.id), + nullable=False, + default=lambda: g.user.individual.id) + # todo compute the org + agent = relationship(Agent, + backref=backref('events_agent', + lazy=True, + collection_class=OrderedSet, + order_by=lambda: Event.created), + primaryjoin=agent_id == Agent.id, ) + agent_id.comment = """ + The direct performer or driver of the action. e.g. John wrote a book. + + It can differ with the user that registered the action in the + system, which can be in their behalf. + """ + components = relationship(Component, backref=backref('events_components', lazy=True, @@ -93,7 +134,7 @@ class Event(Thing): secondary=lambda: EventComponent.__table__, order_by=lambda: Component.id, collection_class=OrderedSet) - """ + components.comment = """ The components that are affected by the event. When performing events to parent devices their components are @@ -138,13 +179,32 @@ class Event(Thing): args[INHERIT_COND] = cls.id == Event.id return args + @validates('end_time') + def validate_end_time(self, _, end_time: datetime): + if self.start_time and end_time <= self.start_time: + raise ValidationError('The event cannot finish before it starts.') + return end_time + + @validates('start_time') + def validate_start_time(self, _, start_time: datetime): + if self.end_time and start_time >= self.end_time: + raise ValidationError('The event cannot start after it finished.') + return start_time + class EventComponent(db.Model): device_id = Column(BigInteger, ForeignKey(Component.id), primary_key=True) event_id = Column(UUID(as_uuid=True), ForeignKey(Event.id), primary_key=True) -class EventWithOneDevice(Event): +class JoinedWithOneDeviceMixin: + # noinspection PyMethodParameters + @declared_attr + def id(cls): + return Column(UUID(as_uuid=True), ForeignKey(EventWithOneDevice.id), primary_key=True) + + +class EventWithOneDevice(JoinedTableMixin, Event): device_id = Column(BigInteger, ForeignKey(Device.id), nullable=False) device = relationship(Device, backref=backref('events_one', @@ -198,9 +258,7 @@ class Deallocate(JoinedTableMixin, EventWithMultipleDevices): organization = Column(Unicode(STR_SIZE)) -class EraseBasic(JoinedTableMixin, EventWithOneDevice): - start_time = Column(DateTime, nullable=False) - end_time = Column(DateTime, CheckConstraint('end_time > start_time'), nullable=False) +class EraseBasic(JoinedWithOneDeviceMixin, EventWithOneDevice): zeros = Column(Boolean, nullable=False) zeros.comment = """ Whether this erasure had a first erasure step consisting of @@ -208,10 +266,6 @@ class EraseBasic(JoinedTableMixin, EventWithOneDevice): """ -class Ready(EventWithMultipleDevices): - pass - - class EraseSectors(EraseBasic): pass @@ -222,7 +276,9 @@ class Step(db.Model): num = Column(SmallInteger, primary_key=True) error = Column(Boolean, default=False, nullable=False) start_time = Column(DateTime, nullable=False) + start_time.comment = Event.start_time.comment end_time = Column(DateTime, CheckConstraint('end_time > start_time'), nullable=False) + end_time.comment = Event.end_time.comment erasure = relationship(EraseBasic, backref=backref('steps', @@ -254,7 +310,7 @@ class StepRandom(Step): pass -class Snapshot(JoinedTableMixin, EventWithOneDevice): +class Snapshot(JoinedWithOneDeviceMixin, EventWithOneDevice): uuid = Column(UUID(as_uuid=True), unique=True) version = Column(StrictVersionType(STR_SM_SIZE), nullable=False) software = Column(DBEnum(SnapshotSoftware), nullable=False) @@ -266,7 +322,7 @@ class Snapshot(JoinedTableMixin, EventWithOneDevice): expected_events = Column(ArrayOfEnum(DBEnum(SnapshotExpectedEvents))) -class Install(JoinedTableMixin, EventWithOneDevice): +class Install(JoinedWithOneDeviceMixin, EventWithOneDevice): elapsed = Column(Interval, nullable=False) @@ -280,7 +336,7 @@ class SnapshotRequest(db.Model): cascade=CASCADE_OWN)) -class Rate(JoinedTableMixin, EventWithOneDevice): +class Rate(JoinedWithOneDeviceMixin, EventWithOneDevice): rating = Column(Float(decimal_return_scale=2), check_range('rating', *RATE_POSITIVE)) software = Column(DBEnum(RatingSoftware)) version = Column(StrictVersionType) @@ -401,9 +457,9 @@ class PhotoboxSystemRate(PhotoboxRate): id = Column(UUID(as_uuid=True), ForeignKey(PhotoboxRate.id), primary_key=True) -class Price(JoinedTableMixin, EventWithOneDevice): +class Price(JoinedWithOneDeviceMixin, EventWithOneDevice): currency = Column(DBEnum(Currency), nullable=False) - price = Column(Float(decimal_return_scale=2), check_range('price', 0), nullable=False) + price = Column(Numeric(precision=19, scale=4), check_range('price', 0), nullable=False) software = Column(DBEnum(PriceSoftware)) version = Column(StrictVersionType) rating_id = Column(UUID(as_uuid=True), ForeignKey(AggregateRate.id)) @@ -497,7 +553,7 @@ class EreusePrice(Price): return self.Service(self.device, self.rating.rating_range, role, self.price) -class Test(JoinedTableMixin, EventWithOneDevice): +class Test(JoinedWithOneDeviceMixin, EventWithOneDevice): elapsed = Column(Interval, nullable=False) @declared_attr @@ -536,11 +592,14 @@ class StressTest(Test): pass @validates('elapsed') - def bigger_than_a_minute(self, _, value: timedelta): - assert value.total_seconds() >= 60 + def is_minute_and_bigger_than_1_minute(self, _, value: timedelta): + seconds = value.total_seconds() + assert not bool(seconds % 60) + assert seconds >= 60 + return value -class Benchmark(JoinedTableMixin, EventWithOneDevice): +class Benchmark(JoinedWithOneDeviceMixin, EventWithOneDevice): elapsed = Column(Interval) @declared_attr @@ -589,6 +648,10 @@ class Repair(EventWithMultipleDevices): pass +class ReadyToUse(EventWithMultipleDevices): + pass + + class ToPrepare(EventWithMultipleDevices): pass @@ -597,11 +660,124 @@ class Prepare(EventWithMultipleDevices): pass -class ToDispose(EventWithMultipleDevices): +class Live(JoinedWithOneDeviceMixin, EventWithOneDevice): + ip = Column(IP, nullable=False, + comment='The IP where the live was triggered.') + subdivision_confidence = Column(SmallInteger, + check_range('subdivision_confidence', 0, 100), + nullable=False) + subdivision = Column(DBEnum(Subdivision), nullable=False) + city = Column(Unicode(STR_SM_SIZE), nullable=False) + city_confidence = Column(SmallInteger, + check_range('city_confidence', 0, 100), + nullable=False) + isp = Column(Unicode(length=STR_SM_SIZE), nullable=False) + organization = Column(Unicode(length=STR_SIZE)) + organization_type = Column(Unicode(length=STR_SM_SIZE)) + + @property + def country(self) -> Country: + return self.subdivision.country + # todo relate to snapshot + # todo testing + + +class Organize(JoinedTableMixin, EventWithMultipleDevices): pass -class Dispose(EventWithMultipleDevices): +class Reserve(Organize): + pass + + +class CancelReservation(Organize): + pass + + +class Trade(JoinedTableMixin, EventWithMultipleDevices): + shipping_date = Column(DateTime) + shipping_date.comment = """ + When are the devices going to be ready for shipping? + """ + invoice_number = Column(Unicode(length=STR_SIZE)) + invoice_number.comment = """ + The id of the invoice so they can be linked. + """ + price_id = Column(UUID(as_uuid=True), ForeignKey(Price.id)) + price = relationship(Price, + backref=backref('trade', lazy=True, uselist=False), + primaryjoin=price_id == Price.id) + price_id.comment = """ + The price set for this trade. + + If no price is set it is supposed that the trade was + not payed, usual in donations. + """ + to_id = Column(UUID(as_uuid=True), + ForeignKey(Agent.id), + nullable=False, + default=lambda: g.user.id) + # todo compute the org + to = relationship(Agent, + backref=backref('events_to', + lazy=True, + collection_class=OrderedSet, + order_by=lambda: Event.created), + primaryjoin=to_id == Agent.id) + confirms_id = Column(UUID(as_uuid=True), ForeignKey(Organize.id)) + confirms = relationship(Organize, + backref=backref('confirmation', lazy=True, uselist=False), + primaryjoin=confirms_id == Organize.id) + confirms_id.comment = """ + An organize action that this association confirms. + + For example, a ``Sell`` or ``Rent`` + can confirm a ``Reserve`` action. + """ + + +class Sell(Trade): + pass + + +class Donate(Trade): + pass + + +class Rent(Trade): + pass + + +class CancelTrade(Trade): + pass + + +class ToDisposeProduct(Trade): + pass + + +class DisposeProduct(Trade): + pass + + +class Receive(JoinedTableMixin, EventWithMultipleDevices): + role = Column(DBEnum(ReceiverRole), + nullable=False, + default=ReceiverRole.Intermediary) + + +class Migrate(JoinedTableMixin, EventWithMultipleDevices): + other = Column(URL(), nullable=False) + other.comment = """ + The URL of the Migrate in the other end. + """ + + +class MigrateTo(Migrate): + pass + + +class MigrateFrom(Migrate): pass diff --git a/ereuse_devicehub/resources/event/models.pyi b/ereuse_devicehub/resources/event/models.pyi index a933bf11..57413512 100644 --- a/ereuse_devicehub/resources/event/models.pyi +++ b/ereuse_devicehub/resources/event/models.pyi @@ -1,25 +1,31 @@ +import ipaddress from datetime import datetime, timedelta +from decimal import Decimal from distutils.version import StrictVersion -from typing import Dict, List, Set +from typing import Dict, List, Set, Union from uuid import UUID +from boltons.urlutils import URL from sqlalchemy import Column from sqlalchemy.orm import relationship from sqlalchemy_utils import Currency +from ereuse_devicehub.resources.agent.models import Agent from ereuse_devicehub.resources.device.models import Component, Computer, Device from ereuse_devicehub.resources.enums import AppearanceRange, Bios, FunctionalityRange, \ - PriceSoftware, RatingSoftware, SnapshotExpectedEvents, SnapshotSoftware, TestHardDriveLength + PriceSoftware, RatingSoftware, ReceiverRole, SnapshotExpectedEvents, SnapshotSoftware, \ + TestHardDriveLength from ereuse_devicehub.resources.image.models import Image from ereuse_devicehub.resources.models import Thing -from ereuse_devicehub.resources.user import User +from ereuse_devicehub.resources.user.models import User +from teal import enums from teal.db import Model +from teal.enums import Country class Event(Thing): id = ... # type: Column name = ... # type: Column - date = ... # type: Column type = ... # type: Column error = ... # type: Column incidence = ... # type: Column @@ -28,14 +34,19 @@ class Event(Thing): snapshot_id = ... # type: Column snapshot = ... # type: relationship author_id = ... # type: Column - author = ... # type: relationship + agent = ... # type: relationship components = ... # type: relationship parent_id = ... # type: Column parent = ... # type: relationship closed = ... # type: Column + start_time = ... # type: Column + end_time = ... # type: Column + agent_id = ... # type: Column - def __init__(self, **kwargs) -> None: - super().__init__(**kwargs) + def __init__(self, id=None, name=None, incidence=None, closed=None, error=None, + description=None, start_time=None, end_time=None, snapshot=None, agent=None, + parent=None, created=None, updated=None, author=None) -> None: + super().__init__(created, updated) self.id = ... # type: UUID self.name = ... # type: str self.type = ... # type: str @@ -43,26 +54,32 @@ class Event(Thing): self.closed = ... # type: bool self.error = ... # type: bool self.description = ... # type: str - self.date = ... # type: datetime - self.snapshot_id = ... # type: UUID + self.start_time = ... # type: datetime + self.end_time = ... # type: datetime self.snapshot = ... # type: Snapshot - self.author_id = ... # type: UUID - self.author = ... # type: User self.components = ... # type: Set[Component] - self.parent_id = ... # type: Computer self.parent = ... # type: Computer + self.agent = ... # type: Agent + self.author = ... # type: User class EventWithOneDevice(Event): - def __init__(self, **kwargs) -> None: - super().__init__(**kwargs) - self.device_id = ... # type: int + + def __init__(self, id=None, name=None, incidence=None, closed=None, error=None, + description=None, start_time=None, end_time=None, snapshot=None, agent=None, + parent=None, created=None, updated=None, author=None, device=None) -> None: + super().__init__(id, name, incidence, closed, error, description, start_time, end_time, + snapshot, agent, parent, created, updated, author) self.device = ... # type: Device class EventWithMultipleDevices(Event): - def __init__(self, **kwargs) -> None: - super().__init__(**kwargs) + + def __init__(self, id=None, name=None, incidence=None, closed=None, error=None, + description=None, start_time=None, end_time=None, snapshot=None, agent=None, + parent=None, created=None, updated=None, author=None, devices=None) -> None: + super().__init__(id, name, incidence, closed, error, description, start_time, end_time, + snapshot, agent, parent, created, updated, author) self.devices = ... # type: Set[Device] @@ -75,14 +92,15 @@ class Remove(EventWithOneDevice): class Step(Model): - def __init__(self, **kwargs) -> None: - self.erasure_id = ... # type: UUID + def __init__(self, num=None, success=None, start_time=None, end_time=None, + erasure=None, error=None) -> None: self.type = ... # type: str self.num = ... # type: int self.success = ... # type: bool self.start_time = ... # type: datetime self.end_time = ... # type: datetime self.erasure = ... # type: EraseBasic + self.error = ... # type: bool class StepZero(Step): @@ -174,7 +192,6 @@ class PhotoboxRate(IndividualRate): def __init__(self, **kwargs) -> None: super().__init__(**kwargs) self.num = ... # type: int - self.image_id = ... # type: UUID self.image = ... # type: Image @@ -205,11 +222,10 @@ class Price(EventWithOneDevice): def __init__(self, **kwargs) -> None: super().__init__(**kwargs) + self.price = ... # type: Decimal self.currency = ... # type: Currency - self.price = ... # type: float self.software = ... # type: PriceSoftware self.version = ... # type: StrictVersion - self.rating_id = ... # type: UUID self.rating = ... # type: AggregateRate @@ -260,10 +276,6 @@ class EraseBasic(EventWithOneDevice): self.success = ... # type: bool -class Ready(EventWithMultipleDevices): - pass - - class EraseSectors(EraseBasic): def __init__(self, **kwargs) -> None: super().__init__(**kwargs) @@ -311,6 +323,10 @@ class Repair(EventWithMultipleDevices): pass +class ReadyToUse(EventWithMultipleDevices): + pass + + class ToPrepare(EventWithMultipleDevices): pass @@ -319,9 +335,96 @@ class Prepare(EventWithMultipleDevices): pass -class ToDispose(EventWithMultipleDevices): +class Live(EventWithOneDevice): + ip = ... # type: Column + subdivision_confidence = ... # type: Column + subdivision = ... # type: Column + city = ... # type: Column + city_confidence = ... # type: Column + isp = ... # type: Column + organization = ... # type: Column + organization_type = ... # type: Column + + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.ip = ... # type: Union[ipaddress.IPv4Address, ipaddress.IPv6Address] + self.subdivision_confidence = ... # type: int + self.subdivision = ... # type: enums.Subdivision + self.city = ... # type: str + self.city_confidence = ... # type: int + self.isp = ... # type: str + self.organization = ... # type: str + self.organization_type = ... # type: str + self.country = ... # type: Country + + +class Organize(EventWithMultipleDevices): pass -class Dispose(EventWithMultipleDevices): +class Reserve(Organize): + pass + + +class Trade(EventWithMultipleDevices): + shipping_date = ... # type: Column + invoice_number = ... # type: Column + price = ... # type: relationship + to = ... # type: relationship + confirms = ... # type: relationship + + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.shipping_date = ... # type: datetime + self.invoice_number = ... # type: str + self.price = ... # type: Price + self.to = ... # type: Agent + self.confirms = ... # type: Organize + + +class Sell(Trade): + pass + + +class Donate(Trade): + pass + + +class Rent(Trade): + pass + + +class CancelTrade(Trade): + pass + + +class ToDisposeProduct(Trade): + pass + + +class DisposeProduct(Trade): + pass + + +class Receive(EventWithMultipleDevices): + role = ... # type:Column + + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.role = ... # type: ReceiverRole + + +class Migrate(EventWithMultipleDevices): + other = ... # type: Column + + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.other = ... # type: URL + + +class MigrateTo(Migrate): + pass + + +class MigrateFrom(Migrate): pass diff --git a/ereuse_devicehub/resources/event/schemas.py b/ereuse_devicehub/resources/event/schemas.py index 71803331..5f1aedf8 100644 --- a/ereuse_devicehub/resources/event/schemas.py +++ b/ereuse_devicehub/resources/event/schemas.py @@ -1,43 +1,49 @@ +import decimal + from flask import current_app as app from marshmallow import Schema as MarshmallowSchema, ValidationError, validates_schema -from marshmallow.fields import Boolean, DateTime, Float, Integer, List, Nested, String, TimeDelta, \ - UUID +from marshmallow.fields import Boolean, DateTime, Decimal, Float, Integer, List, Nested, String, \ + TimeDelta, URL, UUID from marshmallow.validate import Length, Range +from sqlalchemy.util import OrderedSet from ereuse_devicehub.marshmallow import NestedOn +from ereuse_devicehub.resources.agent.schemas import Agent from ereuse_devicehub.resources.device.schemas import Component, Computer, Device from ereuse_devicehub.resources.enums import AppearanceRange, Bios, FunctionalityRange, \ - PriceSoftware, RATE_POSITIVE, RatingSoftware, SnapshotExpectedEvents, SnapshotSoftware, \ - TestHardDriveLength + PriceSoftware, RATE_POSITIVE, RatingSoftware, ReceiverRole, SnapshotExpectedEvents, \ + SnapshotSoftware, TestHardDriveLength from ereuse_devicehub.resources.event import models as m from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE from ereuse_devicehub.resources.schemas import Thing from ereuse_devicehub.resources.user.schemas import User -from teal.currency import Currency -from teal.marshmallow import EnumField, Version +from teal.enums import Country, Currency, Subdivision +from teal.marshmallow import EnumField, IP, Version from teal.resource import Schema class Event(Thing): id = UUID(dump_only=True) name = String(default='', validate=Length(STR_BIG_SIZE), description=m.Event.name.comment) - date = DateTime('iso', description=m.Event.date.comment) - error = Boolean(default=False, description=m.Event.error.comment) incidence = Boolean(default=False, description=m.Event.incidence.comment) - snapshot = NestedOn('Snapshot', dump_only=True) - components = NestedOn(Component, dump_only=True, many=True) - description = String(default='', description=m.Event.description.comment) - author = NestedOn(User, dump_only=True, exclude=('token',)) closed = Boolean(missing=True, description=m.Event.closed.comment) + error = Boolean(default=False, description=m.Event.error.comment) + description = String(default='', description=m.Event.description.comment) + start_time = DateTime(data_key='startTime', description=m.Event.start_time.comment) + end_time = DateTime(data_key='endTime', description=m.Event.end_time.comment) + snapshot = NestedOn('Snapshot', dump_only=True) + agent = NestedOn(Agent, description=m.Event.agent_id.comment) + author = NestedOn(User, dump_only=True, exclude=('token',)) + components = NestedOn(Component, dump_only=True, many=True) parent = NestedOn(Computer, dump_only=True, description=m.Event.parent_id.comment) class EventWithOneDevice(Event): - device = NestedOn(Device) + device = NestedOn(Device, only_query='id') class EventWithMultipleDevices(Event): - devices = NestedOn(Device, many=True) + devices = NestedOn(Device, many=True, only_query='id', collection_class=OrderedSet) class Add(EventWithOneDevice): @@ -51,7 +57,7 @@ class Remove(EventWithOneDevice): class Allocate(EventWithMultipleDevices): to = NestedOn(User, description='The user the devices are allocated to.') - organization = String(validate=Length(STR_SIZE), + organization = String(validate=Length(max=STR_SIZE), description='The organization where the user was when this happened.') @@ -59,13 +65,11 @@ class Deallocate(EventWithMultipleDevices): from_rel = Nested(User, data_key='from', description='The user where the devices are not allocated to anymore.') - organization = String(validate=Length(STR_SIZE), + organization = String(validate=Length(max=STR_SIZE), description='The organization where the user was when this happened.') class EraseBasic(EventWithOneDevice): - start_time = DateTime(required=True, data_key='startTime') - end_time = DateTime(required=True, data_key='endTime') zeros = Boolean(required=True, description=m.EraseBasic.zeros.comment) steps = NestedOn('Step', many=True, required=True) @@ -161,7 +165,7 @@ class WorkbenchRate(ManualRate): class Price(EventWithOneDevice): currency = EnumField(Currency, required=True) - price = Float(required=True) + price = Decimal(places=4, rounding=decimal.ROUND_HALF_EVEN, required=True) software = EnumField(PriceSoftware, dump_only=True) version = Version(dump_only=True) rating = NestedOn(AggregateRate, dump_only=True) @@ -208,7 +212,6 @@ class Snapshot(EventWithOneDevice): 'are performed. Setting this value will activate' 'the async Snapshot.') - device = NestedOn(Device) elapsed = TimeDelta(precision=TimeDelta.SECONDS) components = NestedOn(Component, many=True, @@ -309,6 +312,10 @@ class Repair(EventWithMultipleDevices): pass +class ReadyToUse(EventWithMultipleDevices): + pass + + class ToPrepare(EventWithMultipleDevices): pass @@ -317,9 +324,73 @@ class Prepare(EventWithMultipleDevices): pass -class ToDispose(EventWithMultipleDevices): +class Live(EventWithOneDevice): + ip = IP(dump_only=True) + subdivision_confidence = Integer(dump_only=True, data_key='subdivisionConfidence') + subdivision = EnumField(Subdivision, dump_only=True) + country = EnumField(Country, dump_only=True) + city = String(dump_only=True) + city_confidence = Integer(dump_only=True, data_key='cityConfidence') + isp = String(dump_only=True) + organization = String(dump_only=True) + organization_type = String(dump_only=True, data_key='organizationType') + + +class Organize(EventWithMultipleDevices): pass -class Dispose(EventWithMultipleDevices): +class Reserve(Organize): + pass + + +class CancelReservation(Organize): + pass + + +class Trade(EventWithMultipleDevices): + shipping_date = DateTime(data_key='shippingDate') + invoice_number = String(validate=Length(max=STR_SIZE), data_key='invoiceNumber') + price = NestedOn(Price) + to = NestedOn(Agent, only_query='id') + confirms = NestedOn(Organize) + + +class Sell(Trade): + pass + + +class Donate(Trade): + pass + + +class Rent(Trade): + pass + + +class CancelTrade(Trade): + pass + + +class ToDisposeProduct(Trade): + pass + + +class DisposeProduct(Trade): + pass + + +class Receive(EventWithMultipleDevices): + role = EnumField(ReceiverRole) + + +class Migrate(EventWithMultipleDevices): + other = URL() + + +class MigrateTo(Migrate): + pass + + +class MigrateFrom(Migrate): pass diff --git a/ereuse_devicehub/resources/event/views.py b/ereuse_devicehub/resources/event/views.py index f782873c..972ede94 100644 --- a/ereuse_devicehub/resources/event/views.py +++ b/ereuse_devicehub/resources/event/views.py @@ -3,7 +3,7 @@ from distutils.version import StrictVersion from typing import List from uuid import UUID -from flask import request +from flask import current_app as app, request from sqlalchemy.util import OrderedSet from ereuse_devicehub.db import db @@ -14,6 +14,18 @@ from teal.resource import View class EventView(View): + def post(self): + """Posts an event.""" + json = request.get_json(validate=False) + e = app.resources[json['type']].schema.load(json) + Model = db.Model._decl_class_registry.data[json['type']]() + event = Model(**e) + db.session.add(event) + db.session.commit() + ret = self.schema.jsonify(event) + ret.status_code = 201 + return ret + def one(self, id: UUID): """Gets one event.""" event = Event.query.filter_by(id=id).one() diff --git a/ereuse_devicehub/resources/models.pyi b/ereuse_devicehub/resources/models.pyi index 2c11ac87..e1d59764 100644 --- a/ereuse_devicehub/resources/models.pyi +++ b/ereuse_devicehub/resources/models.pyi @@ -1,5 +1,3 @@ -from datetime import datetime - from sqlalchemy import Column from teal.db import Model @@ -15,8 +13,3 @@ class Thing(Model): type = ... # type: str updated = ... # type: Column created = ... # type: Column - - def __init__(self, **kwargs) -> None: - super().__init__(**kwargs) - self.updated = ... # type: datetime - self.created = ... # type: datetime diff --git a/ereuse_devicehub/resources/tag/model.py b/ereuse_devicehub/resources/tag/model.py index e0153506..30c90eac 100644 --- a/ereuse_devicehub/resources/tag/model.py +++ b/ereuse_devicehub/resources/tag/model.py @@ -2,9 +2,9 @@ from sqlalchemy import BigInteger, Column, ForeignKey, Unicode, UniqueConstraint from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import backref, relationship, validates +from ereuse_devicehub.resources.agent.models import Organization from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.models import Thing -from ereuse_devicehub.resources.user.models import Organization from teal.db import DB_CASCADE_SET_NULL, URL from teal.marshmallow import ValidationError diff --git a/ereuse_devicehub/resources/tag/view.py b/ereuse_devicehub/resources/tag/view.py index 7989020e..03b9cb89 100644 --- a/ereuse_devicehub/resources/tag/view.py +++ b/ereuse_devicehub/resources/tag/view.py @@ -5,7 +5,7 @@ from webargs.flaskparser import parser from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.tag import Tag from teal.marshmallow import ValidationError -from teal.resource import View, Schema +from teal.resource import Schema, View class TagView(View): diff --git a/ereuse_devicehub/resources/user/__init__.py b/ereuse_devicehub/resources/user/__init__.py index e5f3674e..b22d52ce 100644 --- a/ereuse_devicehub/resources/user/__init__.py +++ b/ereuse_devicehub/resources/user/__init__.py @@ -2,9 +2,8 @@ from click import argument, option from ereuse_devicehub.db import db from ereuse_devicehub.resources.user import schemas -from ereuse_devicehub.resources.user.models import Organization, User +from ereuse_devicehub.resources.user.models import User from ereuse_devicehub.resources.user.views import UserView, login -from teal.db import SQLAlchemy from teal.resource import Converters, Resource @@ -34,35 +33,3 @@ class UserDef(Resource): db.session.add(user) db.session.commit() return self.schema.dump(user) - - -class OrganizationDef(Resource): - __type__ = 'Organization' - ID_CONVERTER = Converters.uuid - AUTH = True - - def __init__(self, app, import_name=__package__, static_folder=None, static_url_path=None, - template_folder=None, url_prefix=None, subdomain=None, url_defaults=None, - root_path=None): - cli_commands = ((self.create_org, 'create-org'),) - super().__init__(app, import_name, static_folder, static_url_path, template_folder, - url_prefix, subdomain, url_defaults, root_path, cli_commands) - - @argument('name') - @argument('tax_id') - @argument('country') - def create_org(self, **kw: dict) -> dict: - """ - Creates an organization. - COUNTRY has to be 2 characters as defined by - """ - org = Organization(**self.schema.load(kw)) - db.session.add(org) - db.session.commit() - return self.schema.dump(org) - - def init_db(self, db: SQLAlchemy): - """Creates the default organization.""" - from flask import current_app as app - org = Organization(**app.config.get_namespace('ORGANIZATION_')) - db.session.add(org) diff --git a/ereuse_devicehub/resources/user/models.py b/ereuse_devicehub/resources/user/models.py index 1234d735..ac3a05da 100644 --- a/ereuse_devicehub/resources/user/models.py +++ b/ereuse_devicehub/resources/user/models.py @@ -1,11 +1,11 @@ from uuid import uuid4 -from flask import current_app as app, g -from sqlalchemy import Column, Unicode, UniqueConstraint +from flask import current_app as app +from sqlalchemy import Column from sqlalchemy.dialects.postgresql import UUID -from sqlalchemy_utils import CountryType, EmailType, PasswordType +from sqlalchemy_utils import EmailType, PasswordType -from ereuse_devicehub.resources.models import STR_SIZE, STR_SM_SIZE, Thing +from ereuse_devicehub.resources.models import STR_SIZE, Thing class User(Thing): @@ -22,32 +22,12 @@ class User(Thing): From `here `_ """ - name = Column(Unicode(length=STR_SIZE)) token = Column(UUID(as_uuid=True), default=uuid4, unique=True) def __repr__(self) -> str: - return '<{0.t} {0.id} email={0.email}>'.format(self) + return ''.format(self) - -class Organization(Thing): - id = Column(UUID(as_uuid=True), default=uuid4, primary_key=True) - name = Column(Unicode(length=STR_SM_SIZE), unique=True) - tax_id = Column(Unicode(length=STR_SM_SIZE), - comment='The Tax / Fiscal ID of the organization, ' - 'e.g. the TIN in the US or the CIF/NIF in Spain.') - country = Column(CountryType, comment='Country issuing the tax_id number.') - - __table_args__ = ( - UniqueConstraint(tax_id, country, name='Registration Number per country.'), - ) - - @classmethod - def get_default_org_id(cls) -> UUID: - """Retrieves the default organization.""" - return g.setdefault('org_id', - Organization.query.filter_by( - **app.config.get_namespace('ORGANIZATION_') - ).one().id) - - def __repr__(self) -> str: - return ''.format(self) + @property + def individual(self): + """The individual associated for this database, or None.""" + return next(iter(self.individuals), None) diff --git a/ereuse_devicehub/resources/user/models.pyi b/ereuse_devicehub/resources/user/models.pyi new file mode 100644 index 00000000..f7057e2b --- /dev/null +++ b/ereuse_devicehub/resources/user/models.pyi @@ -0,0 +1,27 @@ +from typing import Set, Union +from uuid import UUID + +from sqlalchemy import Column +from sqlalchemy_utils import Password + +from ereuse_devicehub.resources.agent.models import Individual +from ereuse_devicehub.resources.models import Thing + + +class User(Thing): + id = ... # type: Column + email = ... # type: Column + password = ... # type: Column + token = ... # type: Column + + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.id = ... # type: UUID + self.email = ... # type: str + self.password = ... # type: Password + self.individuals = ... # type: Set[Individual] + self.token = ... # type: UUID + + @property + def individual(self) -> Union[Individual, None]: + pass diff --git a/ereuse_devicehub/resources/user/schemas.py b/ereuse_devicehub/resources/user/schemas.py index d5c4c06b..af47ff0e 100644 --- a/ereuse_devicehub/resources/user/schemas.py +++ b/ereuse_devicehub/resources/user/schemas.py @@ -3,6 +3,8 @@ from base64 import b64encode from marshmallow import post_dump from marshmallow.fields import Email, String, UUID +from ereuse_devicehub.marshmallow import NestedOn +from ereuse_devicehub.resources.agent.schemas import Individual from ereuse_devicehub.resources.schemas import Thing @@ -10,6 +12,7 @@ class User(Thing): id = UUID(dump_only=True) email = Email(required=True) password = String(load_only=True, required=True) + individuals = NestedOn(Individual, many=True, dump_only=True) name = String() token = String(dump_only=True, description='Use this token in an Authorization header to access the app.' diff --git a/setup.py b/setup.py index 2cb4a6b6..3f87cace 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ setup( long_description=long_description, long_description_content_type='text/markdown', install_requires=[ - 'teal>=0.2.0a9', + 'teal>=0.2.0a11', 'marshmallow_enum', 'ereuse-utils[Naming]>=0.4b1', 'psycopg2-binary', @@ -44,7 +44,7 @@ setup( 'hashids', 'click', 'click-spinner', - 'sqlalchemy-utils[password, color, babel]', + 'sqlalchemy-utils[password, color, phone]', 'PyYAML', 'python-stdnum', 'ereuse-rate==0.0.2' @@ -53,7 +53,7 @@ setup( 'docs': [ 'sphinx', 'sphinxcontrib-httpdomain >= 1.5.0', - 'sphinxcontrib-plantuml >= 0.11', + 'sphinxcontrib-plantuml >= 0.12', 'sphinxcontrib-websupport >= 1.0.1' ], 'test': test_requires diff --git a/tests/conftest.py b/tests/conftest.py index 0ae23831..8ca761c3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,6 +8,7 @@ from ereuse_devicehub.client import Client, UserClient from ereuse_devicehub.config import DevicehubConfig from ereuse_devicehub.db import db from ereuse_devicehub.devicehub import Devicehub +from ereuse_devicehub.resources.agent.models import Person from ereuse_devicehub.resources.tag import Tag from ereuse_devicehub.resources.user.models import User @@ -66,16 +67,14 @@ def user(app: Devicehub) -> UserClient: with app.app_context(): password = 'foo' user = create_user(password=password) - client = UserClient(application=app, - response_wrapper=app.response_class, - email=user.email, - password=password) - client.user, _ = client.login(client.email, client.password) + client = UserClient(app, user.email, password, response_wrapper=app.response_class) + client.login() return client def create_user(email='foo@foo.com', password='foo') -> User: user = User(email=email, password=password) + user.individuals.add(Person(name='Timmy')) db.session.add(user) db.session.commit() return user diff --git a/tests/files/1-device-with-components.snapshot.yaml b/tests/files/1-device-with-components.snapshot.yaml index 25148514..97b0dc98 100644 --- a/tests/files/1-device-with-components.snapshot.yaml +++ b/tests/files/1-device-with-components.snapshot.yaml @@ -5,20 +5,20 @@ device: type: Desktop chassis: Tower components: - - manufacturer: p1c1m - serialNumber: p1c1s - type: Motherboard - - manufacturer: p1c2m - serialNumber: p1c2s - model: p1c2 - speed: 1.23 - cores: 2 - type: Processor - - manufacturer: p1c3m - serialNumber: p1c3s - type: GraphicCard - memory: 1.5 +- manufacturer: p1c1m + serialNumber: p1c1s + type: Motherboard +- manufacturer: p1c2m + serialNumber: p1c2s + model: p1c2 + speed: 1.23 + cores: 2 + type: Processor +- manufacturer: p1c3m + serialNumber: p1c3s + type: GraphicCard + memory: 1.5 elapsed: 25 software: Workbench uuid: 76860eca-c3fd-41f6-a801-6af7bd8cf832 -version: '11.0' \ No newline at end of file +version: '11.0' diff --git a/tests/files/2-second-device-with-components-of-first.snapshot.yaml b/tests/files/2-second-device-with-components-of-first.snapshot.yaml index f887452f..5062da56 100644 --- a/tests/files/2-second-device-with-components-of-first.snapshot.yaml +++ b/tests/files/2-second-device-with-components-of-first.snapshot.yaml @@ -5,16 +5,16 @@ device: type: Desktop chassis: Microtower components: - - manufacturer: p2c1m - serialNumber: p2c1s - type: Motherboard - - manufacturer: p1c2m - serialNumber: p1c2s - model: p1c2 - speed: 1.23 - cores: 2 - type: Processor +- manufacturer: p2c1m + serialNumber: p2c1s + type: Motherboard +- manufacturer: p1c2m + serialNumber: p1c2s + model: p1c2 + speed: 1.23 + cores: 2 + type: Processor elapsed: 25 software: Workbench uuid: f2e02261-87a1-4a50-b9b7-92c0e476e5f2 -version: '11.0' \ No newline at end of file +version: '11.0' diff --git a/tests/files/3-first-device-but-removing-motherboard-and-adding-processor-from-2.snapshot.yaml b/tests/files/3-first-device-but-removing-motherboard-and-adding-processor-from-2.snapshot.yaml index 2fb43684..bdf72b37 100644 --- a/tests/files/3-first-device-but-removing-motherboard-and-adding-processor-from-2.snapshot.yaml +++ b/tests/files/3-first-device-but-removing-motherboard-and-adding-processor-from-2.snapshot.yaml @@ -5,17 +5,17 @@ device: type: Desktop chassis: Microtower components: - - manufacturer: p1c2m - serialNumber: p1c2s - model: p1c2 - type: Processor - cores: 2 - speed: 1.23 - - manufacturer: p1c3m - serialNumber: p1c3s - type: GraphicCard - memory: 1.5 +- manufacturer: p1c2m + serialNumber: p1c2s + model: p1c2 + type: Processor + cores: 2 + speed: 1.23 +- manufacturer: p1c3m + serialNumber: p1c3s + type: GraphicCard + memory: 1.5 elapsed: 30 software: Workbench uuid: 3be271b6-5ef4-47d8-8237-5e1133eebfc6 -version: '11.0' \ No newline at end of file +version: '11.0' diff --git a/tests/files/4-first-device-but-removing-processor.snapshot-and-adding-graphic-card.yaml b/tests/files/4-first-device-but-removing-processor.snapshot-and-adding-graphic-card.yaml index 2a648269..463f9b20 100644 --- a/tests/files/4-first-device-but-removing-processor.snapshot-and-adding-graphic-card.yaml +++ b/tests/files/4-first-device-but-removing-processor.snapshot-and-adding-graphic-card.yaml @@ -5,16 +5,16 @@ device: type: Desktop chassis: Tower components: - - manufacturer: p1c4m - serialNumber: p1c4s - type: NetworkAdapter - speed: 1000 - wireless: False - - manufacturer: p1c3m - serialNumber: p1c3s - type: GraphicCard - memory: 1.5 +- manufacturer: p1c4m + serialNumber: p1c4s + type: NetworkAdapter + speed: 1000 + wireless: False +- manufacturer: p1c3m + serialNumber: p1c3s + type: GraphicCard + memory: 1.5 elapsed: 25 software: Workbench uuid: fd007eb4-48e3-454a-8763-169491904c6e -version: '11.0' \ No newline at end of file +version: '11.0' diff --git a/tests/files/basic.snapshot.yaml b/tests/files/basic.snapshot.yaml index 4342d40f..3adc8d9d 100644 --- a/tests/files/basic.snapshot.yaml +++ b/tests/files/basic.snapshot.yaml @@ -10,26 +10,26 @@ device: model: d1ml manufacturer: d1mr events: - - type: WorkbenchRate - appearanceRange: A - functionalityRange: B - labelling: True - bios: B + - type: WorkbenchRate + appearanceRange: A + functionalityRange: B + labelling: True + bios: B components: - - type: GraphicCard - serialNumber: gc1s - model: gc1ml - manufacturer: gc1mr - - type: RamModule - serialNumber: rm1s - model: rm1ml - manufacturer: rm1mr - speed: 1333 - - type: Processor - serialNumber: p1s - model: p1ml - manufacturer: p1mr - speed: 1.6 - events: - - type: BenchmarkProcessor - rate: 2410 \ No newline at end of file +- type: GraphicCard + serialNumber: gc1s + model: gc1ml + manufacturer: gc1mr +- type: RamModule + serialNumber: rm1s + model: rm1ml + manufacturer: rm1mr + speed: 1333 +- type: Processor + serialNumber: p1s + model: p1ml + manufacturer: p1mr + speed: 1.6 + events: + - type: BenchmarkProcessor + rate: 2410 diff --git a/tests/files/computer-monitor.snapshot.yaml b/tests/files/computer-monitor.snapshot.yaml index aefc5817..c4988cf8 100644 --- a/tests/files/computer-monitor.snapshot.yaml +++ b/tests/files/computer-monitor.snapshot.yaml @@ -11,7 +11,7 @@ device: resolutionHeight: 1080 size: 21.5 events: - - type: AppRate - appearanceRange: A - functionalityRange: C - labelling: False + - type: AppRate + appearanceRange: A + functionalityRange: C + labelling: False diff --git a/tests/files/erase-sectors-2-hdd.snapshot.yaml b/tests/files/erase-sectors-2-hdd.snapshot.yaml index 434da508..0fd43f8a 100644 --- a/tests/files/erase-sectors-2-hdd.snapshot.yaml +++ b/tests/files/erase-sectors-2-hdd.snapshot.yaml @@ -18,139 +18,139 @@ "EraseBasic" ], "components": [ + { + "serialNumber": null, + "threads": 2, + "manufacturer": "Intel Corp.", + "address": 64, + "model": "Intel Core i3-2100 CPU @ 3.10GHz", + "type": "Processor", + "events": [], + "cores": 2, + "speed": 1.6071410000000002 + }, + { + "manufacturer": "Intel Corporation", + "model": "6 Series/C200 Series Chipset Family High Definition Audio Controller", + "type": "SoundCard", + "events": [], + "serialNumber": null + }, + { + "serialNumber": "8F17943", + "size": 4096, + "manufacturer": "Kingston", + "format": "DIMM", + "model": "9905403-038.A00LF", + "type": "RamModule", + "events": [], + "interface": "DDR3", + "speed": 1333.0 + }, + { + "manufacturer": "Realtek Semiconductor Co., Ltd.", + "model": "RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller", + "type": "NetworkAdapter", + "events": [], + "serialNumber": "f4:6d:04:12:9b:85", + "speed": 1000 + }, + { + "serialNumber": "WD-WCAV29008961", + "size": 305245, + "manufacturer": "Western Digital", + "model": "WDC WD3200AAJS-2", + "type": "HardDrive", + "events": [ { - "serialNumber": null, - "threads": 2, - "manufacturer": "Intel Corp.", - "address": 64, - "model": "Intel Core i3-2100 CPU @ 3.10GHz", - "type": "Processor", - "events": [], - "cores": 2, - "speed": 1.6071410000000002 - }, - { - "manufacturer": "Intel Corporation", - "model": "6 Series/C200 Series Chipset Family High Definition Audio Controller", - "type": "SoundCard", - "events": [], - "serialNumber": null - }, - { - "serialNumber": "8F17943", - "size": 4096, - "manufacturer": "Kingston", - "format": "DIMM", - "model": "9905403-038.A00LF", - "type": "RamModule", - "events": [], - "interface": "DDR3", - "speed": 1333.0 - }, - { - "manufacturer": "Realtek Semiconductor Co., Ltd.", - "model": "RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller", - "type": "NetworkAdapter", - "events": [], - "serialNumber": "f4:6d:04:12:9b:85", - "speed": 1000 - }, - { - "serialNumber": "WD-WCAV29008961", - "size": 305245, - "manufacturer": "Western Digital", - "model": "WDC WD3200AAJS-2", - "type": "HardDrive", - "events": [ - { - "endTime": "2018-07-13T11:54:55.100581", - "steps": [ - { - "endTime": "2018-07-13T11:54:55.096491", - "type": "StepRandom", - "error": false, - "startTime": "2018-07-13T10:52:45.092981" - } - ], - "type": "EraseBasic", - "error": false, - "zeros": false, - "startTime": "2018-07-13T10:52:45.092612" - }, - { - "lifetime": 24658, - "assessment": false, - "elapsed": 131, - "length": "Short", - "offlineUncorrectable": 1, - "error": true, - "currentPendingSectorCount": 1, - "powerCycleCount": 1253, - "reallocatedSectorCount": 6, - "type": "TestDataStorage", - "status": "Completed: read failure" - } + "endTime": "2018-07-13T11:54:55.100581", + "steps": [ + { + "endTime": "2018-07-13T11:54:55.096491", + "type": "StepRandom", + "error": false, + "startTime": "2018-07-13T10:52:45.092981" + } ], - "interface": "ATA" + "type": "EraseBasic", + "error": false, + "zeros": false, + "startTime": "2018-07-13T10:52:45.092612" }, { - "serialNumber": "WD-WCAV27984668", - "size": 305245, - "manufacturer": "Western Digital", - "model": "WDC WD3200AAJS-0", - "type": "HardDrive", - "events": [ - { - "endTime": "2018-07-13T12:55:47.331586", - "steps": [ - { - "endTime": "2018-07-13T12:55:47.326835", - "type": "StepRandom", - "error": false, - "startTime": "2018-07-13T11:54:55.100925" - } - ], - "type": "EraseBasic", - "error": false, - "zeros": false, - "startTime": "2018-07-13T11:54:55.100667" - }, - { - "lifetime": 21979, - "assessment": true, - "elapsed": 115, - "length": "Short", - "offlineUncorrectable": 0, - "error": false, - "currentPendingSectorCount": 0, - "powerCycleCount": 1956, - "reallocatedSectorCount": 0, - "type": "TestDataStorage", - "status": "Completed without error" - } - ], - "interface": "ATA" - }, - { - "serialNumber": null, - "manufacturer": "Intel Corporation", - "model": "2nd Generation Core Processor Family Integrated Graphics Controller", - "type": "GraphicCard", - "events": [], - "memory": 256.0 - }, - { - "pcmcia": 0, - "serial": 1, - "manufacturer": "ASUSTeK Computer INC.", - "model": "P8H61-M LE", - "type": "Motherboard", - "events": [], - "slots": 2, - "usb": 2, - "firewire": 0, - "serialNumber": "109192430003459" + "lifetime": 24658, + "assessment": false, + "elapsed": 131, + "length": "Short", + "offlineUncorrectable": 1, + "error": true, + "currentPendingSectorCount": 1, + "powerCycleCount": 1253, + "reallocatedSectorCount": 6, + "type": "TestDataStorage", + "status": "Completed: read failure" } + ], + "interface": "ATA" + }, + { + "serialNumber": "WD-WCAV27984668", + "size": 305245, + "manufacturer": "Western Digital", + "model": "WDC WD3200AAJS-0", + "type": "HardDrive", + "events": [ + { + "endTime": "2018-07-13T12:55:47.331586", + "steps": [ + { + "endTime": "2018-07-13T12:55:47.326835", + "type": "StepRandom", + "error": false, + "startTime": "2018-07-13T11:54:55.100925" + } + ], + "type": "EraseBasic", + "error": false, + "zeros": false, + "startTime": "2018-07-13T11:54:55.100667" + }, + { + "lifetime": 21979, + "assessment": true, + "elapsed": 115, + "length": "Short", + "offlineUncorrectable": 0, + "error": false, + "currentPendingSectorCount": 0, + "powerCycleCount": 1956, + "reallocatedSectorCount": 0, + "type": "TestDataStorage", + "status": "Completed without error" + } + ], + "interface": "ATA" + }, + { + "serialNumber": null, + "manufacturer": "Intel Corporation", + "model": "2nd Generation Core Processor Family Integrated Graphics Controller", + "type": "GraphicCard", + "events": [], + "memory": 256.0 + }, + { + "pcmcia": 0, + "serial": 1, + "manufacturer": "ASUSTeK Computer INC.", + "model": "P8H61-M LE", + "type": "Motherboard", + "events": [], + "slots": 2, + "usb": 2, + "firewire": 0, + "serialNumber": "109192430003459" + } ], - "date": "2018-07-13T10:48:36.738398" -} \ No newline at end of file + "endTime": "2018-07-13T10:48:36.738398" +} diff --git a/tests/files/erase-sectors.snapshot.yaml b/tests/files/erase-sectors.snapshot.yaml index e8887216..d0cd5a1b 100644 --- a/tests/files/erase-sectors.snapshot.yaml +++ b/tests/files/erase-sectors.snapshot.yaml @@ -10,29 +10,29 @@ device: model: pc1ml manufacturer: pc1mr components: - - type: SolidStateDrive - serialNumber: c1s - model: c1ml - manufacturer: c1mr - events: - - type: EraseSectors - zeros: True - startTime: 2018-06-01T08:12:06 - endTime: 2018-06-01T09:12:06 - steps: - - type: StepZero - error: False - startTime: 2018-06-01T08:15:00 - endTime: 2018-06-01T09:16:00 - - type: StepZero - error: False - startTime: 2018-06-01T08:16:00 - endTime: 2018-06-01T09:17:00 - - type: Processor - serialNumber: p1s - model: p1ml - manufacturer: p1mr - - type: RamModule - serialNumber: rm1s - model: rm1ml - manufacturer: rm1mr +- type: SolidStateDrive + serialNumber: c1s + model: c1ml + manufacturer: c1mr + events: + - type: EraseSectors + zeros: True + startTime: 2018-06-01T08:12:06 + endTime: 2018-06-01T09:12:06 + steps: + - type: StepZero + error: False + startTime: 2018-06-01T08:15:00 + endTime: 2018-06-01T09:16:00 + - type: StepZero + error: False + startTime: 2018-06-01T08:16:00 + endTime: 2018-06-01T09:17:00 +- type: Processor + serialNumber: p1s + model: p1ml + manufacturer: p1mr +- type: RamModule + serialNumber: rm1s + model: rm1ml + manufacturer: rm1mr diff --git a/tests/files/pc-components.db.yaml b/tests/files/pc-components.db.yaml index c3c9d9ec..8d3efa48 100644 --- a/tests/files/pc-components.db.yaml +++ b/tests/files/pc-components.db.yaml @@ -5,11 +5,11 @@ device: model: d1ml manufacturer: d1mr components: - - type: GraphicCard - serial_number: gc1s - model: gc1ml - manufacturer: gc1mr - - type: RamModule - serial_number: rm1s - model: rm1ml - manufacturer: rm1mr +- type: GraphicCard + serial_number: gc1s + model: gc1ml + manufacturer: gc1mr +- type: RamModule + serial_number: rm1s + model: rm1ml + manufacturer: rm1mr diff --git a/tests/files/real-custom.snapshot.11.yaml b/tests/files/real-custom.snapshot.11.yaml index b9d9235e..a9ac2697 100644 --- a/tests/files/real-custom.snapshot.11.yaml +++ b/tests/files/real-custom.snapshot.11.yaml @@ -7,113 +7,113 @@ ], "uuid": "16467238-64bb-48e0-9058-0cba687d7db0", "components": [ + { + "events": [], + "type": "NetworkAdapter", + "speed": 1000, + "wireless": false, + "manufacturer": "Marvell Technology Group Ltd.", + "serialNumber": "e0:cb:4e:0b:e4:11", + "model": "88E8056 PCI-E Gigabit Ethernet Controller" + }, + { + "events": [ { - "events": [], - "type": "NetworkAdapter", - "speed": 1000, - "wireless": false, - "manufacturer": "Marvell Technology Group Ltd.", - "serialNumber": "e0:cb:4e:0b:e4:11", - "model": "88E8056 PCI-E Gigabit Ethernet Controller" + "rate": 4.8652, + "elapsed": 5, + "type": "BenchmarkProcessorSysbench" }, { - "events": [ - { - "rate": 4.8652, - "elapsed": 5, - "type": "BenchmarkProcessorSysbench" - }, - { - "rate": 56928.88, - "elapsed": 0, - "type": "BenchmarkProcessor" - } - ], - "type": "Processor", - "speed": 1.6, - "manufacturer": "Intel Corp.", - "serialNumber": null, - "cores": 4, - "threads": 8, - "model": "Intel Core i7 CPU 920 @ 2.67GHz", - "address": 64 - }, - { - "events": [], - "type": "SoundCard", - "manufacturer": "Advanced Micro Devices, Inc. AMD/ATI", - "serialNumber": null, - "model": "Barts HDMI Audio Radeon HD 6790/6850/6870 / 7720" - }, - { - "events": [], - "type": "SoundCard", - "manufacturer": "Intel Corporation", - "serialNumber": null, - "model": "82801JI HD Audio Controller" - }, - { - "events": [], - "type": "GraphicCard", - "memory": 256.0, - "manufacturer": "Advanced Micro Devices, Inc. AMD/ATI", - "serialNumber": null, - "model": "Barts XT Radeon HD 6870" - }, - { - "events": [ - { - "elapsed": 2, - "type": "BenchmarkDataStorage", - "writeSpeed": 151.0, - "readSpeed": 7270.4 - }, - { - "remainingLifetimePercentage": 98, - "assessment": true, - "reallocatedSectorCount": 0, - "elapsed": 54, - "type": "TestDataStorage", - "status": "Self-test routine in progress", - "powerCycleCount": 648, - "length": "Short", - "error": false, - "lifetime": 202 - } - ], - "type": "SolidStateDrive", - "interface": "ATA", - "manufacturer": null, - "serialNumber": "1609F017A70F", - "model": "CT240BX200SSD1", - "size": 228936 - }, - { - "events": [], - "type": "Motherboard", - "slots": 6, - "pcmcia": 0, - "manufacturer": "ASUSTeK Computer INC.", - "serialNumber": "102743030000221", - "serial": 1, - "firewire": 0, - "model": "P6T DELUXE V2", - "usb": 9 + "rate": 56928.88, + "elapsed": 0, + "type": "BenchmarkProcessor" } + ], + "type": "Processor", + "speed": 1.6, + "manufacturer": "Intel Corp.", + "serialNumber": null, + "cores": 4, + "threads": 8, + "model": "Intel Core i7 CPU 920 @ 2.67GHz", + "address": 64 + }, + { + "events": [], + "type": "SoundCard", + "manufacturer": "Advanced Micro Devices, Inc. AMD/ATI", + "serialNumber": null, + "model": "Barts HDMI Audio Radeon HD 6790/6850/6870 / 7720" + }, + { + "events": [], + "type": "SoundCard", + "manufacturer": "Intel Corporation", + "serialNumber": null, + "model": "82801JI HD Audio Controller" + }, + { + "events": [], + "type": "GraphicCard", + "memory": 256.0, + "manufacturer": "Advanced Micro Devices, Inc. AMD/ATI", + "serialNumber": null, + "model": "Barts XT Radeon HD 6870" + }, + { + "events": [ + { + "elapsed": 2, + "type": "BenchmarkDataStorage", + "writeSpeed": 151.0, + "readSpeed": 7270.4 + }, + { + "remainingLifetimePercentage": 98, + "assessment": true, + "reallocatedSectorCount": 0, + "elapsed": 54, + "type": "TestDataStorage", + "status": "Self-test routine in progress", + "powerCycleCount": 648, + "length": "Short", + "error": false, + "lifetime": 202 + } + ], + "type": "SolidStateDrive", + "interface": "ATA", + "manufacturer": null, + "serialNumber": "1609F017A70F", + "model": "CT240BX200SSD1", + "size": 228936 + }, + { + "events": [], + "type": "Motherboard", + "slots": 6, + "pcmcia": 0, + "manufacturer": "ASUSTeK Computer INC.", + "serialNumber": "102743030000221", + "serial": 1, + "firewire": 0, + "model": "P6T DELUXE V2", + "usb": 9 + } ], "elapsed": 7339, "device": { "events": [ - { - "rate": 16.5946, - "elapsed": 17, - "type": "BenchmarkRamSysbench" - }, - { - "error": false, - "elapsed": 60, - "type": "StressTest" - } + { + "rate": 16.5946, + "elapsed": 17, + "type": "BenchmarkRamSysbench" + }, + { + "error": false, + "elapsed": 60, + "type": "StressTest" + } ], "type": "Desktop", "manufacturer": null, @@ -123,6 +123,6 @@ }, "type": "Snapshot", "software": "Workbench", - "date": "2018-07-19T15:48:40.635776", + "endTime": "2018-07-19T15:48:40.635776", "closed": false -} \ No newline at end of file +} diff --git a/tests/files/real-eee-1001pxd.snapshot.11.yaml b/tests/files/real-eee-1001pxd.snapshot.11.yaml index b924ac06..47bf9d8f 100644 --- a/tests/files/real-eee-1001pxd.snapshot.11.yaml +++ b/tests/files/real-eee-1001pxd.snapshot.11.yaml @@ -1,134 +1,134 @@ { "components": [ + { + "type": "NetworkAdapter", + "model": "AR9285 Wireless Network Adapter", + "serialNumber": "74:2f:68:8b:fd:c8", + "manufacturer": "Qualcomm Atheros", + "wireless": true, + "events": [] + }, + { + "type": "NetworkAdapter", + "model": "AR8152 v2.0 Fast Ethernet", + "serialNumber": "14:da:e9:42:f6:7c", + "manufacturer": "Qualcomm Atheros", + "speed": 100, + "wireless": false, + "events": [] + }, + { + "type": "Processor", + "cores": 1, + "threads": 1, + "address": 64, + "model": "Intel Atom CPU N455 @ 1.66GHz", + "serialNumber": null, + "manufacturer": "Intel Corp.", + "speed": 1.667, + "events": [ { - "type": "NetworkAdapter", - "model": "AR9285 Wireless Network Adapter", - "serialNumber": "74:2f:68:8b:fd:c8", - "manufacturer": "Qualcomm Atheros", - "wireless": true, - "events": [] + "type": "BenchmarkProcessorSysbench", + "rate": 164.0803, + "elapsed": 164 }, { - "type": "NetworkAdapter", - "model": "AR8152 v2.0 Fast Ethernet", - "serialNumber": "14:da:e9:42:f6:7c", - "manufacturer": "Qualcomm Atheros", - "speed": 100, - "wireless": false, - "events": [] - }, - { - "type": "Processor", - "cores": 1, - "threads": 1, - "address": 64, - "model": "Intel Atom CPU N455 @ 1.66GHz", - "serialNumber": null, - "manufacturer": "Intel Corp.", - "speed": 1.667, - "events": [ - { - "type": "BenchmarkProcessorSysbench", - "rate": 164.0803, - "elapsed": 164 - }, - { - "type": "BenchmarkProcessor", - "rate": 6666.24, - "elapsed": 0 - } - ] - }, - { - "type": "GraphicCard", - "model": "Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller", - "serialNumber": null, - "memory": 256.0, - "manufacturer": "Intel Corporation", - "events": [] - }, - { - "type": "SoundCard", - "model": "NM10/ICH7 Family High Definition Audio Controller", - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [] - }, - { - "type": "SoundCard", - "model": "USB 2.0 UVC VGA WebCam", - "serialNumber": "0x0001", - "manufacturer": "Azurewave", - "events": [] - }, - { - "type": "RamModule", - "format": "DIMM", - "model": null, - "size": 1024, - "interface": "DDR2", - "serialNumber": null, - "manufacturer": null, - "speed": 667.0, - "events": [] - }, - { - "type": "HardDrive", - "model": "HTS54322", - "size": 238475, - "interface": "ATA", - "serialNumber": "E2024242CV86HJ", - "manufacturer": "Hitachi", - "events": [ - { - "type": "BenchmarkDataStorage", - "elapsed": 16, - "writeSpeed": 21.8, - "readSpeed": 66.2 - }, - { - "type": "TestDataStorage", - "length": "Short", - "elapsed": 2, - "error": true, - "status": "Unspecified Error. Self-test not started." - }, - { - "type": "EraseBasic", - "steps": [ - { - "type": "StepRandom", - "startTime": "2018-07-03T09:15:22.257059", - "error": false, - "endTime": "2018-07-03T10:32:11.843190" - } - ], - "startTime": "2018-07-03T09:15:22.256074", - "error": false, - "zeros": false, - "endTime": "2018-07-03T10:32:11.848455" - } - ] - }, - { - "type": "Motherboard", - "serial": 1, - "firewire": 0, - "model": "1001PXD", - "slots": 2, - "pcmcia": 0, - "serialNumber": "Eee0123456789", - "usb": 5, - "manufacturer": "ASUSTeK Computer INC.", - "events": [] + "type": "BenchmarkProcessor", + "rate": 6666.24, + "elapsed": 0 } + ] + }, + { + "type": "GraphicCard", + "model": "Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller", + "serialNumber": null, + "memory": 256.0, + "manufacturer": "Intel Corporation", + "events": [] + }, + { + "type": "SoundCard", + "model": "NM10/ICH7 Family High Definition Audio Controller", + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [] + }, + { + "type": "SoundCard", + "model": "USB 2.0 UVC VGA WebCam", + "serialNumber": "0x0001", + "manufacturer": "Azurewave", + "events": [] + }, + { + "type": "RamModule", + "format": "DIMM", + "model": null, + "size": 1024, + "interface": "DDR2", + "serialNumber": null, + "manufacturer": null, + "speed": 667.0, + "events": [] + }, + { + "type": "HardDrive", + "model": "HTS54322", + "size": 238475, + "interface": "ATA", + "serialNumber": "E2024242CV86HJ", + "manufacturer": "Hitachi", + "events": [ + { + "type": "BenchmarkDataStorage", + "elapsed": 16, + "writeSpeed": 21.8, + "readSpeed": 66.2 + }, + { + "type": "TestDataStorage", + "length": "Short", + "elapsed": 2, + "error": true, + "status": "Unspecified Error. Self-test not started." + }, + { + "type": "EraseBasic", + "steps": [ + { + "type": "StepRandom", + "startTime": "2018-07-03T09:15:22.257059", + "error": false, + "endTime": "2018-07-03T10:32:11.843190" + } + ], + "startTime": "2018-07-03T09:15:22.256074", + "error": false, + "zeros": false, + "endTime": "2018-07-03T10:32:11.848455" + } + ] + }, + { + "type": "Motherboard", + "serial": 1, + "firewire": 0, + "model": "1001PXD", + "slots": 2, + "pcmcia": 0, + "serialNumber": "Eee0123456789", + "usb": 5, + "manufacturer": "ASUSTeK Computer INC.", + "events": [] + } ], "elapsed": 4875, "uuid": "c058e8d2-fb92-47cb-a4b7-522b75561135", "version": "11.0a2", "type": "Snapshot", "software": "Workbench", - "date": "2018-07-03T09:10:57.034598", + "endTime": "2018-07-03T09:10:57.034598", "device": { "type": "Laptop", "model": "1001PXD", @@ -136,16 +136,16 @@ "manufacturer": "ASUSTeK Computer INC.", "chassis": "Netbook", "events": [ - { - "type": "BenchmarkRamSysbench", - "rate": 15.7188, - "elapsed": 16 - }, - { - "type": "StressTest", - "error": false, - "elapsed": 60 - } + { + "type": "BenchmarkRamSysbench", + "rate": 15.7188, + "elapsed": 16 + }, + { + "type": "StressTest", + "error": false, + "elapsed": 60 + } ] }, "expectedEvents": [ @@ -155,4 +155,4 @@ "EraseBasic" ], "closed": false -} \ No newline at end of file +} diff --git a/tests/files/real-hp-quad-core.snapshot.11.yaml b/tests/files/real-hp-quad-core.snapshot.11.yaml index 5cd33be3..86a38a0c 100644 --- a/tests/files/real-hp-quad-core.snapshot.11.yaml +++ b/tests/files/real-hp-quad-core.snapshot.11.yaml @@ -4,102 +4,102 @@ "uuid": "0c822fb7-6e51-4781-86cf-994bd306212e", "software": "Workbench", "closed": false, - "date": "2018-07-05T11:57:17.284891", + "endTime": "2018-07-05T11:57:17.284891", "components": [ + { + "type": "NetworkAdapter", + "model": "82567LM-3 Gigabit Network Connection", + "speed": 1000, + "serialNumber": "00:23:24:0d:86:28", + "manufacturer": "Intel Corporation", + "wireless": false, + "events": [] + }, + { + "type": "NetworkAdapter", + "model": "82541PI Gigabit Ethernet Controller", + "speed": 1000, + "serialNumber": "00:0e:0c:b6:f2:91", + "manufacturer": "Intel Corporation", + "wireless": false, + "events": [] + }, + { + "cores": 4, + "type": "Processor", + "model": "Intel Core2 Quad CPU Q8400 @ 2.66GHz", + "speed": 1.9980000000000002, + "serialNumber": null, + "manufacturer": "Intel Corp.", + "events": [], + "address": 64 + }, + { + "type": "GraphicCard", + "model": "4 Series Chipset Integrated Graphics Controller", + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [], + "memory": 256.0 + }, + { + "type": "SoundCard", + "model": "82801JD/DO HD Audio Controller", + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [] + }, + { + "size": 2048, + "interface": "DDR3", + "type": "RamModule", + "model": "16JTF25664AZ-1G4F", + "speed": 1333.0, + "serialNumber": "F8482E29", + "format": "DIMM", + "manufacturer": "JEDEC ID:80 2C", + "events": [] + }, + { + "size": 2048, + "interface": "DDR3", + "type": "RamModule", + "model": "16JTF25664AZ-1G4F", + "speed": 1333.0, + "serialNumber": "62072F30", + "format": "DIMM", + "manufacturer": "JEDEC ID:80 2C", + "events": [] + }, + { + "size": 238475, + "interface": "ATA", + "type": "HardDrive", + "model": "ST3250318AS", + "serialNumber": "9VY6HBKE", + "manufacturer": "Seagate", + "events": [ { - "type": "NetworkAdapter", - "model": "82567LM-3 Gigabit Network Connection", - "speed": 1000, - "serialNumber": "00:23:24:0d:86:28", - "manufacturer": "Intel Corporation", - "wireless": false, - "events": [] - }, - { - "type": "NetworkAdapter", - "model": "82541PI Gigabit Ethernet Controller", - "speed": 1000, - "serialNumber": "00:0e:0c:b6:f2:91", - "manufacturer": "Intel Corporation", - "wireless": false, - "events": [] - }, - { - "cores": 4, - "type": "Processor", - "model": "Intel Core2 Quad CPU Q8400 @ 2.66GHz", - "speed": 1.9980000000000002, - "serialNumber": null, - "manufacturer": "Intel Corp.", - "events": [], - "address": 64 - }, - { - "type": "GraphicCard", - "model": "4 Series Chipset Integrated Graphics Controller", - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [], - "memory": 256.0 - }, - { - "type": "SoundCard", - "model": "82801JD/DO HD Audio Controller", - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [] - }, - { - "size": 2048, - "interface": "DDR3", - "type": "RamModule", - "model": "16JTF25664AZ-1G4F", - "speed": 1333.0, - "serialNumber": "F8482E29", - "format": "DIMM", - "manufacturer": "JEDEC ID:80 2C", - "events": [] - }, - { - "size": 2048, - "interface": "DDR3", - "type": "RamModule", - "model": "16JTF25664AZ-1G4F", - "speed": 1333.0, - "serialNumber": "62072F30", - "format": "DIMM", - "manufacturer": "JEDEC ID:80 2C", - "events": [] - }, - { - "size": 238475, - "interface": "ATA", - "type": "HardDrive", - "model": "ST3250318AS", - "serialNumber": "9VY6HBKE", - "manufacturer": "Seagate", - "events": [ - { - "elapsed": 0, - "type": "TestDataStorage", - "status": "Unspecified Error. Self-test not started.", - "error": true, - "length": "Short" - } - ] - }, - { - "slots": 0, - "pcmcia": 0, - "type": "Motherboard", - "model": "3646h", - "serialNumber": "CZC03217S7", - "firewire": 0, - "manufacturer": "Hewlett-Packard", - "events": [], - "serial": 0, - "usb": 8 + "elapsed": 0, + "type": "TestDataStorage", + "status": "Unspecified Error. Self-test not started.", + "error": true, + "length": "Short" } + ] + }, + { + "slots": 0, + "pcmcia": 0, + "type": "Motherboard", + "model": "3646h", + "serialNumber": "CZC03217S7", + "firewire": 0, + "manufacturer": "Hewlett-Packard", + "events": [], + "serial": 0, + "usb": 8 + } ], "version": "11.0a3", "device": { @@ -113,4 +113,4 @@ "expectedEvents": [ "SmartTest" ] -} \ No newline at end of file +} diff --git a/tests/files/real-hp.snapshot.11.yaml b/tests/files/real-hp.snapshot.11.yaml index c4eadc08..b360e15d 100644 --- a/tests/files/real-hp.snapshot.11.yaml +++ b/tests/files/real-hp.snapshot.11.yaml @@ -2,132 +2,132 @@ "closed": false, "uuid": "f9e5e587-baee-44e1-9a94-255d216bbda9", "components": [ + { + "events": [], + "serialNumber": "6c:62:6d:81:22:9f", + "type": "NetworkAdapter", + "manufacturer": "Intel Corporation", + "speed": 1000, + "wireless": false, + "model": "82578DM Gigabit Network Connection" + }, + { + "format": "DIMM", + "events": [ + ], + "interface": "DDR3", + "serialNumber": "B4012F30", + "size": 2048, + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "speed": 1333.0, + "model": "16JTF25664AZ-1G4F" + }, + { + "format": "DIMM", + "events": [], + "interface": "DDR3", + "serialNumber": "8E9F2E29", + "size": 2048, + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "speed": 1333.0, + "model": "16JTF25664AZ-1G4F" + }, + { + "format": "DIMM", + "events": [], + "interface": "DDR3", + "serialNumber": "9A012F30", + "size": 2048, + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "speed": 1333.0, + "model": "16JTF25664AZ-1G4F" + }, + { + "format": "DIMM", + "events": [ + ], + "interface": "DDR3", + "serialNumber": "8F9F2E29", + "size": 2048, + "type": "RamModule", + "manufacturer": "JEDEC ID:80 2C", + "speed": 1333.0, + "model": "16JTF25664AZ-1G4F" + }, + { + "cores": 2, + "events": [ { - "events": [], - "serialNumber": "6c:62:6d:81:22:9f", - "type": "NetworkAdapter", - "manufacturer": "Intel Corporation", - "speed": 1000, - "wireless": false, - "model": "82578DM Gigabit Network Connection" + "rate": 23410.76, + "type": "BenchmarkProcessor", + "elapsed": 1 }, { - "format": "DIMM", - "events": [ - ], - "interface": "DDR3", - "serialNumber": "B4012F30", - "size": 2048, - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "speed": 1333.0, - "model": "16JTF25664AZ-1G4F" - }, - { - "format": "DIMM", - "events": [], - "interface": "DDR3", - "serialNumber": "8E9F2E29", - "size": 2048, - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "speed": 1333.0, - "model": "16JTF25664AZ-1G4F" - }, - { - "format": "DIMM", - "events": [], - "interface": "DDR3", - "serialNumber": "9A012F30", - "size": 2048, - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "speed": 1333.0, - "model": "16JTF25664AZ-1G4F" - }, - { - "format": "DIMM", - "events": [ - ], - "interface": "DDR3", - "serialNumber": "8F9F2E29", - "size": 2048, - "type": "RamModule", - "manufacturer": "JEDEC ID:80 2C", - "speed": 1333.0, - "model": "16JTF25664AZ-1G4F" - }, - { - "cores": 2, - "events": [ - { - "rate": 23410.76, - "type": "BenchmarkProcessor", - "elapsed": 1 - }, - { - "rate": 17.0186, - "type": "BenchmarkProcessorSysbench", - "elapsed": 18 - } - ], - "serialNumber": null, - "type": "Processor", - "manufacturer": "Intel Corp.", - "address": 64, - "speed": 1.199, - "model": "Intel Core i3 CPU 530 @ 2.93GHz" - }, - { - "events": [ - { - "writeSpeed": 24.5, - "readSpeed": 111.0, - "type": "BenchmarkDataStorage", - "elapsed": 14 - }, - { - "status": "Unspecified Error. Self-test not started.", - "error": true, - "type": "TestDataStorage", - "elapsed": 1, - "length": Short - } - ], - "interface": "ATA", - "serialNumber": "WD-WCAV2U909540", - "size": 305245, - "type": "HardDrive", - "manufacturer": "Western Digital", - "model": "WDC WD3200AAJS-6" - }, - { - "events": [], - "serialNumber": null, - "type": "SoundCard", - "manufacturer": "Intel Corporation", - "model": "5 Series/3400 Series Chipset High Definition Audio" - }, - { - "memory": 256.0, - "events": [], - "serialNumber": null, - "type": "GraphicCard", - "manufacturer": "Intel Corporation", - "model": "Core Processor Integrated Graphics Controller" - }, - { - "events": [], - "firewire": 0, - "pcmcia": 0, - "serialNumber": "CZC0408YJG", - "slots": 0, - "type": "Motherboard", - "manufacturer": "Hewlett-Packard", - "usb": 2, - "serial": 0, - "model": "304Ah" + "rate": 17.0186, + "type": "BenchmarkProcessorSysbench", + "elapsed": 18 } + ], + "serialNumber": null, + "type": "Processor", + "manufacturer": "Intel Corp.", + "address": 64, + "speed": 1.199, + "model": "Intel Core i3 CPU 530 @ 2.93GHz" + }, + { + "events": [ + { + "writeSpeed": 24.5, + "readSpeed": 111.0, + "type": "BenchmarkDataStorage", + "elapsed": 14 + }, + { + "status": "Unspecified Error. Self-test not started.", + "error": true, + "type": "TestDataStorage", + "elapsed": 1, + "length": Short + } + ], + "interface": "ATA", + "serialNumber": "WD-WCAV2U909540", + "size": 305245, + "type": "HardDrive", + "manufacturer": "Western Digital", + "model": "WDC WD3200AAJS-6" + }, + { + "events": [], + "serialNumber": null, + "type": "SoundCard", + "manufacturer": "Intel Corporation", + "model": "5 Series/3400 Series Chipset High Definition Audio" + }, + { + "memory": 256.0, + "events": [], + "serialNumber": null, + "type": "GraphicCard", + "manufacturer": "Intel Corporation", + "model": "Core Processor Integrated Graphics Controller" + }, + { + "events": [], + "firewire": 0, + "pcmcia": 0, + "serialNumber": "CZC0408YJG", + "slots": 0, + "type": "Motherboard", + "manufacturer": "Hewlett-Packard", + "usb": 2, + "serial": 0, + "model": "304Ah" + } ], "software": "Workbench", "elapsed": 96, @@ -139,16 +139,16 @@ ], "device": { "events": [ - { - "type": "StressTest", - "elapsed": 60, - "error": false - }, - { - "rate": 0.9759, - "type": "BenchmarkRamSysbench", - "elapsed": 1 - } + { + "type": "StressTest", + "elapsed": 60, + "error": false + }, + { + "rate": 0.9759, + "type": "BenchmarkRamSysbench", + "elapsed": 1 + } ], "serialNumber": "CZC0408YJG", "type": "Desktop", @@ -157,5 +157,5 @@ "model": "HP Compaq 8100 Elite SFF" }, "type": "Snapshot", - "date": "2018-06-29T12:28:54.508266" + "endTime": "2018-06-29T12:28:54.508266" } diff --git a/tests/files/real-toshiba.snapshot.11.yaml b/tests/files/real-toshiba.snapshot.11.yaml index bb899521..1ea7be17 100644 --- a/tests/files/real-toshiba.snapshot.11.yaml +++ b/tests/files/real-toshiba.snapshot.11.yaml @@ -4,132 +4,132 @@ "Benchmark", "StressTest" ], - "date": "2018-06-29T15:29:29.322424", + "endTime": "2018-06-29T15:29:29.322424", "elapsed": 391, "software": "Workbench", "components": [ + { + "serialNumber": null, + "interface": "DDR", + "size": 1024, + "manufacturer": null, + "format": "SODIMM", + "events": [ + ], + "speed": 533.0, + "type": "RamModule", + "model": null + }, + { + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [], + "type": "SoundCard", + "model": "NM10/ICH7 Family High Definition Audio Controller" + }, + { + "serialNumber": null, + "manufacturer": "Chicony Electronics Co., Ltd.", + "events": [], + "type": "SoundCard", + "model": "USB2.0 UVC WebCam" + }, + { + "serialNumber": "00:23:08:a5:07:6d", + "manufacturer": "Qualcomm Atheros", + "events": [], + "type": "NetworkAdapter", + "wireless": true, + "model": "AR9285 Wireless Network Adapter" + }, + { + "serialNumber": "00:23:5a:fe:d7:14", + "manufacturer": "Realtek Semiconductor Co., Ltd.", + "events": [], + "speed": 100, + "type": "NetworkAdapter", + "wireless": false, + "model": "RTL810xE PCI Express Fast Ethernet controller" + }, + { + "serialNumber": null, + "address": 32, + "manufacturer": "Intel Corp.", + "events": [ { - "serialNumber": null, - "interface": "DDR", - "size": 1024, - "manufacturer": null, - "format": "SODIMM", - "events": [ - ], - "speed": 533.0, - "type": "RamModule", - "model": null + "rate": 171.3049, + "type": "BenchmarkProcessorSysbench", + "elapsed": 171 }, { - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [], - "type": "SoundCard", - "model": "NM10/ICH7 Family High Definition Audio Controller" - }, - { - "serialNumber": null, - "manufacturer": "Chicony Electronics Co., Ltd.", - "events": [], - "type": "SoundCard", - "model": "USB2.0 UVC WebCam" - }, - { - "serialNumber": "00:23:08:a5:07:6d", - "manufacturer": "Qualcomm Atheros", - "events": [], - "type": "NetworkAdapter", - "wireless": true, - "model": "AR9285 Wireless Network Adapter" - }, - { - "serialNumber": "00:23:5a:fe:d7:14", - "manufacturer": "Realtek Semiconductor Co., Ltd.", - "events": [], - "speed": 100, - "type": "NetworkAdapter", - "wireless": false, - "model": "RTL810xE PCI Express Fast Ethernet controller" - }, - { - "serialNumber": null, - "address": 32, - "manufacturer": "Intel Corp.", - "events": [ - { - "rate": 171.3049, - "type": "BenchmarkProcessorSysbench", - "elapsed": 171 - }, - { - "rate": 6383.9, - "type": "BenchmarkProcessor", - "elapsed": 1 - } - ], - "speed": 1.3330000000000002, - "type": "Processor", - "model": "Intel Atom CPU N270 @ 1.60GHz" - }, - { - "memory": 256.0, - "serialNumber": null, - "manufacturer": "Intel Corporation", - "events": [], - "type": "GraphicCard", - "model": "Mobile 945GSE Express Integrated Graphics Controller" - }, - { - "serialNumber": "090623PB5B00QCGREMAH", - "interface": "ATA", - "size": 152627, - "manufacturer": "Hitachi", - "events": [ - { - "elapsed": 71, - "readSpeed": 19.1, - "type": "BenchmarkDataStorage", - "writeSpeed": 4.7 - }, - { - "elapsed": 2, - "status": "Unspecified Error. Self-test not started.", - "type": "TestDataStorage", - "length": Short, - "error": true - } - ], - "type": "HardDrive", - "model": "HTS54501" - }, - { - "slots": 0, - "serialNumber": "0123456789AB", - "manufacturer": "TOSHIBA", - "firewire": 0, - "events": [], - "pcmcia": 0, - "usb": 5, - "serial": 1, - "type": "Motherboard", - "model": "KAVAA" + "rate": 6383.9, + "type": "BenchmarkProcessor", + "elapsed": 1 } + ], + "speed": 1.3330000000000002, + "type": "Processor", + "model": "Intel Atom CPU N270 @ 1.60GHz" + }, + { + "memory": 256.0, + "serialNumber": null, + "manufacturer": "Intel Corporation", + "events": [], + "type": "GraphicCard", + "model": "Mobile 945GSE Express Integrated Graphics Controller" + }, + { + "serialNumber": "090623PB5B00QCGREMAH", + "interface": "ATA", + "size": 152627, + "manufacturer": "Hitachi", + "events": [ + { + "elapsed": 71, + "readSpeed": 19.1, + "type": "BenchmarkDataStorage", + "writeSpeed": 4.7 + }, + { + "elapsed": 2, + "status": "Unspecified Error. Self-test not started.", + "type": "TestDataStorage", + "length": Short, + "error": true + } + ], + "type": "HardDrive", + "model": "HTS54501" + }, + { + "slots": 0, + "serialNumber": "0123456789AB", + "manufacturer": "TOSHIBA", + "firewire": 0, + "events": [], + "pcmcia": 0, + "usb": 5, + "serial": 1, + "type": "Motherboard", + "model": "KAVAA" + } ], "version": "11.0a1", "device": { "serialNumber": "79545417K", "manufacturer": "TOSHIBA", "events": [ - { - "type": "StressTest", - "error": false, - "elapsed": 120 - }, - { - "rate": 19.0443, - "type": "BenchmarkRamSysbench", - "elapsed": 19 - } + { + "type": "StressTest", + "error": false, + "elapsed": 120 + }, + { + "rate": 19.0443, + "type": "BenchmarkRamSysbench", + "elapsed": 19 + } ], "type": "Laptop", "chassis": "Netbook", diff --git a/tests/files/workbench-10.snapshot.yaml b/tests/files/workbench-10.snapshot.yaml index a057a10d..c336627e 100644 --- a/tests/files/workbench-10.snapshot.yaml +++ b/tests/files/workbench-10.snapshot.yaml @@ -15,9 +15,9 @@ components: serialNumber: null speed: 2.0 - {'@type': RamModule, manufacturer: null, model: null, serialNumber: null, size: 2048, - speed: 1067.0} + speed: 1067.0} - {'@type': RamModule, manufacturer: null, model: null, serialNumber: null, size: 2048, - speed: 1067.0} + speed: 1067.0} - '@type': HardDrive benchmark: {'@type': BenchmarkHardDrive, readingSpeed: 129.0, writingSpeed: 32.6} interface: 'ata @@ -28,12 +28,12 @@ components: serialNumber: 6VMB1A52 size: 238475 test: {'@type': TestHardDrive, CommandTimeout: 1786733725708, CurrentPendingSectorCount: 0, - OfflineUncorrectable: 0, assessment: true, error: false, firstError: null, lifetime: 16947, - passedLifetime: 16947, powerCycleCount: 1694, reallocatedSectorCount: 0, reportedUncorrectableErrors: 0, - status: Completed without error, type: Short offline} + OfflineUncorrectable: 0, assessment: true, error: false, firstError: null, lifetime: 16947, + passedLifetime: 16947, powerCycleCount: 1694, reallocatedSectorCount: 0, reportedUncorrectableErrors: 0, + status: Completed without error, type: Short offline} type: HDD -- {'@type': GraphicCard, manufacturer: Intel Corporation, memory: 256.0, model: 4 - Series Chipset Integrated Graphics Controller, serialNumber: null} +- { '@type': GraphicCard, manufacturer: Intel Corporation, memory: 256.0, model: 4 + Series Chipset Integrated Graphics Controller, serialNumber: null} - '@type': Motherboard connectors: {firewire: 0, pcmcia: 0, serial: 1, usb: 8} manufacturer: LENOVO @@ -41,24 +41,24 @@ components: serialNumber: null totalSlots: 0 usedSlots: 2 -- {'@type': NetworkAdapter, manufacturer: Intel Corporation, model: 82567LM-3 Gigabit - Network Connection, serialNumber: '00:21:86:2c:5e:d6', speed: 1000} -- {'@type': SoundCard, manufacturer: Intel Corporation, model: 82801JD/DO HD Audio - Controller, serialNumber: null} +- { '@type': NetworkAdapter, manufacturer: Intel Corporation, model: 82567LM-3 Gigabit + Network Connection, serialNumber: '00:21:86:2c:5e:d6', speed: 1000} +- { '@type': SoundCard, manufacturer: Intel Corporation, model: 82801JD/DO HD Audio + Controller, serialNumber: null} condition: appearance: {general: B} functionality: {general: A} date: '2018-05-09T10:32:15' debug: - capabilities: {dmi-2.5: DMI version 2.5, smbios-2.5: SMBIOS version 2.5, smp: Symmetric - Multi-Processing, smp-1.4: SMP specification v1.4} + capabilities: { dmi-2.5: DMI version 2.5, smbios-2.5: SMBIOS version 2.5, smp: Symmetric + Multi-Processing, smp-1.4: SMP specification v1.4} children: - children: - - capabilities: {acpi: ACPI, biosbootspecification: BIOS boot specification, cdboot: Booting - from CD-ROM/DVD, edd: Enhanced Disk Drive extensions, escd: ESCD, ls120boot: Booting - from LS-120, pci: PCI bus, pnp: Plug-and-Play, shadowing: BIOS shadowing, - smartbattery: Smart battery, upgrade: BIOS EEPROM can be upgraded, usb: USB - legacy emulation} + - capabilities: { acpi: ACPI, biosbootspecification: BIOS boot specification, cdboot: Booting + from CD-ROM/DVD, edd: Enhanced Disk Drive extensions, escd: ESCD, ls120boot: Booting + from LS-120, pci: PCI bus, pnp: Plug-and-Play, shadowing: BIOS shadowing, + smartbattery: Smart battery, upgrade: BIOS EEPROM can be upgraded, usb: USB + legacy emulation} capacity: 4128768 claimed: true class: memory @@ -71,24 +71,24 @@ debug: vendor: LENOVO version: 5CKT48AUS - businfo: cpu@0 - capabilities: {acpi: thermal control (ACPI), aperfmperf: true, apic: on-chip - advanced programmable interrupt controller (APIC), arch_perfmon: true, boot: boot - processor, bts: true, clflush: true, cmov: conditional move instruction, + capabilities: { acpi: thermal control (ACPI), aperfmperf: true, apic: on-chip + advanced programmable interrupt controller (APIC), arch_perfmon: true, boot: boot + processor, bts: true, clflush: true, cmov: conditional move instruction, constant_tsc: true, cpufreq: CPU Frequency scaling, cx16: true, cx8: compare - and exchange 8-byte, de: debugging extensions, ds_cpl: true, dtes64: true, + and exchange 8-byte, de: debugging extensions, ds_cpl: true, dtes64: true, dtherm: true, dts: debug trace and EMON store MSRs, eagerfpu: true, est: true, flexpriority: true, fpu: mathematical co-processor, fpu_exception: FPU exceptions - reporting, fxsr: fast floating point save/restore, ht: HyperThreading, lahf_lm: true, + reporting, fxsr: fast floating point save/restore, ht: HyperThreading, lahf_lm: true, mca: machine check architecture, mce: machine check exceptions, mmx: multimedia - extensions (MMX), monitor: true, msr: model-specific registers, mtrr: memory - type range registers, nx: no-execute bit (NX), pae: 4GB+ memory addressing - (Physical Address Extension), pat: page attribute table, pbe: pending break - event, pdcm: true, pebs: true, pge: page global enable, pni: true, pse: page - size extensions, pse36: 36-bit page size extensions, sep: fast system calls, + extensions (MMX), monitor: true, msr: model-specific registers, mtrr: memory + type range registers, nx: no-execute bit (NX), pae: 4GB+ memory addressing + (Physical Address Extension), pat: page attribute table, pbe: pending break + event, pdcm: true, pebs: true, pge: page global enable, pni: true, pse: page + size extensions, pse36: 36-bit page size extensions, sep: fast system calls, smx: true, ss: self-snoop, sse: streaming SIMD extensions (SSE), sse2: streaming - SIMD extensions (SSE2), sse4_1: true, ssse3: true, tm: thermal interrupt - and status, tm2: true, tpr_shadow: true, tsc: time stamp counter, vme: virtual - mode extensions, vmx: CPU virtualization (Vanderpool), vnmi: true, wp: true, + SIMD extensions (SSE2), sse4_1: true, ssse3: true, tm: thermal interrupt + and status, tm2: true, tpr_shadow: true, tsc: time stamp counter, vme: virtual + mode extensions, vmx: CPU virtualization (Vanderpool), vnmi: true, wp: true, x86-64: 64bits extensions (x86-64), xsave: true, xtpr: true} capacity: 3600000000 children: @@ -149,22 +149,22 @@ debug: version: 6.7.10 width: 64 - children: - - {claimed: true, class: memory, clock: 1067000000, description: DIMM DDR2 Synchronous - 1067 MHz (0.9 ns), handle: 'DMI:001F', id: 'bank:0', physid: '0', product: '000000000000000000000000000000000000', + - { claimed: true, class: memory, clock: 1067000000, description: DIMM DDR2 Synchronous + 1067 MHz (0.9 ns), handle: 'DMI:001F', id: 'bank:0', physid: '0', product: '000000000000000000000000000000000000', serial: '00000000', size: 2147483648, slot: J6G1, units: bytes, vendor: Unknown, width: 40960} - {claimed: true, class: memory, clock: 1067000000, description: 'DIMM DDR2 Synchronous 1067 MHz (0.9 ns) [empty]', handle: 'DMI:0020', id: 'bank:1', - physid: '1', product: 012345678901234567890123456789012345, serial: '01234567', - slot: J6G2, vendor: 48spaces} - - {claimed: true, class: memory, clock: 1067000000, description: DIMM DDR2 Synchronous - 1067 MHz (0.9 ns), handle: 'DMI:0021', id: 'bank:2', physid: '2', product: '000000000000000000000000000000000000', + physid: '1', product: 012345678901234567890123456789012345, serial: '01234567', + slot: J6G2, vendor: 48spaces} + - { claimed: true, class: memory, clock: 1067000000, description: DIMM DDR2 Synchronous + 1067 MHz (0.9 ns), handle: 'DMI:0021', id: 'bank:2', physid: '2', product: '000000000000000000000000000000000000', serial: '00000000', size: 2147483648, slot: J6H1, units: bytes, vendor: Unknown, width: 41984} - {claimed: true, class: memory, clock: 1067000000, description: 'DIMM DDR2 Synchronous 1067 MHz (0.9 ns) [empty]', handle: 'DMI:0022', id: 'bank:3', - physid: '3', product: 012345678901234567890123456789012345, serial: '01234567', - slot: J6H2, vendor: 48spaces} + physid: '3', product: 012345678901234567890123456789012345, serial: '01234567', + slot: J6H2, vendor: 48spaces} claimed: true class: memory description: System Memory @@ -176,7 +176,7 @@ debug: units: bytes - businfo: cpu@1 capabilities: {cpufreq: CPU Frequency scaling, ht: HyperThreading, vmx: CPU - virtualization (Vanderpool)} + virtualization (Vanderpool)} capacity: 3000000000 children: - capabilities: {logical: Logical CPU} @@ -205,9 +205,9 @@ debug: - businfo: pci@0000:00:00.0 children: - businfo: pci@0000:00:02.0 - capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, + capabilities: { bus_master: bus mastering, cap_list: PCI capabilities listing, msi: Message Signalled Interrupts, pm: Power Management, rom: extension - ROM, vga_controller: true} + ROM, vga_controller: true} claimed: true class: display clock: 33000000 @@ -222,7 +222,7 @@ debug: width: 64 - businfo: pci@0000:00:02.1 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - pm: Power Management} + pm: Power Management} class: display clock: 33000000 configuration: {latency: '0'} @@ -236,7 +236,7 @@ debug: width: 64 - businfo: pci@0000:00:03.0 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - msi: Message Signalled Interrupts, pm: Power Management} + msi: Message Signalled Interrupts, pm: Power Management} claimed: true class: communication clock: 33000000 @@ -251,8 +251,8 @@ debug: width: 64 - businfo: pci@0000:00:03.2 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - ide: true, msi: Message Signalled Interrupts, pci_native_mode-only_controller__supports_bus_mastering: true, - pm: Power Management} + ide: true, msi: Message Signalled Interrupts, pci_native_mode-only_controller__supports_bus_mastering: true, + pm: Power Management} class: storage clock: 66000000 configuration: {latency: '0'} @@ -265,8 +265,8 @@ debug: version: '03' width: 32 - businfo: pci@0000:00:03.3 - capabilities: {'16550': true, bus_master: bus mastering, cap_list: PCI capabilities - listing, msi: Message Signalled Interrupts, pm: Power Management} + capabilities: { '16550': true, bus_master: bus mastering, cap_list: PCI capabilities + listing, msi: Message Signalled Interrupts, pm: Power Management} claimed: true class: communication clock: 66000000 @@ -280,18 +280,18 @@ debug: version: '03' width: 32 - businfo: pci@0000:00:19.0 - capabilities: {1000bt-fd: 1Gbit/s (full duplex), 100bt: 100Mbit/s, 100bt-fd: 100Mbit/s - (full duplex), 10bt: 10Mbit/s, 10bt-fd: 10Mbit/s (full duplex), autonegotiation: Auto-negotiation, + capabilities: { 1000bt-fd: 1Gbit/s (full duplex), 100bt: 100Mbit/s, 100bt-fd: 100Mbit/s + (full duplex), 10bt: 10Mbit/s, 10bt-fd: 10Mbit/s (full duplex), autonegotiation: Auto-negotiation, bus_master: bus mastering, cap_list: PCI capabilities listing, ethernet: true, msi: Message Signalled Interrupts, physical: Physical interface, pm: Power - Management, tp: twisted pair} + Management, tp: twisted pair} capacity: 1000000000 claimed: true class: network clock: 33000000 configuration: {autonegotiation: 'on', broadcast: 'yes', driver: e1000e, driverversion: 3.2.6-k, - duplex: full, firmware: 0.4-3, ip: 192.168.2.24, latency: '0', link: 'yes', - multicast: 'yes', port: twisted pair, speed: 100Mbit/s} + duplex: full, firmware: 0.4-3, ip: 192.168.2.24, latency: '0', link: 'yes', + multicast: 'yes', port: twisted pair, speed: 100Mbit/s} description: Ethernet interface handle: PCI:0000:00:19.0 id: network @@ -306,7 +306,7 @@ debug: width: 32 - businfo: pci@0000:00:1a.0 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - uhci: Universal Host Controller Interface (USB1)} + uhci: Universal Host Controller Interface (USB1)} children: - businfo: usb@3 capabilities: {usb-1.10: USB 1.1} @@ -334,7 +334,7 @@ debug: width: 32 - businfo: pci@0000:00:1a.1 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - uhci: Universal Host Controller Interface (USB1)} + uhci: Universal Host Controller Interface (USB1)} children: - businfo: usb@4 capabilities: {usb-1.10: USB 1.1} @@ -362,7 +362,7 @@ debug: width: 32 - businfo: pci@0000:00:1a.2 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - uhci: Universal Host Controller Interface (USB1)} + uhci: Universal Host Controller Interface (USB1)} children: - businfo: usb@5 capabilities: {usb-1.10: USB 1.1} @@ -390,8 +390,8 @@ debug: width: 32 - businfo: pci@0000:00:1a.7 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - debug: Debug port, ehci: Enhanced Host Controller Interface (USB2), pm: Power - Management} + debug: Debug port, ehci: Enhanced Host Controller Interface (USB2), pm: Power + Management} children: - businfo: usb@1 capabilities: {usb-2.00: USB 2.0} @@ -419,7 +419,7 @@ debug: width: 32 - businfo: pci@0000:00:1b.0 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - msi: Message Signalled Interrupts, pciexpress: PCI Express, pm: Power Management} + msi: Message Signalled Interrupts, pciexpress: PCI Express, pm: Power Management} claimed: true class: multimedia clock: 33000000 @@ -434,7 +434,7 @@ debug: width: 64 - businfo: pci@0000:00:1d.0 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - uhci: Universal Host Controller Interface (USB1)} + uhci: Universal Host Controller Interface (USB1)} children: - businfo: usb@6 capabilities: {usb-1.10: USB 1.1} @@ -462,7 +462,7 @@ debug: width: 32 - businfo: pci@0000:00:1d.1 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - uhci: Universal Host Controller Interface (USB1)} + uhci: Universal Host Controller Interface (USB1)} children: - businfo: usb@7 capabilities: {usb-1.10: USB 1.1} @@ -490,7 +490,7 @@ debug: width: 32 - businfo: pci@0000:00:1d.2 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - uhci: Universal Host Controller Interface (USB1)} + uhci: Universal Host Controller Interface (USB1)} children: - businfo: usb@8 capabilities: {usb-1.10: USB 1.1} @@ -518,8 +518,8 @@ debug: width: 32 - businfo: pci@0000:00:1d.7 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - debug: Debug port, ehci: Enhanced Host Controller Interface (USB2), pm: Power - Management} + debug: Debug port, ehci: Enhanced Host Controller Interface (USB2), pm: Power + Management} children: - businfo: usb@2 capabilities: {usb-2.00: USB 2.0} @@ -547,7 +547,7 @@ debug: width: 32 - businfo: pci@0000:00:1e.0 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - pci: true, subtractive_decode: true} + pci: true, subtractive_decode: true} claimed: true class: bridge clock: 33000000 @@ -561,7 +561,7 @@ debug: width: 32 - businfo: pci@0000:00:1f.0 capabilities: {bus_master: bus mastering, cap_list: PCI capabilities listing, - isa: true} + isa: true} claimed: true class: bridge clock: 33000000 @@ -575,8 +575,8 @@ debug: version: '02' width: 32 - businfo: pci@0000:00:1f.2 - capabilities: {ahci_1.0: true, bus_master: bus mastering, cap_list: PCI capabilities - listing, msi: Message Signalled Interrupts, pm: Power Management, storage: true} + capabilities: { ahci_1.0: true, bus_master: bus mastering, cap_list: PCI capabilities + listing, msi: Message Signalled Interrupts, pm: Power Management, storage: true} claimed: true class: storage clock: 66000000 @@ -617,18 +617,18 @@ debug: children: - businfo: scsi@0:0.0.0 capabilities: {partitioned: Partitioned disk, 'partitioned:dos': MS-DOS partition - table} + table} children: - businfo: scsi@0:0.0.0,1 - capabilities: {dir_nlink: directories with 65000+ subdirs, ext2: EXT2/EXT3, + capabilities: { dir_nlink: directories with 65000+ subdirs, ext2: EXT2/EXT3, ext4: true, extended_attributes: Extended Attributes, extents: extent-based - allocation, huge_files: 16TB+ files, initialized: initialized volume, + allocation, huge_files: 16TB+ files, initialized: initialized volume, journaled: true, large_files: 4GB+ files, primary: Primary partition} capacity: 248984559616 claimed: true class: volume configuration: {created: '2016-11-03 17:23:45', filesystem: ext4, lastmountpoint: /tmp/mnt, - modified: '2016-11-03 17:27:46', mounted: '2016-11-03 17:27:30', state: clean} + modified: '2016-11-03 17:27:46', mounted: '2016-11-03 17:27:30', state: clean} description: EXT4 volume dev: '8:1' id: volume:0 @@ -651,7 +651,7 @@ debug: claimed: true class: disk configuration: {ansiversion: '5', logicalsectorsize: '512', sectorsize: '512', - signature: e4bb7bc9} + signature: e4bb7bc9} description: ATA Disk dev: '8:0' handle: SCSI:00:00:00:00 @@ -672,8 +672,8 @@ debug: - capabilities: {emulated: Emulated device} children: - businfo: scsi@1:0.0.0 - capabilities: {audio: Audio CD playback, cd-r: CD-R burning, cd-rw: CD-RW - burning, dvd: DVD playback, dvd-r: DVD-R burning, dvd-ram: DVD-RAM burning, + capabilities: { audio: Audio CD playback, cd-r: CD-R burning, cd-rw: CD-RW + burning, dvd: DVD playback, dvd-r: DVD-R burning, dvd-ram: DVD-RAM burning, removable: support is removable} claimed: true class: disk @@ -709,13 +709,13 @@ debug: physid: '1' vendor: Intel - {capacity: 125, class: power, description: Standard 235 ATX, id: power, physid: '2', - product: 'Diamond MM #87997/1845333', serial: '7481909424', units: mWh, vendor: 'PC + product: 'Diamond MM #87997/1845333', serial: '7481909424', units: mWh, vendor: 'PC POwer & Cooling, INC', version: '2.30'} claimed: true class: system configuration: {administrator_password: enabled, boot: normal, chassis: desktop, - cpus: '2', family: NONE, keyboard_password: disabled, power-on_password: disabled, - sku: NONE, uuid: 4D503B35-2239-3B5D-8499-343AE3A5F659} + cpus: '2', family: NONE, keyboard_password: disabled, power-on_password: disabled, + sku: NONE, uuid: 4D503B35-2239-3B5D-8499-343AE3A5F659} description: Desktop Computer handle: DMI:0001 id: debian @@ -725,11 +725,11 @@ debug: version: ThinkCentre M58p width: 32 device: {'@type': Computer, _id: '4544', gid: '10663', manufacturer: LENOVO, model: 7220A91, - serialNumber: LMCVFMF, type: Desktop} + serialNumber: LMCVFMF, type: Desktop} elapsed: 0:13:10 inventory: {elapsed: '0:00:34'} osInstallation: {elapsed: '0:06:25', label: /media/workbench-images/LinuxMint18.3-cat-64, - success: true} + success: true} snapshotSoftware: Workbench tests: - {'@type': StressTest, elapsed: '0:05:00', success: true} diff --git a/tests/files/workbench-server-1.snapshot.yaml b/tests/files/workbench-server-1.snapshot.yaml index adbedb9b..cb733443 100644 --- a/tests/files/workbench-server-1.snapshot.yaml +++ b/tests/files/workbench-server-1.snapshot.yaml @@ -18,68 +18,68 @@ device: model: d1ml manufacturer: d1mr tags: - - type: Tag - id: tag1 + - type: Tag + id: tag1 events: - - type: WorkbenchRate - appearanceRange: A - functionalityRange: B - - type: BenchmarkRamSysbench - rate: 2444 + - type: WorkbenchRate + appearanceRange: A + functionalityRange: B + - type: BenchmarkRamSysbench + rate: 2444 components: - - type: GraphicCard - serialNumber: gc1-1s - model: gc1-1ml - manufacturer: gc1-1mr - - type: RamModule - serialNumber: rm1-1s - model: rm1-1ml - manufacturer: rm1-1mr - - type: RamModule - serialNumber: rm2-1s - model: rm2-1ml - manufacturer: rm2-1mr - - type: Processor - model: p1-1s - manufacturer: p1-1mr - events: - - type: BenchmarkProcessor - rate: 2410 - - type: BenchmarkProcessorSysbench - rate: 4400 - - type: SolidStateDrive - serialNumber: ssd1-1s - model: ssd1-1ml - manufacturer: ssd1-1mr - events: - - type: BenchmarkDataStorage - readSpeed: 20 - writeSpeed: 15 - elapsed: 21 - - type: TestDataStorage - elapsed: 233 - error: False - status: Completed without error - length: Short - lifetime: 99 - assessment: True - powerCycleCount: 11 - reallocatedSectorCount: 2 - powerCycleCount: 4 - reportedUncorrectableErrors: 1 - commandTimeout: 11 - currentPendingSectorCount: 1 - offlineUncorrectable: 33 - remainingLifetimePercentage: 1 - - type: HardDrive - serialNumber: hdd1-1s - model: hdd1-1ml - manufacturer: hdd1-1mr - events: - - type: BenchmarkDataStorage - readSpeed: 10 - writeSpeed: 5 - - type: Motherboard - serialNumber: mb1-1s - model: mb1-1ml - manufacturer: mb1-1mr +- type: GraphicCard + serialNumber: gc1-1s + model: gc1-1ml + manufacturer: gc1-1mr +- type: RamModule + serialNumber: rm1-1s + model: rm1-1ml + manufacturer: rm1-1mr +- type: RamModule + serialNumber: rm2-1s + model: rm2-1ml + manufacturer: rm2-1mr +- type: Processor + model: p1-1s + manufacturer: p1-1mr + events: + - type: BenchmarkProcessor + rate: 2410 + - type: BenchmarkProcessorSysbench + rate: 4400 +- type: SolidStateDrive + serialNumber: ssd1-1s + model: ssd1-1ml + manufacturer: ssd1-1mr + events: + - type: BenchmarkDataStorage + readSpeed: 20 + writeSpeed: 15 + elapsed: 21 + - type: TestDataStorage + elapsed: 233 + error: False + status: Completed without error + length: Short + lifetime: 99 + assessment: True + powerCycleCount: 11 + reallocatedSectorCount: 2 + powerCycleCount: 4 + reportedUncorrectableErrors: 1 + commandTimeout: 11 + currentPendingSectorCount: 1 + offlineUncorrectable: 33 + remainingLifetimePercentage: 1 +- type: HardDrive + serialNumber: hdd1-1s + model: hdd1-1ml + manufacturer: hdd1-1mr + events: + - type: BenchmarkDataStorage + readSpeed: 10 + writeSpeed: 5 +- type: Motherboard + serialNumber: mb1-1s + model: mb1-1ml + manufacturer: mb1-1mr diff --git a/tests/files/workbench-server-3.erase.yaml b/tests/files/workbench-server-3.erase.yaml index c8862d88..24bde030 100644 --- a/tests/files/workbench-server-3.erase.yaml +++ b/tests/files/workbench-server-3.erase.yaml @@ -14,7 +14,7 @@ zeros: False startTime: 2018-01-01T10:10:10 endTime: 2018-01-01T12:10:10 steps: - - type: 'StepRandom' - startTime: '2018-01-01T10:10:10' - endTime: '2018-01-01T12:10:10' - error: False +- type: 'StepRandom' + startTime: '2018-01-01T10:10:10' + endTime: '2018-01-01T12:10:10' + error: False diff --git a/tests/test_agent.py b/tests/test_agent.py new file mode 100644 index 00000000..3e6f7f84 --- /dev/null +++ b/tests/test_agent.py @@ -0,0 +1,129 @@ +from uuid import UUID + +import pytest +from sqlalchemy.exc import IntegrityError +from sqlalchemy_utils import PhoneNumber + +from ereuse_devicehub.config import DevicehubConfig +from ereuse_devicehub.db import db +from ereuse_devicehub.devicehub import Devicehub +from ereuse_devicehub.resources.agent import OrganizationDef, models, schemas +from ereuse_devicehub.resources.agent.models import Membership, Organization, Person, System +from teal.enums import Country +from tests.conftest import app_context, create_user + + +@pytest.mark.usefixtures(app_context.__name__) +def test_agent(): + """Tests creating an person.""" + person = Person(name='Timmy', + tax_id='XYZ', + country=Country.ES, + telephone=PhoneNumber('+34666666666'), + email='foo@bar.com') + db.session.add(person) + db.session.commit() + + p = schemas.Person().dump(person) + assert p['name'] == person.name == 'Timmy' + assert p['taxId'] == person.tax_id == 'XYZ' + assert p['country'] == person.country.name == 'ES' + assert p['telephone'] == person.telephone.international == '+34 666 66 66 66' + assert p['email'] == person.email == 'foo@bar.com' + + +@pytest.mark.usefixtures(app_context.__name__) +def test_system(): + """Tests creating a system.""" + system = System(name='Workbench', + email='hello@ereuse.org') + db.session.add(system) + db.session.commit() + + s = schemas.System().dump(system) + assert s['name'] == system.name == 'Workbench' + assert s['email'] == system.email == 'hello@ereuse.org' + + +@pytest.mark.usefixtures(app_context.__name__) +def test_organization(): + """Tests creating an organization.""" + org = Organization(name='ACME', + tax_id='XYZ', + country=Country.ES, + email='contact@acme.com') + db.session.add(org) + db.session.commit() + + o = schemas.Organization().dump(org) + assert o['name'] == org.name == 'ACME' + assert o['taxId'] == org.tax_id == 'XYZ' + assert org.country.name == o['country'] == 'ES' + + +@pytest.mark.usefixtures(app_context.__name__) +def test_membership(): + """Tests assigning an Individual to an Organization.""" + person = Person(name='Timmy') + org = Organization(name='ACME') + person.member_of.add(Membership(org, person, id='acme-1')) + db.session.add(person) + db.session.flush() + + +@pytest.mark.usefixtures(app_context.__name__) +def test_membership_repeated(): + person = Person(name='Timmy') + org = Organization(name='ACME') + person.member_of.add(Membership(org, person, id='acme-1')) + db.session.add(person) + + person.member_of.add(Membership(org, person)) + with pytest.raises(IntegrityError): + db.session.flush() + + +@pytest.mark.usefixtures(app_context.__name__) +def test_membership_repeating_id(): + person = Person(name='Timmy') + org = Organization(name='ACME') + person.member_of.add(Membership(org, person, id='acme-1')) + db.session.add(person) + db.session.flush() + + person2 = Person(name='Tommy') + person2.member_of.add(Membership(org, person2, id='acme-1')) + db.session.add(person2) + with pytest.raises(IntegrityError) as e: + db.session.flush() + assert 'One member id per organization' in str(e) + + +@pytest.mark.usefixtures(app_context.__name__) +def test_default_org_exists(config: DevicehubConfig): + """ + Ensures that the default organization is created on app + initialization and that is accessible for the method + :meth:`ereuse_devicehub.resources.user.Organization.get_default_org`. + """ + assert models.Organization.query.filter_by(name=config.ORGANIZATION_NAME, + tax_id=config.ORGANIZATION_TAX_ID).one() + assert isinstance(models.Organization.get_default_org_id(), UUID) + + +@pytest.mark.usefixtures(app_context.__name__) +def test_assign_individual_user(): + """Tests assigning an individual to an user.""" + user = create_user() + assert len(user.individuals) == 1 + assert next(iter(user.individuals)).name == 'Timmy' + + +@pytest.mark.usefixtures(app_context.__name__) +def test_create_organization_main_method(app: Devicehub): + org_def = app.resources[models.Organization.t] # type: OrganizationDef + o = org_def.create_org('ACME', tax_id='FOO', country='ES') + org = models.Agent.query.filter_by(id=o['id']).one() # type: Organization + assert org.name == o['name'] == 'ACME' + assert org.tax_id == o['taxId'] == 'FOO' + assert org.country.name == o['country'] == 'ES' diff --git a/tests/test_basic.py b/tests/test_basic.py index aa9c4a6b..a57697ab 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -35,4 +35,4 @@ def test_api_docs(client: Client): 'scheme': 'basic', 'name': 'Authorization' } - assert 60 == len(docs['definitions']) + assert 76 == len(docs['definitions']) diff --git a/tests/test_device.py b/tests/test_device.py index 47a53986..381352be 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -9,6 +9,7 @@ from sqlalchemy.util import OrderedSet from ereuse_devicehub.client import UserClient from ereuse_devicehub.db import db from ereuse_devicehub.devicehub import Devicehub +from ereuse_devicehub.resources.agent.models import Person from ereuse_devicehub.resources.device.exceptions import NeedsId from ereuse_devicehub.resources.device.models import Component, ComputerMonitor, Desktop, Device, \ GraphicCard, Laptop, Motherboard, NetworkAdapter @@ -369,6 +370,7 @@ def test_get_device(app: Devicehub, user: UserClient): db.session.add(Test(device=pc, elapsed=timedelta(seconds=4), error=False, + agent=Person(name='Timmy'), author=User(email='bar@bar.com'))) db.session.commit() pc, _ = user.get(res=Device, item=1) diff --git a/tests/test_event.py b/tests/test_event.py index 0468d1d5..888b6b4b 100644 --- a/tests/test_event.py +++ b/tests/test_event.py @@ -1,19 +1,22 @@ +import ipaddress from datetime import datetime, timedelta import pytest -from flask import g +from flask import current_app as app, g from sqlalchemy.util import OrderedSet from ereuse_devicehub.client import UserClient from ereuse_devicehub.db import db from ereuse_devicehub.resources.device.models import Desktop, Device, GraphicCard, HardDrive, \ RamModule, SolidStateDrive -from ereuse_devicehub.resources.enums import TestHardDriveLength +from ereuse_devicehub.resources.enums import ComputerChassis, TestHardDriveLength from ereuse_devicehub.resources.event import models +from teal.enums import Currency, Subdivision +from tests import conftest from tests.conftest import create_user, file -@pytest.mark.usefixtures('app_context') +@pytest.mark.usefixtures(conftest.app_context.__name__) def test_author(): """ Checks the default created author. @@ -30,7 +33,7 @@ def test_author(): assert e.author == user -@pytest.mark.usefixtures('auth_app_context') +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) def test_erase_basic(): erasure = models.EraseBasic( device=HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar'), @@ -46,7 +49,7 @@ def test_erase_basic(): assert next(iter(db_erasure.device.events)) == erasure -@pytest.mark.usefixtures('auth_app_context') +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) def test_validate_device_data_storage(): """Checks the validation for data-storage-only events works.""" # We can't set a GraphicCard @@ -62,7 +65,7 @@ def test_validate_device_data_storage(): ) -@pytest.mark.usefixtures('auth_app_context') +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) def test_erase_sectors_steps(): erasure = models.EraseSectors( device=SolidStateDrive(serial_number='foo', manufacturer='bar', model='foo-bar'), @@ -91,7 +94,7 @@ def test_erase_sectors_steps(): assert db_erasure.steps[2].num == 2 -@pytest.mark.usefixtures('auth_app_context') +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) def test_test_data_storage(): test = models.TestDataStorage( device=HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar'), @@ -106,7 +109,7 @@ def test_test_data_storage(): assert models.TestDataStorage.query.one() -@pytest.mark.usefixtures('auth_app_context') +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) def test_install(): hdd = HardDrive(serial_number='sn') install = models.Install(name='LinuxMint 18.04 es', @@ -116,7 +119,7 @@ def test_install(): db.session.commit() -@pytest.mark.usefixtures('auth_app_context') +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) def test_update_components_event_one(): computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1') hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar') @@ -141,13 +144,13 @@ def test_update_components_event_one(): assert len(test.components) == 1 -@pytest.mark.usefixtures('auth_app_context') +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) def test_update_components_event_multiple(): computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1') hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar') computer.components.add(hdd) - ready = models.Ready() + ready = models.ReadyToUse() assert not ready.devices assert not ready.components @@ -167,7 +170,7 @@ def test_update_components_event_multiple(): assert ready.components -@pytest.mark.usefixtures('auth_app_context') +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) def test_update_parent(): computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1') hdd = HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar') @@ -184,21 +187,96 @@ def test_update_parent(): assert not benchmark.parent -@pytest.mark.xfail(reason='No POST view for generic tests') @pytest.mark.parametrize('event_model', [ models.ToRepair, models.Repair, models.ToPrepare, + models.ReadyToUse, + models.ToPrepare, models.Prepare, - models.ToDispose, - models.Dispose, - models.Ready ]) def test_generic_event(event_model: models.Event, user: UserClient): """Tests POSTing all generic events.""" snapshot, _ = user.post(file('basic.snapshot'), res=models.Snapshot) event = {'type': event_model.t, 'devices': [snapshot['device']['id']]} - event, _ = user.post(event, res=event_model) - assert event['device'][0]['id'] == snapshot['device']['id'] + event, _ = user.post(event, res=models.Event) + assert event['devices'][0]['id'] == snapshot['device']['id'] device, _ = user.get(res=Device, item=snapshot['device']['id']) - assert device['events'][0]['id'] == event['id'] + assert device['events'][-1]['id'] == event['id'] + + +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) +def test_live(): + """Tests inserting a Live into the database and GETting it.""" + db_live = models.Live(ip=ipaddress.ip_address('79.147.10.10'), + subdivision_confidence=84, + subdivision=Subdivision['ES-CA'], + city='Barcelona', + city_confidence=20, + isp='ACME', + device=Desktop(serial_number='sn1', model='ml1', manufacturer='mr1', + chassis=ComputerChassis.Docking), + organization='ACME1', + organization_type='ACME1bis') + db.session.add(db_live) + db.session.commit() + client = UserClient(app, 'foo@foo.com', 'foo', response_wrapper=app.response_class) + client.login() + live, _ = client.get(res=models.Event, item=str(db_live.id)) + assert live['ip'] == '79.147.10.10' + assert live['subdivision'] == 'ES-CA' + assert live['country'] == 'ES' + + +@pytest.mark.xfail(reson='Functionality not developed.') +def test_live_geoip(): + """Tests performing a Live action using the GEOIP library.""" + + +@pytest.mark.xfail(reson='Develop reserve') +def test_reserve(user: UserClient): + """Performs a reservation and then cancels it.""" + + +@pytest.mark.parametrize('event_model', [ + models.Sell, + models.Donate, + models.Rent, + models.DisposeProduct +]) +def test_trade(event_model: models.Event, user: UserClient): + """Tests POSTing all generic events.""" + snapshot, _ = user.post(file('basic.snapshot'), res=models.Snapshot) + event = { + 'type': event_model.t, + 'devices': [snapshot['device']['id']], + 'to': user.user['individuals'][0]['id'], + 'shippingDate': '2018-06-29T12:28:54', + 'invoiceNumber': 'ABC' + } + event, _ = user.post(event, res=models.Event) + assert event['devices'][0]['id'] == snapshot['device']['id'] + device, _ = user.get(res=Device, item=snapshot['device']['id']) + assert device['events'][-1]['id'] == event['id'] + + +@pytest.mark.xfail(reson='Develop migrate') +def test_migrate(): + pass + + +@pytest.mark.usefixtures(conftest.auth_app_context.__name__) +def test_price_custom(): + computer = Desktop(serial_number='sn1', model='ml1', manufacturer='mr1', + chassis=ComputerChassis.Docking) + price = models.Price(price=25.25, currency=Currency.EUR) + price.device = computer + db.session.add(computer) + db.session.commit() + + client = UserClient(app, 'foo@foo.com', 'foo', response_wrapper=app.response_class) + client.login() + p, _ = client.get(res=models.Event, item=str(price.id)) + assert p['device']['id'] == price.device.id == computer.id + assert p['price'] == 25.25 + assert p['currency'] == Currency.EUR.name == 'EUR' diff --git a/tests/test_organization.py b/tests/test_organization.py deleted file mode 100644 index 074f9714..00000000 --- a/tests/test_organization.py +++ /dev/null @@ -1,18 +0,0 @@ -from uuid import UUID - -import pytest - -from ereuse_devicehub.config import DevicehubConfig -from ereuse_devicehub.resources.user import Organization - - -@pytest.mark.usefixtures('app_context') -def test_default_org_exists(config: DevicehubConfig): - """ - Ensures that the default organization is created on app - initialization and that is accessible for the method - :meth:`ereuse_devicehub.resources.user.Organization.get_default_org`. - """ - assert Organization.query.filter_by(name=config.ORGANIZATION_NAME, - tax_id=config.ORGANIZATION_TAX_ID).one() - assert isinstance(Organization.get_default_org_id(), UUID) diff --git a/tests/test_price.py b/tests/test_price.py deleted file mode 100644 index b3c1105c..00000000 --- a/tests/test_price.py +++ /dev/null @@ -1,6 +0,0 @@ -import pytest - - -@pytest.mark.xfail(reason='Just needs to do the test') -def test_price_no_data_storage(): - pass diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index b72ba52b..290d1c0d 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -4,6 +4,7 @@ from typing import List, Tuple from uuid import uuid4 import pytest + from ereuse_devicehub.client import UserClient from ereuse_devicehub.db import db from ereuse_devicehub.devicehub import Devicehub @@ -28,7 +29,7 @@ def test_snapshot_model(): device = m.Desktop(serial_number='a1', chassis=ComputerChassis.Tower) # noinspection PyArgumentList snapshot = Snapshot(uuid=uuid4(), - date=datetime.now(), + end_time=datetime.now(), version='1.0', software=SnapshotSoftware.DesktopApp, elapsed=timedelta(seconds=25)) diff --git a/tests/test_tag.py b/tests/test_tag.py index ddb10c01..cad129e2 100644 --- a/tests/test_tag.py +++ b/tests/test_tag.py @@ -5,11 +5,11 @@ from sqlalchemy.exc import IntegrityError from ereuse_devicehub.client import UserClient from ereuse_devicehub.db import db from ereuse_devicehub.devicehub import Devicehub +from ereuse_devicehub.resources.agent.models import Organization from ereuse_devicehub.resources.device.models import Desktop from ereuse_devicehub.resources.enums import ComputerChassis from ereuse_devicehub.resources.tag import Tag from ereuse_devicehub.resources.tag.view import CannotCreateETag, TagNotLinked -from ereuse_devicehub.resources.user import Organization from teal.db import MultipleResourcesFound, ResourceNotFound from teal.marshmallow import ValidationError diff --git a/tests/test_user.py b/tests/test_user.py index a27415ef..ca362ff4 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -1,6 +1,7 @@ from base64 import b64decode from uuid import UUID +import pytest from sqlalchemy_utils import Password from werkzeug.exceptions import NotFound @@ -11,42 +12,42 @@ from ereuse_devicehub.resources.user import UserDef from ereuse_devicehub.resources.user.exceptions import WrongCredentials from ereuse_devicehub.resources.user.models import User from teal.marshmallow import ValidationError -from tests.conftest import create_user +from tests.conftest import app_context, create_user +@pytest.mark.usefixtures(app_context.__name__) def test_create_user_method(app: Devicehub): """ Tests creating an user through the main method. This method checks that the token is correct, too. """ - with app.app_context(): - user_def = app.resources['User'] # type: UserDef - u = user_def.create_user(email='foo@foo.com', password='foo') - user = User.query.filter_by(id=u['id']).one() # type: User - assert user.email == 'foo@foo.com' - assert isinstance(user.token, UUID) - assert User.query.filter_by(email='foo@foo.com').one() == user + user_def = app.resources['User'] # type: UserDef + u = user_def.create_user(email='foo@foo.com', password='foo') + user = User.query.filter_by(id=u['id']).one() # type: User + assert user.email == 'foo@foo.com' + assert isinstance(user.token, UUID) + assert User.query.filter_by(email='foo@foo.com').one() == user -def test_create_user_email_insensitive(app: Devicehub): +@pytest.mark.usefixtures(app_context.__name__) +def test_create_user_email_insensitive(): """Ensures email is case insensitive.""" - with app.app_context(): - user = User(email='FOO@foo.com') - db.session.add(user) - db.session.commit() - # We search in case insensitive manner - u1 = User.query.filter_by(email='foo@foo.com').one() - assert u1 == user - assert u1.email == 'foo@foo.com' + user = User(email='FOO@foo.com') + db.session.add(user) + db.session.commit() + # We search in case insensitive manner + u1 = User.query.filter_by(email='foo@foo.com').one() + assert u1 == user + assert u1.email == 'foo@foo.com' -def test_hash_password(app: Devicehub): +@pytest.mark.usefixtures(app_context.__name__) +def test_hash_password(): """Tests correct password hashing and equaling.""" - with app.app_context(): - user = create_user() - assert isinstance(user.password, Password) - assert user.password == 'foo' + user = create_user() + assert isinstance(user.password, Password) + assert user.password == 'foo' def test_login_success(client: Client, app: Devicehub): @@ -66,6 +67,9 @@ def test_login_success(client: Client, app: Devicehub): assert user['email'] == 'foo@foo.com' assert UUID(b64decode(user['token'].encode()).decode()[:-1]) assert 'password' not in user + assert user['individuals'][0]['name'] == 'Timmy' + assert user['individuals'][0]['type'] == 'Person' + assert len(user['individuals']) == 1 def test_login_failure(client: Client, app: Devicehub): diff --git a/tests/test_workbench.py b/tests/test_workbench.py index ef4f46f7..9c17f030 100644 --- a/tests/test_workbench.py +++ b/tests/test_workbench.py @@ -3,12 +3,12 @@ Tests that emulates the behaviour of a WorkbenchServer. """ import pytest + from ereuse_devicehub.client import UserClient from ereuse_devicehub.resources.device.exceptions import NeedsId from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.event import models as em from ereuse_devicehub.resources.tag.model import Tag - from tests.conftest import file