From e4cf093b4b77ef4fc64ce71d0dc85c99380d2780 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 14 Oct 2020 13:41:28 +0200 Subject: [PATCH 01/20] test of case when the time mark need to be updated --- tests/test_snapshot.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 4482e66e..707577af 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -98,6 +98,26 @@ def test_snapshot_post(user: UserClient): assert rate['snapshot']['id'] == snapshot['id'] +@pytest.mark.mvp +def test_snapshot_update_timeupdated(user: UserClient): + """ + Tests for check if one computer have the time mark updated when one component of it is updated + """ + computer1 = file('1-device-with-components.snapshot') + snapshot = snapshot_and_check(user, + computer1, + action_types=(BenchmarkProcessor.t, + RateComputer.t), + perform_second_snapshot=False) + computer2 = file('2-second-device-with-components-of-first.snapshot') + snapshot_and_check(user, computer2, action_types=('Remove', 'RateComputer'), + perform_second_snapshot=False) + # import pdb; pdb.set_trace() + pc1_id = snapshot['device']['id'] + pc1, _ = user.get(res=m.Device, item=pc1_id) + assert pc1['updated'] != snapshot['updated'] + + @pytest.mark.mvp def test_snapshot_component_add_remove(user: UserClient): """Tests adding and removing components and some don't generate HID. From a7c3ea7317a735e03f6e4610d5e7f0d23dac1ca0 Mon Sep 17 00:00:00 2001 From: nad Date: Thu, 15 Oct 2020 13:18:51 +0200 Subject: [PATCH 02/20] Adding workbench file for Issue 69 EreusePrice Computer type --- .../computer-type.snapshot.json | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 tests/workbench_files/computer-type.snapshot.json diff --git a/tests/workbench_files/computer-type.snapshot.json b/tests/workbench_files/computer-type.snapshot.json new file mode 100644 index 00000000..893f7e4a --- /dev/null +++ b/tests/workbench_files/computer-type.snapshot.json @@ -0,0 +1,135 @@ +{ + "device": { + "manufacturer": "Render", + "chassis": "Virtual", + "sku": "1234567890", + "actions": [ + { + "type": "StressTest", + "elapsed": 60, + "severity": "Info" + }, + { + "type": "BenchmarkRamSysbench", + "rate": 47.3516, + "elapsed": 47 + } + ], + "model": "Pinetrail", + "serialNumber": "0123456789", + "type": "Computer", + "version": "Revision A" + }, + "endTime": "2020-09-11T18:59:14.395622+00:00", + "closed": true, + "components": [ + { + "model": "NM10/ICH7 Family High Definition Audio Controller", + "type": "SoundCard", + "manufacturer": "Intel Corporation", + "serialNumber": null, + "actions": [] + }, + { + "model": "USB2.0-Camera", + "type": "SoundCard", + "manufacturer": "Generic", + "serialNumber": "200901010001", + "actions": [] + }, + { + "cores": 1, + "model": "Intel Atom CPU N455 @ 1.66GHz", + "brand": "Atom", + "manufacturer": "Intel Corp.", + "actions": [ + { + "type": "BenchmarkProcessorSysbench", + "rate": 164.4763, + "elapsed": 165 + }, + { + "type": "BenchmarkProcessor", + "rate": 6667.6, + "elapsed": 0 + } + ], + "speed": 1.667, + "generation": null, + "serialNumber": null, + "type": "Processor", + "address": 64, + "threads": 2 + }, + { + "format": "SODIMM", + "manufacturer": "7576aces", + "interface": "DDR3", + "actions": [], + "model": null, + "speed": 667.0, + "serialNumber": "7A7B7C7D", + "type": "RamModule", + "size": 1024.0 + }, + { + "manufacturer": "Toshiba", + "interface": "ATA", + "serialNumber": "907HT0RKT", + "model": "MK1665GS", + "actions": [ + { + "type": "BenchmarkDataStorage", + "readSpeed": 81.1, + "writeSpeed": 24.6, + "elapsed": 14 + }, + { + "reallocatedSectorCount": 47, + "powerCycleCount": 147, + "assessment": true, + "currentPendingSectorCount": 0, + "offlineUncorrectable": 0, + "elapsed": 114, + "status": "Completed without error", + "type": "TestDataStorage", + "length": "Short", + "lifetime": 98, + "severity": "Info" + } + ], + "type": "HardDrive", + "size": 160041.88569599998, + "variant": "1M" + }, + { + "manufacturer": "Intel Corporation", + "serialNumber": null, + "model": "Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller", + "memory": null, + "actions": [], + "type": "GraphicCard" + }, + { + "firewire": 0, + "serial": 1, + "actions": [], + "model": "Pinetrail", + "pcmcia": 0, + "serialNumber": "400", + "usb": 5, + "slots": 0, + "manufacturer": "Render", + "ramMaxSize": 2, + "version": "6.00", + "biosDate": "2011-02-28T00:00:00", + "type": "Motherboard", + "ramSlots": 2 + } + ], + "elapsed": 11215, + "uuid": "426ba7a5-7d73-4555-817e-562cead08e48", + "version": "11.0b11", + "software": "Workbench", + "type": "Snapshot" +} \ No newline at end of file From 75b5a4a710ac2b24d2f3ba290aad3fd750b8d8a9 Mon Sep 17 00:00:00 2001 From: nad Date: Thu, 15 Oct 2020 13:19:47 +0200 Subject: [PATCH 03/20] Adding test and fix for Issue 69 EreusePrice Computer type --- ereuse_devicehub/resources/action/models.py | 3 ++- tests/conftest.py | 6 ++++++ tests/test_workbench.py | 7 ++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ereuse_devicehub/resources/action/models.py b/ereuse_devicehub/resources/action/models.py index 6e728ab1..a0d38e14 100644 --- a/ereuse_devicehub/resources/action/models.py +++ b/ereuse_devicehub/resources/action/models.py @@ -1163,6 +1163,7 @@ class EreusePrice(Price): value agreed by a circuit or platform. """ MULTIPLIER = { + Computer: 20, Desktop: 20, Laptop: 30 } @@ -1205,7 +1206,7 @@ class EreusePrice(Price): } } } - SCHEMA[Server] = SCHEMA[Desktop] + SCHEMA[Server] = SCHEMA[Computer] = SCHEMA[Desktop] def __init__(self, device, rating_range, role, price: Decimal) -> None: cls = device.__class__ if device.__class__ != Server else Desktop diff --git a/tests/conftest.py b/tests/conftest.py index bdae5797..9969be22 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -134,6 +134,12 @@ def file(name: str) -> dict: return yaml.load(f) +def file_workbench(name: str) -> dict: + """Opens and parses a YAML file from the ``files`` subdir.""" + with Path(__file__).parent.joinpath('workbench_files').joinpath(name + '.json').open() as f: + return yaml.load(f) + + @pytest.fixture() def tag_id(app: Devicehub) -> str: """Creates a tag and returns its id.""" diff --git a/tests/test_workbench.py b/tests/test_workbench.py index 3620e951..cefd294e 100644 --- a/tests/test_workbench.py +++ b/tests/test_workbench.py @@ -11,7 +11,7 @@ from ereuse_devicehub.resources.action.models import RateComputer, BenchmarkProc from ereuse_devicehub.resources.device.exceptions import NeedsId from ereuse_devicehub.resources.device.models import Device from ereuse_devicehub.resources.tag.model import Tag -from tests.conftest import file +from tests.conftest import file, file_workbench @pytest.mark.mvp @@ -328,3 +328,8 @@ def test_workbench_asus_1001pxd_rate_low(user: UserClient): def test_david(user: UserClient): s = file('david.lshw.snapshot') snapshot, _ = user.post(res=em.Snapshot, data=s) + + +def test_eresueprice_computer_type(user: UserClient): + s = file_workbench('computer-type.snapshot') + snapshot, _ = user.post(res=em.Snapshot, data=s) From 76806299cd3e7093a08d91f68476e0d8cd8b5ed8 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 15:08:54 +0200 Subject: [PATCH 04/20] update devices when there are a new action --- ereuse_devicehub/resources/action/views.py | 5 +++++ tests/test_action.py | 2 ++ tests/test_snapshot.py | 21 +++++++++++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ereuse_devicehub/resources/action/views.py b/ereuse_devicehub/resources/action/views.py index ba727dc3..eb975e18 100644 --- a/ereuse_devicehub/resources/action/views.py +++ b/ereuse_devicehub/resources/action/views.py @@ -1,4 +1,5 @@ from distutils.version import StrictVersion +from datetime import datetime from typing import List from uuid import UUID @@ -37,6 +38,8 @@ class ActionView(View): return self.transfer_ownership() Model = db.Model._decl_class_registry.data[json['type']]() action = Model(**a) + for d in action.devices: + d.updated = datetime.now() db.session.add(action) db.session().final_flush() ret = self.schema.jsonify(action) @@ -109,6 +112,8 @@ class ActionView(View): if snapshot.device.hid is None: snapshot.severity = Severity.Warning db.session.add(snapshot) + for action in snapshot.actions: + action.device.updated = datetime.now() db.session().final_flush() ret = self.schema.jsonify(snapshot) # transform it back ret.status_code = 201 diff --git a/tests/test_action.py b/tests/test_action.py index ba99996d..ba095685 100644 --- a/tests/test_action.py +++ b/tests/test_action.py @@ -238,6 +238,8 @@ def test_generic_action(action_model_state: Tuple[models.Action, states.Trading] device, _ = user.get(res=Device, item=snapshot['device']['id']) assert device['actions'][-1]['id'] == action['id'] assert device['physical'] == state.name + # Check if the update of device is changed + assert snapshot['device']['updated'] != device['updated'] @pytest.mark.mvp diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 707577af..db00d16b 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -99,7 +99,7 @@ def test_snapshot_post(user: UserClient): @pytest.mark.mvp -def test_snapshot_update_timeupdated(user: UserClient): +def test_snapshot_update_timefield_updated(user: UserClient): """ Tests for check if one computer have the time mark updated when one component of it is updated """ @@ -110,9 +110,10 @@ def test_snapshot_update_timeupdated(user: UserClient): RateComputer.t), perform_second_snapshot=False) computer2 = file('2-second-device-with-components-of-first.snapshot') + pc1_id = snapshot['device']['id'] + pc1, _ = user.get(res=m.Device, item=pc1_id) snapshot_and_check(user, computer2, action_types=('Remove', 'RateComputer'), perform_second_snapshot=False) - # import pdb; pdb.set_trace() pc1_id = snapshot['device']['id'] pc1, _ = user.get(res=m.Device, item=pc1_id) assert pc1['updated'] != snapshot['updated'] @@ -144,6 +145,7 @@ def test_snapshot_component_add_remove(user: UserClient): perform_second_snapshot=False) pc1_id = snapshot1['device']['id'] pc1, _ = user.get(res=m.Device, item=pc1_id) + update1_pc1 = pc1['updated'] # Parent contains components assert tuple(c['serialNumber'] for c in pc1['components']) == ('p1c1s', 'p1c2s', 'p1c3s') # Components contain parent @@ -166,6 +168,10 @@ def test_snapshot_component_add_remove(user: UserClient): pc2_id = snapshot2['device']['id'] pc1, _ = user.get(res=m.Device, item=pc1_id) pc2, _ = user.get(res=m.Device, item=pc2_id) + # Check if the update_timestamp is updated + update1_pc2 = pc2['updated'] + update2_pc1 = pc1['updated'] + assert update1_pc1 != update2_pc1 # PC1 assert tuple(c['serialNumber'] for c in pc1['components']) == ('p1c1s', 'p1c3s') assert all(c['parent'] == pc1_id for c in pc1['components']) @@ -188,6 +194,12 @@ def test_snapshot_component_add_remove(user: UserClient): snapshot_and_check(user, s3, ('Remove', 'RateComputer'), perform_second_snapshot=False) pc1, _ = user.get(res=m.Device, item=pc1_id) pc2, _ = user.get(res=m.Device, item=pc2_id) + # Check if the update_timestamp is updated + update2_pc2 = pc2['updated'] + update3_pc1 = pc1['updated'] + assert not update3_pc1 in [update1_pc1, update2_pc1] + assert update1_pc2 != update2_pc2 + # PC1 assert {c['serialNumber'] for c in pc1['components']} == {'p1c2s', 'p1c3s'} assert all(c['parent'] == pc1_id for c in pc1['components']) @@ -228,6 +240,11 @@ def test_snapshot_component_add_remove(user: UserClient): snapshot_and_check(user, s4, ('RateComputer',), perform_second_snapshot=False) pc1, _ = user.get(res=m.Device, item=pc1_id) pc2, _ = user.get(res=m.Device, item=pc2_id) + # Check if the update_timestamp is updated + update3_pc2 = pc2['updated'] + update4_pc1 = pc1['updated'] + assert not update4_pc1 in [update1_pc1, update2_pc1, update3_pc1] + assert update3_pc2 == update2_pc2 # PC 0: p1c3s, p1c4s. PC1: p2c1s assert {c['serialNumber'] for c in pc1['components']} == {'p1c3s', 'p1c4s'} assert all(c['parent'] == pc1_id for c in pc1['components']) From 14d4d0aed0116d0bb4effce0d75c7dddf33da37d Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 15:26:12 +0200 Subject: [PATCH 05/20] fixed view --- ereuse_devicehub/resources/action/views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ereuse_devicehub/resources/action/views.py b/ereuse_devicehub/resources/action/views.py index 6bdaa8f8..f96d50c7 100644 --- a/ereuse_devicehub/resources/action/views.py +++ b/ereuse_devicehub/resources/action/views.py @@ -70,8 +70,9 @@ class ActionView(View): return self.transfer_ownership() Model = db.Model._decl_class_registry.data[json['type']]() action = Model(**a) - for d in action.devices: - d.updated = datetime.now() + if hasattr(action, 'devices'): + for d in action.devices: + d.updated = datetime.now() db.session.add(action) db.session().final_flush() ret = self.schema.jsonify(action) From c7abf29706e766ac632b7818ea0da742053bd1e4 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 16:24:48 +0200 Subject: [PATCH 06/20] clean all previus modifications --- ereuse_devicehub/resources/action/views.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ereuse_devicehub/resources/action/views.py b/ereuse_devicehub/resources/action/views.py index f96d50c7..689cb942 100644 --- a/ereuse_devicehub/resources/action/views.py +++ b/ereuse_devicehub/resources/action/views.py @@ -70,9 +70,6 @@ class ActionView(View): return self.transfer_ownership() Model = db.Model._decl_class_registry.data[json['type']]() action = Model(**a) - if hasattr(action, 'devices'): - for d in action.devices: - d.updated = datetime.now() db.session.add(action) db.session().final_flush() ret = self.schema.jsonify(action) @@ -146,8 +143,6 @@ class ActionView(View): if snapshot.device.hid is None: snapshot.severity = Severity.Warning db.session.add(snapshot) - for action in snapshot.actions: - action.device.updated = datetime.now() db.session().final_flush() ret = self.schema.jsonify(snapshot) # transform it back ret.status_code = 201 From ae1ecb59e2642ec18ec905682d0104c000663f20 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 16:25:13 +0200 Subject: [PATCH 07/20] add listener a event --- ereuse_devicehub/resources/models.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ereuse_devicehub/resources/models.py b/ereuse_devicehub/resources/models.py index 721e9258..74e1e6b4 100644 --- a/ereuse_devicehub/resources/models.py +++ b/ereuse_devicehub/resources/models.py @@ -1,4 +1,5 @@ from datetime import datetime, timezone +from flask_sqlalchemy import event from ereuse_devicehub.db import db @@ -34,3 +35,9 @@ class Thing(db.Model): # to be able to use sorted containers self.created = kwargs.get('created', datetime.now(timezone.utc)) super().__init__(**kwargs) + +def on_update_time(mapper, connection, thing_obj): + thing_obj.updated = datetime.now() + +def update_timestamp(thing_obj): + event.listen(thing_obj, 'before_update', on_update_time) From 9a488887f585733eb9b61dd963f553d561947523 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 16:25:46 +0200 Subject: [PATCH 08/20] modify devices models for add listeners --- ereuse_devicehub/resources/device/models.py | 58 ++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index 028a8bf6..3eb445d9 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -28,7 +28,7 @@ from teal.resource import url_for_resource from ereuse_devicehub.db import db from ereuse_devicehub.resources.enums import BatteryTechnology, CameraFacing, ComputerChassis, \ DataStorageInterface, DisplayTech, PrinterTechnology, RamFormat, RamInterface, Severity, TransferState -from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing +from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing, update_timestamp from ereuse_devicehub.resources.user.models import User @@ -881,3 +881,59 @@ class Manufacturer(db.Model): 'COPY common.manufacturer FROM STDIN (FORMAT csv)', f ) + + + +update_timestamp(Computer) +update_timestamp(Desktop) +update_timestamp(Laptop) +update_timestamp(Server) +update_timestamp(Monitor) +update_timestamp(ComputerMonitor) +update_timestamp(TelevisionSet) +update_timestamp(Projector) +update_timestamp(Mobile) +update_timestamp(Smartphone) +update_timestamp(Tablet) +update_timestamp(Cellphone) +update_timestamp(Component) +update_timestamp(GraphicCard) +update_timestamp(DataStorage) +update_timestamp(HardDrive) +update_timestamp(SolidStateDrive) +update_timestamp(Motherboard) +update_timestamp(NetworkAdapter) +update_timestamp(Processor) +update_timestamp(RamModule) +update_timestamp(SoundCard) +update_timestamp(Display) +update_timestamp(Battery) +update_timestamp(Camera) +update_timestamp(ComputerAccessory) +update_timestamp(SAI) +update_timestamp(Keyboard) +update_timestamp(Mouse) +update_timestamp(MemoryCardReader) +update_timestamp(Networking) +update_timestamp(Router) +update_timestamp(Switch) +update_timestamp(Hub) +update_timestamp(WirelessAccessPoint) +update_timestamp(Printer) +update_timestamp(LabelPrinter) +update_timestamp(Sound) +update_timestamp(Microphone) +update_timestamp(Video) +update_timestamp(VideoScaler) +update_timestamp(Videoconference) +update_timestamp(Cooking) +update_timestamp(Mixer) +update_timestamp(DIYAndGardening) +update_timestamp(Drill) +update_timestamp(PackOfScrewdrivers) +update_timestamp(Home) +update_timestamp(Dehumidifier) +update_timestamp(Stairs) +update_timestamp(Recreation) +update_timestamp(Bike) +update_timestamp(Racket) From 7313f7cf73f124082560bc3a9546cae1a6f87b87 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 16:26:37 +0200 Subject: [PATCH 09/20] fixed test --- tests/test_snapshot.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 10ec93d2..ead63703 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -115,13 +115,11 @@ def test_snapshot_update_timefield_updated(user: UserClient): RateComputer.t), perform_second_snapshot=False) computer2 = file('2-second-device-with-components-of-first.snapshot') - pc1_id = snapshot['device']['id'] - pc1, _ = user.get(res=m.Device, item=pc1_id) snapshot_and_check(user, computer2, action_types=('Remove', 'RateComputer'), perform_second_snapshot=False) pc1_id = snapshot['device']['id'] pc1, _ = user.get(res=m.Device, item=pc1_id) - assert pc1['updated'] != snapshot['updated'] + assert pc1['updated'] != snapshot['device']['updated'] @pytest.mark.mvp From 195c5265e4d0df16c3059f4eb46fde21bb973a54 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 16:30:53 +0200 Subject: [PATCH 10/20] document new function --- ereuse_devicehub/resources/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ereuse_devicehub/resources/models.py b/ereuse_devicehub/resources/models.py index 74e1e6b4..d6fafc78 100644 --- a/ereuse_devicehub/resources/models.py +++ b/ereuse_devicehub/resources/models.py @@ -36,8 +36,11 @@ class Thing(db.Model): self.created = kwargs.get('created', datetime.now(timezone.utc)) super().__init__(**kwargs) + def on_update_time(mapper, connection, thing_obj): + """ This function update the stamptime of field updated """ thing_obj.updated = datetime.now() def update_timestamp(thing_obj): + """ This function launch a event than listen like a signal when some object is saved """ event.listen(thing_obj, 'before_update', on_update_time) From e00c3f576c82c96be921c515ed3abdb945862f58 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 16:31:54 +0200 Subject: [PATCH 11/20] document new function --- tests/test_snapshot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index ead63703..c0b56686 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -393,6 +393,7 @@ def test_erase_privacy_standards_endtime_sort(user: UserClient): assert _snapshot1['type'] == _snapshot2['type'] == 'Snapshot' get_snapshot, _ = user.get(res=Action, item=_snapshot2['id']) assert get_snapshot['actions'][0]['endTime'] == '2018-06-01T07:14:00+00:00' + import pdb; pdb.set_trace() assert snapshot == get_snapshot erasure, _ = user.get(res=Action, item=erasure1['id']) assert len(erasure['steps']) == 2 From 3988079b01368c01ecb443cefee29a873d170744 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 16:32:16 +0200 Subject: [PATCH 12/20] drop pdb --- tests/test_snapshot.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index c0b56686..ead63703 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -393,7 +393,6 @@ def test_erase_privacy_standards_endtime_sort(user: UserClient): assert _snapshot1['type'] == _snapshot2['type'] == 'Snapshot' get_snapshot, _ = user.get(res=Action, item=_snapshot2['id']) assert get_snapshot['actions'][0]['endTime'] == '2018-06-01T07:14:00+00:00' - import pdb; pdb.set_trace() assert snapshot == get_snapshot erasure, _ = user.get(res=Action, item=erasure1['id']) assert len(erasure['steps']) == 2 From 0c5897a06c463e6293a19ce9e9f2d168ab22c4ad Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Fri, 16 Oct 2020 16:42:43 +0200 Subject: [PATCH 13/20] fixed test of devices --- tests/test_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_device.py b/tests/test_device.py index 685b08b0..60389d8f 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -53,7 +53,7 @@ def test_device_model(): # Removing a component from pc doesn't delete the component pc.components.remove(net) db.session.commit() - pc = d.Device.query.first() # this is the same as querying for d.Desktop directly + pc = d.Device.query.filter_by(id=pc.id).first() # this is the same as querying for d.Desktop directly assert pc.components == {graphic} network_adapter = d.NetworkAdapter.query.one() assert network_adapter not in pc.components From 1400d292ce61c0b9f57dbc3a6162ee1ecaa4a527 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Tue, 27 Oct 2020 21:29:38 +0100 Subject: [PATCH 14/20] refactoring --- ereuse_devicehub/resources/device/models.py | 57 +-------------------- ereuse_devicehub/resources/models.py | 8 +-- 2 files changed, 6 insertions(+), 59 deletions(-) diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index 3eb445d9..682327bb 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -28,7 +28,7 @@ from teal.resource import url_for_resource from ereuse_devicehub.db import db from ereuse_devicehub.resources.enums import BatteryTechnology, CameraFacing, ComputerChassis, \ DataStorageInterface, DisplayTech, PrinterTechnology, RamFormat, RamInterface, Severity, TransferState -from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing, update_timestamp +from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing, listener_reset_field_updated_in_actual_time from ereuse_devicehub.resources.user.models import User @@ -883,57 +883,4 @@ class Manufacturer(db.Model): ) - -update_timestamp(Computer) -update_timestamp(Desktop) -update_timestamp(Laptop) -update_timestamp(Server) -update_timestamp(Monitor) -update_timestamp(ComputerMonitor) -update_timestamp(TelevisionSet) -update_timestamp(Projector) -update_timestamp(Mobile) -update_timestamp(Smartphone) -update_timestamp(Tablet) -update_timestamp(Cellphone) -update_timestamp(Component) -update_timestamp(GraphicCard) -update_timestamp(DataStorage) -update_timestamp(HardDrive) -update_timestamp(SolidStateDrive) -update_timestamp(Motherboard) -update_timestamp(NetworkAdapter) -update_timestamp(Processor) -update_timestamp(RamModule) -update_timestamp(SoundCard) -update_timestamp(Display) -update_timestamp(Battery) -update_timestamp(Camera) -update_timestamp(ComputerAccessory) -update_timestamp(SAI) -update_timestamp(Keyboard) -update_timestamp(Mouse) -update_timestamp(MemoryCardReader) -update_timestamp(Networking) -update_timestamp(Router) -update_timestamp(Switch) -update_timestamp(Hub) -update_timestamp(WirelessAccessPoint) -update_timestamp(Printer) -update_timestamp(LabelPrinter) -update_timestamp(Sound) -update_timestamp(Microphone) -update_timestamp(Video) -update_timestamp(VideoScaler) -update_timestamp(Videoconference) -update_timestamp(Cooking) -update_timestamp(Mixer) -update_timestamp(DIYAndGardening) -update_timestamp(Drill) -update_timestamp(PackOfScrewdrivers) -update_timestamp(Home) -update_timestamp(Dehumidifier) -update_timestamp(Stairs) -update_timestamp(Recreation) -update_timestamp(Bike) -update_timestamp(Racket) +listener_reset_field_updated_in_actual_time(Device) diff --git a/ereuse_devicehub/resources/models.py b/ereuse_devicehub/resources/models.py index d6fafc78..e079269f 100644 --- a/ereuse_devicehub/resources/models.py +++ b/ereuse_devicehub/resources/models.py @@ -37,10 +37,10 @@ class Thing(db.Model): super().__init__(**kwargs) -def on_update_time(mapper, connection, thing_obj): +def update_object_timestamp(mapper, connection, thing_obj): """ This function update the stamptime of field updated """ - thing_obj.updated = datetime.now() + thing_obj.updated = datetime.now(timezone.utc) -def update_timestamp(thing_obj): +def listener_reset_field_updated_in_actual_time(thing_obj): """ This function launch a event than listen like a signal when some object is saved """ - event.listen(thing_obj, 'before_update', on_update_time) + event.listen(thing_obj, 'before_update', update_object_timestamp, propagate=True) From 954dfa95a1ef8659fcf1a797d13b0f920196f0a2 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 29 Oct 2020 11:59:53 +0100 Subject: [PATCH 15/20] check in test this bug about time in the filename --- tests/test_snapshot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 42792c2f..4348d408 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -493,6 +493,7 @@ def test_save_snapshot_in_file(app: Devicehub, user: UserClient): snapshot = {'software': '', 'version': '', 'uuid': ''} if files: path_snapshot = os.path.join(tmp_snapshots, files[0]) + assert not "0001-01-01 00:00:00" in path_snapshot with open(path_snapshot) as file_snapshot: snapshot = json.loads(file_snapshot.read()) From b2c258b69929fb12ce2a49a85fcfa0294307c0df Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 29 Oct 2020 12:10:12 +0100 Subject: [PATCH 16/20] fixed mark time correctly in the name file of json --- ereuse_devicehub/resources/action/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ereuse_devicehub/resources/action/views.py b/ereuse_devicehub/resources/action/views.py index 689cb942..de99781c 100644 --- a/ereuse_devicehub/resources/action/views.py +++ b/ereuse_devicehub/resources/action/views.py @@ -32,7 +32,7 @@ def save_json(req_json, tmp_snapshots, user): month = now.month day = now.day hour = now.hour - minutes = now.min + minutes = now.minute name_file = f"{year}-{month}-{day}-{hour}-{minutes}_{user}_{uuid}.json" path_name = os.path.join(tmp_snapshots, name_file) From 785d8091ea30948ec380c6c0f228b9aeb489fba3 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 29 Oct 2020 12:39:11 +0100 Subject: [PATCH 17/20] adding new test for check the debug file --- tests/test_snapshot.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 42792c2f..2ec4412b 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -502,6 +502,26 @@ def test_save_snapshot_in_file(app: Devicehub, user: UserClient): assert snapshot['version'] == snapshot_no_hid['version'] assert snapshot['uuid'] == uuid +@pytest.mark.mvp +def test_save_snapshot_with_debug(app: Devicehub, user: UserClient): + """ This test check if works the function save_snapshot_in_file """ + tmp_snapshots = app.config['TMP_SNAPSHOTS'] + snapshot_file = file('basic.snapshot.with_debug') + debug = snapshot_file['debug'] + user.post(res=Snapshot, data=snapshot_file) + + uuid = snapshot_file['uuid'] + files = [x for x in os.listdir(tmp_snapshots) if uuid in x] + + if files: + path_snapshot = os.path.join(tmp_snapshots, files[0]) + with open(path_snapshot) as file_snapshot: + snapshot = json.loads(file_snapshot.read()) + + os.remove(path_snapshot) + + assert snapshot['debug'] == debug + @pytest.mark.mvp def test_backup_snapshot_with_errors(app: Devicehub, user: UserClient): From 5f68803d9f60c2e71081fa5d83bfc6811222d385 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 29 Oct 2020 16:09:02 +0100 Subject: [PATCH 18/20] adding the directory structure for save all jsons --- ereuse_devicehub/resources/action/views.py | 28 +++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/ereuse_devicehub/resources/action/views.py b/ereuse_devicehub/resources/action/views.py index 689cb942..f16f8947 100644 --- a/ereuse_devicehub/resources/action/views.py +++ b/ereuse_devicehub/resources/action/views.py @@ -2,6 +2,7 @@ import os import json +import shutil from datetime import datetime from distutils.version import StrictVersion from uuid import UUID @@ -35,10 +36,14 @@ def save_json(req_json, tmp_snapshots, user): minutes = now.min name_file = f"{year}-{month}-{day}-{hour}-{minutes}_{user}_{uuid}.json" - path_name = os.path.join(tmp_snapshots, name_file) + path_dir_base = os.path.join(tmp_snapshots, user) + path_errors = os.path.join(path_dir_base, 'errors') + path_fixeds = os.path.join(path_dir_base, 'fixeds') + path_name = os.path.join(path_errors, name_file) - if not os.path.isdir(tmp_snapshots): - os.system('mkdir -p {}'.format(tmp_snapshots)) + if not os.path.isdir(path_dir_base): + os.system(f'mkdir -p {path_errors}') + os.system(f'mkdir -p {path_fixeds}') with open(path_name, 'w') as snapshot_file: snapshot_file.write(json.dumps(req_json)) @@ -46,12 +51,23 @@ def save_json(req_json, tmp_snapshots, user): return path_name +def move_json(tmp_snapshots, path_name, user): + """ + This function move the json than it's correct + """ + path_dir_base = os.path.join(tmp_snapshots, user) + if os.path.isfile(path_name): + shutil.copy(path_name, path_dir_base) + os.remove(path_name) + + class ActionView(View): def post(self): """Posts an action.""" json = request.get_json(validate=False) tmp_snapshots = app.config['TMP_SNAPSHOTS'] path_snapshot = save_json(json, tmp_snapshots, g.user.email) + json.pop('debug', None) if not json or 'type' not in json: raise ValidationError('Resource needs a type.') # todo there should be a way to better get subclassess resource @@ -60,13 +76,13 @@ class ActionView(View): a = resource_def.schema.load(json) if json['type'] == Snapshot.t: response = self.snapshot(a, resource_def) - os.remove(path_snapshot) + move_json(tmp_snapshots, path_snapshot, g.user.email) return response if json['type'] == VisualTest.t: pass # TODO JN add compute rate with new visual test and old components device if json['type'] == InitTransfer.t: - os.remove(path_snapshot) + move_json(tmp_snapshots, path_snapshot, g.user.email) return self.transfer_ownership() Model = db.Model._decl_class_registry.data[json['type']]() action = Model(**a) @@ -75,7 +91,7 @@ class ActionView(View): ret = self.schema.jsonify(action) ret.status_code = 201 db.session.commit() - os.remove(path_snapshot) + move_json(tmp_snapshots, path_snapshot, g.user.email) return ret def one(self, id: UUID): From ed32f691f729232d2322393e2ffb41515fc8de6d Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 29 Oct 2020 16:09:38 +0100 Subject: [PATCH 19/20] fixing test for new structure and adding debug test --- tests/test_snapshot.py | 59 +++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 2ec4412b..6b85d94d 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -1,5 +1,6 @@ import os import json +import shutil import pytest from datetime import datetime, timedelta, timezone @@ -483,20 +484,22 @@ def test_pc_2(user: UserClient): @pytest.mark.mvp def test_save_snapshot_in_file(app: Devicehub, user: UserClient): """ This test check if works the function save_snapshot_in_file """ - tmp_snapshots = app.config['TMP_SNAPSHOTS'] snapshot_no_hid = file('basic.snapshot.nohid') + tmp_snapshots = app.config['TMP_SNAPSHOTS'] + path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors') + save_json(snapshot_no_hid, tmp_snapshots, user.user['email']) uuid = snapshot_no_hid['uuid'] - files = [x for x in os.listdir(tmp_snapshots) if uuid in x] + files = [x for x in os.listdir(path_dir_base) if uuid in x] snapshot = {'software': '', 'version': '', 'uuid': ''} if files: - path_snapshot = os.path.join(tmp_snapshots, files[0]) + path_snapshot = os.path.join(path_dir_base, files[0]) with open(path_snapshot) as file_snapshot: snapshot = json.loads(file_snapshot.read()) - os.remove(path_snapshot) + shutil.rmtree(tmp_snapshots) assert snapshot['software'] == snapshot_no_hid['software'] assert snapshot['version'] == snapshot_no_hid['version'] @@ -505,20 +508,23 @@ def test_save_snapshot_in_file(app: Devicehub, user: UserClient): @pytest.mark.mvp def test_save_snapshot_with_debug(app: Devicehub, user: UserClient): """ This test check if works the function save_snapshot_in_file """ - tmp_snapshots = app.config['TMP_SNAPSHOTS'] snapshot_file = file('basic.snapshot.with_debug') debug = snapshot_file['debug'] user.post(res=Snapshot, data=snapshot_file) - uuid = snapshot_file['uuid'] - files = [x for x in os.listdir(tmp_snapshots) if uuid in x] + tmp_snapshots = app.config['TMP_SNAPSHOTS'] + path_dir_base = os.path.join(tmp_snapshots, user.user['email']) + uuid = snapshot_file['uuid'] + files = [x for x in os.listdir(path_dir_base) if uuid in x] + + snapshot = {'debug': ''} if files: - path_snapshot = os.path.join(tmp_snapshots, files[0]) + path_snapshot = os.path.join(path_dir_base, files[0]) with open(path_snapshot) as file_snapshot: snapshot = json.loads(file_snapshot.read()) - os.remove(path_snapshot) + shutil.rmtree(tmp_snapshots) assert snapshot['debug'] == debug @@ -527,6 +533,7 @@ def test_save_snapshot_with_debug(app: Devicehub, user: UserClient): def test_backup_snapshot_with_errors(app: Devicehub, user: UserClient): """ This test check if the file snapshot is create when some snapshot is wrong """ tmp_snapshots = app.config['TMP_SNAPSHOTS'] + path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors') snapshot_no_hid = file('basic.snapshot.badly_formed') uuid = snapshot_no_hid['uuid'] @@ -534,13 +541,13 @@ def test_backup_snapshot_with_errors(app: Devicehub, user: UserClient): with pytest.raises(KeyError): response = user.post(res=Snapshot, data=snapshot_no_hid) - files = [x for x in os.listdir(tmp_snapshots) if uuid in x] + files = [x for x in os.listdir(path_dir_base) if uuid in x] if files: - path_snapshot = os.path.join(tmp_snapshots, files[0]) + path_snapshot = os.path.join(path_dir_base, files[0]) with open(path_snapshot) as file_snapshot: snapshot = json.loads(file_snapshot.read()) - os.remove(path_snapshot) + shutil.rmtree(tmp_snapshots) assert snapshot['software'] == snapshot_no_hid['software'] assert snapshot['version'] == snapshot_no_hid['version'] @@ -551,6 +558,7 @@ def test_backup_snapshot_with_errors(app: Devicehub, user: UserClient): def test_snapshot_failed_missing_cpu_benchmark(app: Devicehub, user: UserClient): """ This test check if the file snapshot is create when some snapshot is wrong """ tmp_snapshots = app.config['TMP_SNAPSHOTS'] + path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors') snapshot_error = file('failed.snapshot.500.missing-cpu-benchmark') uuid = snapshot_error['uuid'] @@ -558,13 +566,13 @@ def test_snapshot_failed_missing_cpu_benchmark(app: Devicehub, user: UserClient) with pytest.raises(TypeError): user.post(res=Snapshot, data=snapshot_error) - files = [x for x in os.listdir(tmp_snapshots) if uuid in x] + files = [x for x in os.listdir(path_dir_base) if uuid in x] if files: - path_snapshot = os.path.join(tmp_snapshots, files[0]) + path_snapshot = os.path.join(path_dir_base, files[0]) with open(path_snapshot) as file_snapshot: snapshot = json.loads(file_snapshot.read()) - os.remove(path_snapshot) + shutil.rmtree(tmp_snapshots) assert snapshot['software'] == snapshot_error['software'] assert snapshot['version'] == snapshot_error['version'] @@ -575,6 +583,7 @@ def test_snapshot_failed_missing_cpu_benchmark(app: Devicehub, user: UserClient) def test_snapshot_failed_missing_hdd_benchmark(app: Devicehub, user: UserClient): """ This test check if the file snapshot is create when some snapshot is wrong """ tmp_snapshots = app.config['TMP_SNAPSHOTS'] + path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors') snapshot_error = file('failed.snapshot.500.missing-hdd-benchmark') uuid = snapshot_error['uuid'] @@ -582,13 +591,13 @@ def test_snapshot_failed_missing_hdd_benchmark(app: Devicehub, user: UserClient) with pytest.raises(TypeError): user.post(res=Snapshot, data=snapshot_error) - files = [x for x in os.listdir(tmp_snapshots) if uuid in x] + files = [x for x in os.listdir(path_dir_base) if uuid in x] if files: - path_snapshot = os.path.join(tmp_snapshots, files[0]) + path_snapshot = os.path.join(path_dir_base, files[0]) with open(path_snapshot) as file_snapshot: snapshot = json.loads(file_snapshot.read()) - os.remove(path_snapshot) + shutil.rmtree(tmp_snapshots) assert snapshot['software'] == snapshot_error['software'] assert snapshot['version'] == snapshot_error['version'] @@ -599,6 +608,7 @@ def test_snapshot_failed_missing_hdd_benchmark(app: Devicehub, user: UserClient) def test_snapshot_failed_null_chassis(app: Devicehub, user: UserClient): """ This test check if the file snapshot is create when some snapshot is wrong """ tmp_snapshots = app.config['TMP_SNAPSHOTS'] + path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors') snapshot_error = file('failed.snapshot.422.null-chassis') uuid = snapshot_error['uuid'] @@ -606,13 +616,13 @@ def test_snapshot_failed_null_chassis(app: Devicehub, user: UserClient): with pytest.raises(TypeError): user.post(res=Snapshot, data=snapshot_error) - files = [x for x in os.listdir(tmp_snapshots) if uuid in x] + files = [x for x in os.listdir(path_dir_base) if uuid in x] if files: - path_snapshot = os.path.join(tmp_snapshots, files[0]) + path_snapshot = os.path.join(path_dir_base, files[0]) with open(path_snapshot) as file_snapshot: snapshot = json.loads(file_snapshot.read()) - os.remove(path_snapshot) + shutil.rmtree(tmp_snapshots) assert snapshot['software'] == snapshot_error['software'] assert snapshot['version'] == snapshot_error['version'] @@ -623,6 +633,7 @@ def test_snapshot_failed_null_chassis(app: Devicehub, user: UserClient): def test_snapshot_failed_missing_chassis(app: Devicehub, user: UserClient): """ This test check if the file snapshot is create when some snapshot is wrong """ tmp_snapshots = app.config['TMP_SNAPSHOTS'] + path_dir_base = os.path.join(tmp_snapshots, user.user['email'], 'errors') snapshot_error = file('failed.snapshot.422.missing-chassis') uuid = snapshot_error['uuid'] @@ -630,13 +641,13 @@ def test_snapshot_failed_missing_chassis(app: Devicehub, user: UserClient): with pytest.raises(TypeError): user.post(res=Snapshot, data=snapshot_error) - files = [x for x in os.listdir(tmp_snapshots) if uuid in x] + files = [x for x in os.listdir(path_dir_base) if uuid in x] if files: - path_snapshot = os.path.join(tmp_snapshots, files[0]) + path_snapshot = os.path.join(path_dir_base, files[0]) with open(path_snapshot) as file_snapshot: snapshot = json.loads(file_snapshot.read()) - os.remove(path_snapshot) + shutil.rmtree(tmp_snapshots) assert snapshot['software'] == snapshot_error['software'] assert snapshot['version'] == snapshot_error['version'] From 2dbcd2e7e2490f84f215b9b77aa103f3e527116a Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 29 Oct 2020 17:50:52 +0100 Subject: [PATCH 20/20] add the snapshot file for test of debug --- tests/files/basic.snapshot.with_debug.yaml | 126 +++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 tests/files/basic.snapshot.with_debug.yaml diff --git a/tests/files/basic.snapshot.with_debug.yaml b/tests/files/basic.snapshot.with_debug.yaml new file mode 100644 index 00000000..0ccb912c --- /dev/null +++ b/tests/files/basic.snapshot.with_debug.yaml @@ -0,0 +1,126 @@ +{ + "elapsed": 4, + "type": "Snapshot", + "uuid": "0c822fb7-6e51-4781-86cf-994bd306212e", + "software": "Workbench", + "closed": false, + "endTime": "2018-07-05T11:57:17.284891+00:00", + "components": [ + { + "type": "NetworkAdapter", + "model": "82567LM-3 Gigabit Network Connection", + "speed": 1000, + "serialNumber": "00:23:24:0d:86:28", + "manufacturer": "Intel Corporation", + "wireless": false, + "actions": [] + }, + { + "type": "NetworkAdapter", + "model": "82541PI Gigabit Ethernet Controller", + "speed": 1000, + "serialNumber": "00:0e:0c:b6:f2:91", + "manufacturer": "Intel Corporation", + "wireless": false, + "actions": [] + }, + { + "cores": 4, + "type": "Processor", + "model": "Intel Core2 Quad CPU Q8400 @ 2.66GHz", + "speed": 1.9980000000000002, + "serialNumber": null, + "manufacturer": "Intel Corp.", + "actions": [ + { + "elapsed": 0, + "rate": 6665.7, + "type": "BenchmarkProcessor" + } + ], + "address": 64 + }, + { + "type": "GraphicCard", + "model": "4 Series Chipset Integrated Graphics Controller", + "serialNumber": null, + "manufacturer": "Intel Corporation", + "actions": [], + "memory": 256.0 + }, + { + "type": "SoundCard", + "model": "82801JD/DO HD Audio Controller", + "serialNumber": null, + "manufacturer": "Intel Corporation", + "actions": [] + }, + { + "size": 2048, + "interface": "DDR3", + "type": "RamModule", + "model": "16JTF25664AZ-1G4F", + "speed": 1333.0, + "serialNumber": "F8482E29", + "format": "DIMM", + "manufacturer": "JEDEC ID:80 2C", + "actions": [] + }, + { + "size": 2048, + "interface": "DDR3", + "type": "RamModule", + "model": "16JTF25664AZ-1G4F", + "speed": 1333.0, + "serialNumber": "62072F30", + "format": "DIMM", + "manufacturer": "JEDEC ID:80 2C", + "actions": [] + }, + { + "size": 238475, + "interface": "ATA", + "type": "HardDrive", + "model": "ST3250318AS", + "serialNumber": "9VY6HBKE", + "manufacturer": "Seagate", + "actions": [ + { + "elapsed": 0, + "type": "TestDataStorage", + "status": "Unspecified Error. Self-test not started.", + "severity": "Error", + "length": "Short" + }, + { + "type": "BenchmarkDataStorage", + "elapsed": 16, + "readSpeed": 66.2, + "writeSpeed": 21.8 + } + ] + }, + { + "slots": 0, + "pcmcia": 0, + "type": "Motherboard", + "model": "3646h", + "serialNumber": "CZC03217S7", + "firewire": 0, + "manufacturer": "Hewlett-Packard", + "actions": [], + "serial": 0, + "usb": 8 + } + ], + "version": "11.0a3", + "device": { + "type": "Desktop", + "model": "HP Compaq 8000 Elite SFF", + "chassis": "Tower", + "serialNumber": "CZC03217S7", + "manufacturer": "Hewlett-Packard", + "actions": [] + }, + "debug": "123456789 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 " +}