# -*- coding: utf-8 -*-
# Copyright (C) 2011  Michał Masłowski  <mtjm@mtjm.eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


"""Test communication with h-source."""


import unittest


#: A dictionary mapping triplets of domain, request path and post data
#: to response body.
#:
#: The data was obtained from h-node.com and includes only a subset
#: used for tests.
_RESPONSES = {
	('example.org/', 'download/all/en', None): """<?xml version='1.0' encoding='UTF-8'?>
<hardware>
	<general_information>
		<credits>h-node project</credits>
		<link>www.h-node.com</link>
		<date>2011-12-03 03:47:50</date>
		<license>The contents of this page are in the Public Domain. (see the CC0 page at http://creativecommons.org/publicdomain/zero/1.0/ for detailed information). Anyone is free to copy, modify, publish, use, sell, or distribute the text for any purpose, commercial or non-commercial, and by any means.</license>
	</general_information>
	<device>
		<id>8</id>
		<type>wifi</type>
		<model_name>Atheros Communications Inc. AR922X Wireless Network Adapter</model_name>
		<other_names><![CDATA[TP-LINK TL-WN851N
TP-LINK TL-WN861N
D-Link DWA-552 Xtreme N Desktop Adapter]]></other_names>
		<vendorid_productid>168c:0029</vendorid_productid>
		<vendor>Atheros</vendor>
		<kernel_libre>2.6.32-24-generic</kernel_libre>
		<distribution>trisquel_4_0 , trisquel_4_5</distribution>
		<year>2008</year>
		<interface>not-specified</interface>
		<it_works>yes</it_works>
		<driver>ath9k</driver>
		<description><![CDATA[[p]This is an Atheros AR9223 chipset, which uses the officially supported free ath9k Linux driver.[/p]

[p]The [a]http://www.tp-link.com/en/products/prodetail.aspx?id=389|TP-LINK TL-WN851N[/a] is a PCI card.[/p]

[p]The [a]http://www.tp-link.com/en/products/prodetail.aspx?id=717|TP-LINK TL-WN861N[/a] is a Mini-PCI card.[/p]

[p]The [a]http://www.dlink.com/products/?pid=531|D-Link DWA-552 Xtreme N Desktop Adapter[/a] is a PCI card.[/p]

[p]This chipset has been tested with IEEE 802.11g and 802.11n networks, unsecured and secured (WPA2-PSK).[/p]

[code]$ lspci -nnkd 168c:0029
06:02.0 Network controller [0280]: Atheros Communications Inc. AR922X Wireless Network Adapter [168c:0029] (rev 01)
        Subsystem: Atheros Communications Inc. Device [168c:2091]
        Kernel driver in use: ath9k
        Kernel modules: ath9k[/code]]]></description>
		<link>http://www.h-node.com/wifi/view/en/8/Atheros-Communications-Inc--AR922X-Wireless-Network-Adapter</link>
		<created_by>http://www.h-node.com/wifi/history/en/8</created_by>
	</device>
	<device>
		<id>346</id>
		<type>ethernet-card</type>
		<model_name>MCP67 Ethernet  (rev a2)</model_name>
		<other_names><![CDATA[]]></other_names>
		<vendorid_productid>10de:054c</vendorid_productid>
		<vendor>NVIDIA</vendor>
		<kernel_libre>2.6.32-27-generic</kernel_libre>
		<distribution>trisquel_4_0</distribution>
		<year>not-specified</year>
		<interface>not-specified</interface>
		<it_works>yes</it_works>
		<driver>forcedeth</driver>
		<description><![CDATA[]]></description>
		<link>http://www.h-node.com/ethernetcards/view/en/346/MCP67-Ethernet---rev-a2-</link>
		<created_by>http://www.h-node.com/ethernetcards/history/en/346</created_by>
	</device>
	<device>
		<id>380</id>
		<type>videocard</type>
		<model_name>G71 [GeForce 7300 GS]  (rev a1)</model_name>
		<other_names><![CDATA[]]></other_names>
		<vendorid_productid>10de:01df</vendorid_productid>
		<vendor>NVIDIA</vendor>
		<kernel_libre>3.0.3-1</kernel_libre>
		<distribution>parabola</distribution>
		<year>not-specified</year>
		<interface>PCI-E</interface>
		<it_works>works_with_3D</it_works>
		<driver>nouveau</driver>
		<description><![CDATA[KWin OpenGL compositing is slow, some OpenGL using programs might hang the machine, and Nouveau doesn&#039;t recommend reporting bugs for NV4x 3d driver yet. No problems when not using 3d acceleration.]]></description>
		<link>http://www.h-node.com/videocards/view/en/380/G71--GeForce-7300-GS----rev-a1-</link>
		<created_by>http://www.h-node.com/videocards/history/en/380</created_by>
	</device>
	<device>
		<id>101</id>
		<type>soundcard</type>
		<model_name>MCP67 High Definition Audio (rev a1)</model_name>
		<other_names><![CDATA[]]></other_names>
		<vendorid_productid>10de:055c</vendorid_productid>
		<vendor>nVidia-Corporation</vendor>
		<kernel_libre>2.6.32-27-generic</kernel_libre>
		<distribution>trisquel_4_0 </distribution>
		<year>not-specified</year>
		<interface>not-specified</interface>
		<it_works>yes</it_works>
		<driver>HDA Intel</driver>
		<description><![CDATA[[p]It works out of the box with Trisquel 4.o Taranis![/p]

[p][b]lspci -nnk[/b] output[/p]

[p]00:07.0 Audio device [0403]: nVidia Corporation MCP67 High Definition Audio [10de:055c] (rev a1)[/p]
[p]Kernel driver in use: HDA Intel[/p]
[p]Kernel modules: snd-hda-intel[/p]]]></description>
		<link>http://www.h-node.com/soundcards/view/en/101/MCP67-High-Definition-Audio--rev-a1-</link>
		<created_by>http://www.h-node.com/soundcards/history/en/101</created_by>
	</device>
	<device>
		<id>229</id>
		<type>scanner</type>
		<model_name>Canon CanoScan LiDE 110</model_name>
		<other_names><![CDATA[]]></other_names>
		<vendorid_productid>04a9:1909</vendorid_productid>
		<vendor>Canon-Inc.</vendor>
		<kernel_libre>2.6.32-31-generic</kernel_libre>
		<distribution>parabola , trisquel_4_0 </distribution>
		<year>2010</year>
		<interface>USB</interface>
		<compatibility>A-Full</compatibility>
		<driver>genesys (1.0-62)</driver>
		<description><![CDATA[[list]
[*] Supported by SANE: [a]http://www.sane-project.org/sane-mfgs.html[/a][/*]
[*] To install, I followed the instructions here: [a]http://robsworldoftech.blogspot.com/2010/09/canon-canoscan-lide-100-on-ubuntu-or.html[/a][/*]
[*] Note: Just change to product or device id to &quot;1909&quot;[/*]
[*] Also tried it on Ubuntu 9.10 following the same procedure, and it worked[/*]
[*] Hardware buttons don&#039;t work, though[/*]
[/list]

[p]On Parabola GNU/Linux-libre with kernel 2.6.39.3-1 and SANE 1.0.22-2 it needed just unlocking and connecting the device to scan with Skanlite.[/p]]]></description>
		<link>http://www.h-node.com/scanners/view/en/229/Canon-CanoScan-LiDE-110</link>
		<created_by>http://www.h-node.com/scanners/history/en/229</created_by>
	</device>
</hardware>
""",
	}


