1# -*- coding: utf-8 -*-
2# Copyright (c) 2015 Spotify AB
3import sys
4
5if sys.version_info[0] == 2:
6    from io import open
7
8import json
9import os
10import tempfile
11
12from mock import Mock, patch
13import pytest
14import xmltodict
15
16from ramlfications import utils
17
18from .base import UPDATE
19
20
21@pytest.fixture(scope="session")
22def downloaded_xml():
23    return os.path.join(UPDATE, "iana_mime_media_types.xml")
24
25
26@pytest.fixture(scope="session")
27def invalid_xml():
28    return os.path.join(UPDATE, "invalid_iana_download.xml")
29
30
31@pytest.fixture(scope="session")
32def no_data_xml():
33    return os.path.join(UPDATE, "no_data.xml")
34
35
36@pytest.fixture(scope="session")
37def expected_data():
38    expected_json = os.path.join(UPDATE, "expected_mime_types.json")
39    with open(expected_json, "r", encoding="UTF-8") as f:
40        return json.load(f)
41
42
43@pytest.fixture(scope="session")
44def parsed_xml(downloaded_xml):
45    with open(downloaded_xml, "r", encoding="UTF-8") as f:
46        data = f.read()
47        return xmltodict.parse(data)
48
49
50def test_xml_to_dict(downloaded_xml):
51    with open(downloaded_xml, "r", encoding="UTF-8") as f:
52        data = f.read()
53        xml_data = utils._xml_to_dict(data)
54        assert xml_data is not None
55        assert isinstance(xml_data, dict)
56
57
58def test_xml_to_dict_no_data(no_data_xml):
59    with pytest.raises(utils.MediaTypeError) as e:
60        with open(no_data_xml, "r", encoding="UTF-8") as f:
61            data = f.read()
62            utils._xml_to_dict(data)
63
64    msg = "Error parsing XML: "
65    assert msg in e.value.args[0]
66
67
68def test_xml_to_dict_invalid(invalid_xml):
69    with pytest.raises(utils.MediaTypeError) as e:
70        with open(invalid_xml, "r", encoding="UTF-8") as f:
71            data = f.read()
72            utils._xml_to_dict(data)
73
74    msg = "Error parsing XML: "
75    assert msg in e.value.args[0]
76
77
78def test_parse_xml_data(parsed_xml, expected_data):
79    result = utils._parse_xml_data(parsed_xml)
80
81    assert result == expected_data
82    assert len(result) == len(expected_data)
83
84
85@pytest.fixture(scope="session")
86def incorrect_registry_count():
87    xml_file = os.path.join(UPDATE, "unexpected_registry_count.xml")
88    with open(xml_file, "r", encoding="UTF-8") as f:
89        data = f.read()
90        return xmltodict.parse(data)
91
92
93def test_parse_xml_data_incorrect_reg(incorrect_registry_count):
94    with pytest.raises(utils.MediaTypeError) as e:
95        utils._parse_xml_data(incorrect_registry_count)
96
97    msg = ("Expected 9 registries but parsed 2",)
98    assert e.value.args == msg
99
100
101@pytest.fixture(scope="session")
102def no_registries():
103    xml_file = os.path.join(UPDATE, "no_registries.xml")
104    with open(xml_file, "r", encoding="UTF-8") as f:
105        data = f.read()
106        return xmltodict.parse(data)
107
108
109def test_parse_xml_data_no_reg(no_registries):
110    with pytest.raises(utils.MediaTypeError) as e:
111        utils._parse_xml_data(no_registries)
112
113    msg = ("No registries found to parse.",)
114    assert e.value.args == msg
115
116
117def test_requests_download_xml(downloaded_xml):
118    utils.requests = Mock()
119    with open(downloaded_xml, "r", encoding="UTF-8") as xml:
120        expected = xml.read()
121        utils.requests.get.return_value.text = expected
122        results = utils._requests_download(utils.IANA_URL)
123
124        assert results == expected
125
126
127def test_urllib_download(downloaded_xml):
128    utils.urllib = Mock()
129    with open(downloaded_xml, "r", encoding="UTF-8") as xml:
130        utils.urllib.urlopen.return_value = xml
131        results = utils._urllib_download(utils.IANA_URL)
132
133    with open(downloaded_xml, "r", encoding="UTF-8") as xml:
134        assert results == xml.read()
135
136
137@patch("ramlfications.utils._parse_xml_data")
138@patch("ramlfications.utils._xml_to_dict")
139@patch("ramlfications.utils._save_updated_mime_types")
140def test_insecure_download_urllib_flag(_a, _b, _c, mocker, monkeypatch):
141    monkeypatch.setattr(utils, "SECURE_DOWNLOAD", False)
142    monkeypatch.setattr(utils, "URLLIB", True)
143    utils.requests = Mock()
144
145    mocker.patch("ramlfications.utils._urllib_download")
146
147    utils.update_mime_types()
148    utils._urllib_download.assert_called_once()
149
150    mocker.stopall()
151
152
153@patch("ramlfications.utils._xml_to_dict")
154@patch("ramlfications.utils._parse_xml_data")
155@patch("ramlfications.utils._save_updated_mime_types")
156def test_secure_download_requests_flag(_a, _b_, _c, mocker, monkeypatch):
157    monkeypatch.setattr(utils, "SECURE_DOWNLOAD", True)
158    monkeypatch.setattr(utils, "URLLIB", False)
159    utils.urllib = Mock()
160
161    mocker.patch("ramlfications.utils._requests_download")
162
163    utils.update_mime_types()
164    utils._requests_download.assert_called_once()
165
166    mocker.stopall()
167
168
169@patch("ramlfications.utils._xml_to_dict")
170@patch("ramlfications.utils._parse_xml_data")
171@patch("ramlfications.utils._requests_download")
172@patch("ramlfications.utils._urllib_download")
173@patch("ramlfications.utils._save_updated_mime_types")
174def test_update_mime_types(_a, _b, _c, _d, _e, downloaded_xml):
175    utils.requests = Mock()
176
177    with open(downloaded_xml, "r", encoding="UTF-8") as raw_data:
178        utils.update_mime_types()
179        utils._requests_download.assert_called_once()
180        utils._requests_download.return_value = raw_data.read()
181        utils._xml_to_dict.assert_called_once()
182        utils._parse_xml_data.assert_called_once()
183        utils._save_updated_mime_types.assert_called_once()
184
185
186def test_save_updated_mime_types():
187    content = ["foo/bar", "bar/baz"]
188    temp_output = tempfile.mkstemp()[1]
189    utils._save_updated_mime_types(temp_output, content)
190
191    result = open(temp_output, "r", encoding="UTF-8").read()
192    result = json.loads(result)
193    assert result == content
194
195    os.remove(temp_output)
196