#: A fragment of h-node.com database with both notebook and
#: non-notebook devices.
_WITH_NOTEBOOK = """<?xml version='1.0' encoding='UTF-8'?>
<hardware>
	<general_information>
		<credits>h-node project</credits>
		<link>www.h-node.com</link>
		<date>2011-12-03 03:47:50</date>
		<license>The contents of this page are in the Public Domain. (see the CC0 page at http://creativecommons.org/publicdomain/zero/1.0/ for detailed information). Anyone is free to copy, modify, publish, use, sell, or distribute the text for any purpose, commercial or non-commercial, and by any means.</license>
	</general_information>
	<device>
		<id>53</id>
		<type>3G-card</type>
		<model_name>CDU-680</model_name>
		<other_names><![CDATA[]]></other_names>
		<vendorid_productid>16d8:6803</vendorid_productid>
		<vendor>CMOTECH-Co.-Ltd.</vendor>
		<kernel_libre>2.6.32-24-generic</kernel_libre>
		<distribution>trisquel_4_0 </distribution>
		<year>2009</year>
		<interface>USB</interface>
		<it_works>yes</it_works>
		<driver></driver>
		<description><![CDATA[[tab lang=en]
[b]IUSACELL - Mexico[/b]

[p]In order to work this card needs to be on Hybrid mode.[/p]
Then run this on the terminal:
[code]sudo modprobe usbserial vendor=0x16d8 product=0x6803[/code]
[/tab]

[tab lang=es]
[b]IUSACELL - Mexico[/b]

[p]Para funcionar, la tarjeta necesita estar en modo Hibrido.[/p]
Despu&eacute;s ejecute esta orden en la terminal:
[code]sudo modprobe usbserial vendor=0x16d8 product=0x6803[/code]
[/tab]]]></description>
		<link>http://www.h-node.com/threegcards/view/en/53/CDU-680</link>
		<created_by>http://www.h-node.com/threegcards/history/en/53</created_by>
	</device>
	<device>
		<id>4</id>
		<type>notebook</type>
		<subtype>notebook</subtype>
		<architecture>x86-64/amd64</architecture>
		<free_bios>no</free_bios>
		<can_free_systems_be_installed>not-specified</can_free_systems_be_installed>
		<model_name>Pavillion dv6530 el</model_name>
		<vendor>Hewlett-Packard</vendor>
		<kernel_libre>2.6.35-28-generic</kernel_libre>
		<distribution>trisquel_4_5 </distribution>
		<year>2007</year>
		<compatibility>D-bronze</compatibility>
		<wifi_card>BCM4311 (rev 02)</wifi_card>
		<videocard>GeForce 8400M GS (rev a1)</videocard>
		<webcam></webcam>
		<wifi_works>no</wifi_works>
		<videocard_works>yes_with_3D</videocard_works>
		<webcam_works>no</webcam_works>
		<description><![CDATA[[h1]Overview[/h1]

[p]The notebook works fine except for the wifi card and the webcam that do not work. The video card works with the nouveau driver with 3D acceleration[/p]

[h1]About webcam[/h1]

[p]I was not able to find out the webcam model and I was not able to make it work.[/p]]]></description>
		<link>http://www.h-node.com/notebooks/view/en/4/Pavillion-dv6530-el</link>
		<created_by>http://www.h-node.com/notebooks/history/en/4</created_by>
	</device>
</hardware>
"""


#: A fragment with devices without vendorid:productid.
_WITH_NOKEY = """<?xml version='1.0' encoding='UTF-8'?>
<hardware>
	<general_information>
		<credits>h-node project</credits>
		<link>www.h-node.com</link>
		<date>2011-12-03 03:47:50</date>
		<license>The contents of this page are in the Public Domain. (see the CC0 page at http://creativecommons.org/publicdomain/zero/1.0/ for detailed information). Anyone is free to copy, modify, publish, use, sell, or distribute the text for any purpose, commercial or non-commercial, and by any means.</license>
	</general_information>
	<device>
		<id>458</id>
		<type>modem</type>
		<model_name>Xilinx Corporation Device 0300</model_name>
		<other_names><![CDATA[Traverse Technologies Solos ADSL2+ PCI
]]></other_names>
		<vendorid_productid></vendorid_productid>
		<vendor>Xilinx-Corporation</vendor>
		<kernel_libre>2.6.35-28-generic</kernel_libre>
		<distribution>trisquel_4_5 </distribution>
		<year>not-specified</year>
		<interface>PCI</interface>
		<it_works>yes</it_works>
		<driver>solos_pci</driver>
		<description><![CDATA[[p]I successfully connected to the Internet with this device and pppd with pppoatm.so loaded, and the connection then used to add this entry to h-node.[/p]

[code]trisquel@trisquel:~$ uname -a
Linux trisquel 2.6.35-28-generic #50trisquel2-Ubuntu SMP Tue May 3 02:42:36 UTC 2011 x86_64 GNU/Linux

trisquel@trisquel:~$ lspci -vvnnd 10ee:0300 
04:08.0 ATM network controller [0203]: Xilinx Corporation Device [10ee:0300]
	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium &gt;TAbort- &lt;TAbort- &lt;MAbort- &gt;SERR- &lt;PERR- INTx-
	Latency: 32
	Interrupt: pin A routed to IRQ 20
	Region 0: Memory at 90118000 (32-bit, non-prefetchable) [size=128]
	Region 1: Memory at 90110000 (32-bit, non-prefetchable) [size=32K]
	Kernel driver in use: solos
	Kernel modules: solos-pci
[/code]]]></description>
		<link>http://www.h-node.com/modems/view/en/458/Xilinx-Corporation-Device-0300</link>
		<created_by>http://www.h-node.com/modems/history/en/458</created_by>
	</device>
	<device>
		<id>53</id>
		<type>3G-card</type>
		<model_name>CDU-680</model_name>
		<other_names><![CDATA[]]></other_names>
		<vendorid_productid>16d8:6803</vendorid_productid>
		<vendor>CMOTECH-Co.-Ltd.</vendor>
		<kernel_libre>2.6.32-24-generic</kernel_libre>
		<distribution>trisquel_4_0 </distribution>
		<year>2009</year>
		<interface>USB</interface>
		<it_works>yes</it_works>
		<driver></driver>
		<description><![CDATA[[tab lang=en]
[b]IUSACELL - Mexico[/b]

[p]In order to work this card needs to be on Hybrid mode.[/p]
Then run this on the terminal:
[code]sudo modprobe usbserial vendor=0x16d8 product=0x6803[/code]
[/tab]

[tab lang=es]
[b]IUSACELL - Mexico[/b]

[p]Para funcionar, la tarjeta necesita estar en modo Hibrido.[/p]
Despu&eacute;s ejecute esta orden en la terminal:
[code]sudo modprobe usbserial vendor=0x16d8 product=0x6803[/code]
[/tab]]]></description>
		<link>http://www.h-node.com/threegcards/view/en/53/CDU-680</link>
		<created_by>http://www.h-node.com/threegcards/history/en/53</created_by>
	</device>
	<device>
		<id>74</id>
		<type>soundcard</type>
		<model_name>CK804 AC 97 Audio Controller (rev a2)</model_name>
		<other_names><![CDATA[]]></other_names>
		<vendor>NVIDIA</vendor>
		<kernel_libre></kernel_libre>
		<distribution>trisquel_4_0 </distribution>
		<year>not-specified</year>
		<interface>not-specified</interface>
		<it_works>yes</it_works>
		<driver>snd-intel8x0</driver>
		<description><![CDATA[]]></description>
		<link>http://www.h-node.com/soundcards/view/en/74/CK804-AC-97-Audio-Controller--rev-a2-</link>
		<created_by>http://www.h-node.com/soundcards/history/en/74</created_by>
	</device>
</hardware>
"""


def make_client(responses):
	"""Return an `hclient.hlibrary.HTTPClient`-like class using
	specified dictionary for responses.
	"""
	from hclient.hlibrary import HTTPClient

	class FixedHTTPClient(HTTPClient):

		"""A replacement for `hclient.hlibrary.HTTPClient` using fixed
		strings as responses.
		"""

		def perform(self, request_path, post=None):
			"""Return a pair of response status code and document body."""
			# Make the post dictionary hashable.
			if post is not None:
				post = tuple(sorted(post.items()))
			try:
				return True, responses[self.domain, request_path, post]
			except KeyError:
				print repr((self.domain, request_path, post))
				return False, ""

	return FixedHTTPClient


class HSourceTestCase(unittest.TestCase):

	"""Tests for communication h-source, using fixed responses."""

	def test_sync(self):
		"""Test synchronization with h-source"""
		from hclient.hlibrary import Client
		from hclient.machine import createDevices, parse_lspci
		from tests_hclient.machine import _LSPCI_OUTPUT

		client = Client("example.org", make_client(_RESPONSES))
		client.devices = createDevices(parse_lspci(_LSPCI_OUTPUT), {})
		client.sync()
		# Check that a device not found on the system is not added by sync.
		self.assertFalse("u_04a9:1909" in client.devices)
		# Check that a device included is considered tested on several distros.
		# TODO just compare whole device dictionary after implementing
		# needed methods in Device
		self.assertEquals(["trisquel_4_0 ", " trisquel_4_5"],
						  client.devices["p_168c:0029"][0].getDistributions())
		# Check that the devices are updated.
		for dev in client.devices.itervalues():
			self.assertEquals("update", dev[2])

	def test_unfound_device(self):
		"""Test that having devices not known to server works"""
		from hclient.hlibrary import Client
		from hclient.devices import Device

		client = Client("example.org", make_client(_RESPONSES))
		device = Device()
		client.devices = {"p_10de:0547": [device, 0x0500, "insert", "0"]}
		client.sync()
		self.assertEquals(client.devices,
						  {"p_10de:0547": [device, 0x0500, "insert", "0"]})

	def test_ignore_notebooks(self):
		"""Test that notebooks are ignored"""
		from hclient.hlibrary import get_devices_from_xml
		self.assertEquals(["u_16d8:6803"],
						  get_devices_from_xml(_WITH_NOTEBOOK).keys())

	def test_ignore_nokey(self):
		"""Test that devices without vendorid:productid are ignored"""
		from hclient.hlibrary import get_devices_from_xml
		self.assertEquals(["u_16d8:6803"],
						  get_devices_from_xml(_WITH_NOKEY).keys())

# Local Variables:
# indent-tabs-mode: t
# python-guess-indent: nil
# python-indent: 4
# tab-width: 4
# End:
