| LEFT | RIGHT | 
|---|
| 1 # coding: utf-8 | 1 # coding: utf-8 | 
| 2 | 2 | 
| 3 # This file is part of the Adblock Plus web scripts, | 3 # This file is part of the Adblock Plus web scripts, | 
| 4 # Copyright (C) 2006-2015 Eyeo GmbH | 4 # Copyright (C) 2006-2015 Eyeo GmbH | 
| 5 # | 5 # | 
| 6 # Adblock Plus is free software: you can redistribute it and/or modify | 6 # Adblock Plus is free software: you can redistribute it and/or modify | 
| 7 # it under the terms of the GNU General Public License version 3 as | 7 # it under the terms of the GNU General Public License version 3 as | 
| 8 # published by the Free Software Foundation. | 8 # published by the Free Software Foundation. | 
| 9 # | 9 # | 
| 10 # Adblock Plus is distributed in the hope that it will be useful, | 10 # Adblock Plus is distributed in the hope that it will be useful, | 
| 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 13 # GNU General Public License for more details. | 13 # GNU General Public License for more details. | 
| 14 # | 14 # | 
| 15 # You should have received a copy of the GNU General Public License | 15 # You should have received a copy of the GNU General Public License | 
| 16 # along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 16 # along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 17 | 17 | 
| 18 import MySQLdb |  | 
| 19 import StringIO |  | 
| 20 import json | 18 import json | 
| 21 import sys | 19 import sys | 
|  | 20 import StringIO | 
| 22 import unittest | 21 import unittest | 
| 23 from urllib import urlencode | 22 from urllib import urlencode | 
| 24 | 23 | 
| 25 from sitescripts.filterhits.test import test_helpers | 24 from sitescripts.filterhits.test import test_helpers | 
| 26 from sitescripts.filterhits import db | 25 from sitescripts.filterhits import db | 
| 27 from sitescripts.filterhits.web.query import query_handler | 26 from sitescripts.filterhits.web.query import query_handler | 
| 28 from sitescripts.filterhits.web.submit import submit as submit_handler | 27 from sitescripts.filterhits.web.submit import submit as submit_handler | 
| 29 | 28 | 
| 30 valid_data = """{ | 29 valid_data = """{ | 
| 31   "version": 1, | 30   "version": 1, | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 43         "example.org": {"hits": 4, "latest": 1414859271125} | 42         "example.org": {"hits": 4, "latest": 1414859271125} | 
| 44       }, | 43       }, | 
| 45       "thirdParty": { | 44       "thirdParty": { | 
| 46         "example.com": {"hits": 5, "latest": 1414916268769} | 45         "example.com": {"hits": 5, "latest": 1414916268769} | 
| 47       }, | 46       }, | 
| 48       "subscriptions": ["EasyList", "EasyList Germany+EasyList"] | 47       "subscriptions": ["EasyList", "EasyList Germany+EasyList"] | 
| 49     } | 48     } | 
| 50   } | 49   } | 
| 51 }""" | 50 }""" | 
| 52 | 51 | 
| 53 class APITestCase(unittest.TestCase): | 52 class APITestCase(test_helpers.FilterhitsTestCase): | 
| 54   def clear_rows(self): |  | 
| 55     if self.db: |  | 
| 56       db.write(self.db, (("DELETE FROM filters",), |  | 
| 57                          ("DELETE FROM frequencies",))) |  | 
| 58 |  | 
| 59   def setUp(self): |  | 
| 60     self.config = test_helpers.setup_config() |  | 
| 61     try: |  | 
| 62       self.db = db.connect() |  | 
| 63     except MySQLdb.Error: |  | 
| 64       self.db = None |  | 
| 65     self.clear_rows() |  | 
| 66 |  | 
| 67   def tearDown(self): |  | 
| 68     test_helpers.restore_config() |  | 
| 69     if self.db: |  | 
| 70       self.clear_rows() |  | 
| 71       self.db.close() |  | 
| 72       self.db = None |  | 
| 73 |  | 
| 74   def assertResponse(self, handler, expected_response, expected_result=None, exp
     ected_headers=None, **environ): | 53   def assertResponse(self, handler, expected_response, expected_result=None, exp
     ected_headers=None, **environ): | 
| 75     def check_response(response, headers): | 54     def check_response(response, headers): | 
| 76       self.assertEqual(response, expected_response) | 55       self.assertEqual(response, expected_response) | 
| 77       if not expected_headers is None: | 56       if not expected_headers is None: | 
| 78         self.assertEqual(headers, expected_headers) | 57         self.assertEqual(headers, expected_headers) | 
| 79 | 58 | 
| 80     if "body" in environ: | 59     if "body" in environ: | 
| 81       environ["CONTENT_LENGTH"] = len(environ["body"]) | 60       environ["CONTENT_LENGTH"] = len(environ["body"]) | 
| 82       environ["wsgi.input"] = StringIO.StringIO(environ["body"]) | 61       environ["wsgi.input"] = StringIO.StringIO(environ["body"]) | 
| 83       del environ["body"] | 62       del environ["body"] | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 98     self.assertResponse(submit_handler, "400 Processing Error", | 77     self.assertResponse(submit_handler, "400 Processing Error", | 
| 99                         REQUEST_METHOD="POST", body="") | 78                         REQUEST_METHOD="POST", body="") | 
| 100     self.assertResponse(submit_handler, "400 Processing Error", | 79     self.assertResponse(submit_handler, "400 Processing Error", | 
| 101                         REQUEST_METHOD="POST", body="Oops...") | 80                         REQUEST_METHOD="POST", body="Oops...") | 
| 102     self.assertResponse(submit_handler, "400 Processing Error", | 81     self.assertResponse(submit_handler, "400 Processing Error", | 
| 103                         REQUEST_METHOD="POST", body="{123:]") | 82                         REQUEST_METHOD="POST", body="{123:]") | 
| 104     self.assertResponse(submit_handler, "400 Processing Error", | 83     self.assertResponse(submit_handler, "400 Processing Error", | 
| 105                         REQUEST_METHOD="POST", body="1") | 84                         REQUEST_METHOD="POST", body="1") | 
| 106     self.assertEqual(len(db.query(self.db, "SELECT * FROM frequencies")), 0) | 85     self.assertEqual(len(db.query(self.db, "SELECT * FROM frequencies")), 0) | 
| 107     self.assertEqual(len(db.query(self.db, "SELECT * FROM filters")), 0) | 86     self.assertEqual(len(db.query(self.db, "SELECT * FROM filters")), 0) | 
| 108     # Ensure even an empty object, or one with the wrong fields returns OK | 87     # Ensure even an empty object, or one with the wrong fields returns successf
     ully | 
| 109     self.assertResponse(submit_handler, "200 OK", | 88     self.assertResponse(submit_handler, "204 No Content", | 
| 110                         REQUEST_METHOD="POST", body="{}") | 89                         REQUEST_METHOD="POST", body="{}") | 
| 111     self.assertResponse(submit_handler, "200 OK", | 90     self.assertResponse(submit_handler, "204 No Content", | 
| 112                         REQUEST_METHOD="POST", body="{\"hello\": \"world\"}") | 91                         REQUEST_METHOD="POST", body="{\"hello\": \"world\"}") | 
| 113     self.assertEqual(len(db.query(self.db, "SELECT * FROM frequencies")), 0) | 92     self.assertEqual(len(db.query(self.db, "SELECT * FROM frequencies")), 0) | 
| 114     self.assertEqual(len(db.query(self.db, "SELECT * FROM filters")), 0) | 93     self.assertEqual(len(db.query(self.db, "SELECT * FROM filters")), 0) | 
| 115     # Now some actually valid data | 94     # Now some actually valid data | 
| 116     self.assertResponse(submit_handler, "200 OK", | 95     self.assertResponse(submit_handler, "204 No Content", | 
| 117                         REQUEST_METHOD="POST", body=valid_data) | 96                         REQUEST_METHOD="POST", body=valid_data) | 
| 118     self.assertEqual(len(db.query(self.db, "SELECT * FROM frequencies")), 2) | 97     self.assertEqual(len(db.query(self.db, "SELECT * FROM frequencies")), 2) | 
| 119     self.assertEqual(len(db.query(self.db, "SELECT * FROM filters")), 1) | 98     self.assertEqual(len(db.query(self.db, "SELECT * FROM filters")), 1) | 
| 120     # Now make sure apparently valid data with timestamps that cause geometrical | 99     # Now make sure apparently valid data with timestamps that cause geometrical | 
| 121     # mean calculations to fail with MySQL errors return OK but don't change DB | 100     # mean calculations to fail with MySQL errors return OK but don't change DB | 
| 122     invalid_data = json.loads(valid_data) | 101     invalid_data = json.loads(valid_data) | 
| 123     invalid_data["filters"]["||example.com^"]["firstParty"]["example.com"]["late
     st"] = 3 | 102     invalid_data["filters"]["||example.com^"]["firstParty"]["example.com"]["late
     st"] = 3 | 
| 124     invalid_data = json.dumps(invalid_data) | 103     invalid_data = json.dumps(invalid_data) | 
| 125     self.assertResponse(submit_handler, "200 OK", | 104     self.assertResponse(submit_handler, "204 No Content", | 
| 126                         REQUEST_METHOD="POST", body=invalid_data) | 105                         REQUEST_METHOD="POST", body=invalid_data) | 
| 127     self.assertEqual(len(db.query(self.db, "SELECT * FROM frequencies")), 2) | 106     self.assertEqual(len(db.query(self.db, "SELECT * FROM frequencies")), 2) | 
| 128     self.assertEqual(len(db.query(self.db, "SELECT * FROM filters")), 1) | 107     self.assertEqual(len(db.query(self.db, "SELECT * FROM filters")), 1) | 
| 129 | 108 | 
| 130   def test_query(self): | 109   def test_query(self): | 
| 131     # Basic query with no data, should return OK | 110     # Basic query with no data, should return successfully | 
| 132     self.assertResponse(query_handler, "200 OK", {"count": 0, "total": 0, "resul
     ts": [], "echo": 0}) | 111     self.assertResponse(query_handler, "200 OK", {"count": 0, "total": 0, "resul
     ts": [], "echo": 0}) | 
| 133     # If echo parameter is passed and is integer it should be returned | 112     # If echo parameter is passed and is integer it should be returned | 
| 134     self.assertResponse(query_handler, "200 OK", {"count": 0, "total": 0, "resul
     ts": [], "echo": 1337}, | 113     self.assertResponse(query_handler, "200 OK", {"count": 0, "total": 0, "resul
     ts": [], "echo": 1337}, | 
| 135                         get_params={ "echo": 1337 }) | 114                         get_params={ "echo": 1337 }) | 
| 136     self.assertResponse(query_handler, "200 OK", {"count": 0, "total": 0, "resul
     ts": [], "echo": 0}, | 115     self.assertResponse(query_handler, "200 OK", {"count": 0, "total": 0, "resul
     ts": [], "echo": 0}, | 
| 137                         get_params={ "echo": "naughty" }) | 116                         get_params={ "echo": "naughty" }) | 
| 138     # Now let's submit some data so we can query it back out | 117     # Now let's submit some data so we can query it back out | 
| 139     test_data = [json.loads(valid_data), json.loads(valid_data), json.loads(vali
     d_data)] | 118     test_data = [json.loads(valid_data), json.loads(valid_data), json.loads(vali
     d_data)] | 
| 140     test_data[1]["filters"]["##Second-Filter|"] = test_data[1]["filters"].pop("|
     |example.com^") | 119     test_data[1]["filters"]["##Second-Filter|"] = test_data[1]["filters"].pop("|
     |example.com^") | 
| 141     test_data[2]["filters"]["##Third-Filter|"] = test_data[2]["filters"].pop("||
     example.com^") | 120     test_data[2]["filters"]["##Third-Filter|"] = test_data[2]["filters"].pop("||
     example.com^") | 
| 142     for data in test_data: | 121     for data in test_data: | 
| 143       self.assertResponse(submit_handler, "200 OK", | 122       self.assertResponse(submit_handler, "204 No Content", | 
| 144                           REQUEST_METHOD="POST", body=json.dumps(data)) | 123                           REQUEST_METHOD="POST", body=json.dumps(data)) | 
| 145     # Ordering parameters should be respected | 124     # Ordering parameters should be respected | 
| 146     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 6, | 125     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 6, | 
| 147                                                   "results": [{'domain': 'exampl
     e.com', | 126                                                   "results": [{"domain": "exampl
     e.com", | 
| 148                                                                'filter': '||exam
     ple.com^', | 127                                                                "filter": "||exam
     ple.com^", | 
| 149                                                                'frequency': 0}],
      "echo": 0}, | 128                                                                "frequency": 0}],
      "echo": 0}, | 
| 150                         get_params={ "order_by": "filter", "order": "desc", "tak
     e": "1" }) | 129                         get_params={ "order_by": "filter", "order": "desc", "tak
     e": "1" }) | 
| 151     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 6, | 130     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 6, | 
| 152                                                   "results": [{'domain': 'exampl
     e.com', | 131                                                   "results": [{"domain": "exampl
     e.com", | 
| 153                                                                'filter': '##Seco
     nd-Filter|', | 132                                                                "filter": "##Seco
     nd-Filter|", | 
| 154                                                                'frequency': 0}],
      "echo": 0}, | 133                                                                "frequency": 0}],
      "echo": 0}, | 
| 155                         get_params={ "order_by": "filter", "order": "asc", "take
     ": "1" }) | 134                         get_params={ "order_by": "filter", "order": "asc", "take
     ": "1" }) | 
| 156     # As should filtering parameters | 135     # As should filtering parameters | 
| 157     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 3, | 136     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 3, | 
| 158                                                   "results": [{'domain': 'exampl
     e.com', | 137                                                   "results": [{"domain": "exampl
     e.com", | 
| 159                                                                'filter': '##Thir
     d-Filter|', | 138                                                                "filter": "##Thir
     d-Filter|", | 
| 160                                                                'frequency': 0}],
      "echo": 0}, | 139                                                                "frequency": 0}],
      "echo": 0}, | 
| 161                         get_params={ "domain": "example.com", "take": "1" }) | 140                         get_params={ "domain": "example.com", "take": "1" }) | 
| 162     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 2, | 141     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 2, | 
| 163                                                   "results": [{'domain': 'exampl
     e.org', | 142                                                   "results": [{"domain": "exampl
     e.org", | 
| 164                                                                'filter': '##Thir
     d-Filter|', | 143                                                                "filter": "##Thir
     d-Filter|", | 
| 165                                                                'frequency': 4}],
      "echo": 0}, | 144                                                                "frequency": 4}],
      "echo": 0}, | 
| 166                         get_params={ "filter": "Third", "take": 1 }) | 145                         get_params={ "filter": "Third", "take": 1 }) | 
| 167     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 1, | 146     self.assertResponse(query_handler, "200 OK", {"count": 1, "total": 1, | 
| 168                                                   "results": [{'domain': 'exampl
     e.com', | 147                                                   "results": [{"domain": "exampl
     e.com", | 
| 169                                                                'filter': '##Thir
     d-Filter|', | 148                                                                "filter": "##Thir
     d-Filter|", | 
| 170                                                                'frequency': 0}],
      "echo": 0}, | 149                                                                "frequency": 0}],
      "echo": 0}, | 
| 171                         get_params={ "domain": "example.com", "filter": "Third",
      "take": "1" }) | 150                         get_params={ "domain": "example.com", "filter": "Third",
      "take": "1" }) | 
| 172     # ... and pagination parameters | 151     # ... and pagination parameters | 
| 173     self.maxDiff = None | 152     self.maxDiff = None | 
| 174     self.assertResponse(query_handler, "200 OK", {"count": 2, "total": 6, | 153     self.assertResponse(query_handler, "200 OK", {"count": 2, "total": 6, | 
| 175                                                   "results": [{'domain': 'exampl
     e.org', | 154                                                   "results": [{"domain": "exampl
     e.org", | 
| 176                                                                'filter': '||exam
     ple.com^', | 155                                                                "filter": "||exam
     ple.com^", | 
| 177                                                                'frequency': 4}, | 156                                                                "frequency": 4}, | 
| 178                                                               {'domain': 'exampl
     e.org', | 157                                                               {"domain": "exampl
     e.org", | 
| 179                                                                'filter': '##Seco
     nd-Filter|', | 158                                                                "filter": "##Seco
     nd-Filter|", | 
| 180                                                                'frequency': 4}],
      "echo": 0}, | 159                                                                "frequency": 4}],
      "echo": 0}, | 
| 181                         get_params={ "skip": "1", "take": "2" }) | 160                         get_params={ "skip": "1", "take": "2" }) | 
| 182     self.assertResponse(query_handler, "200 OK", {"count": 2, "total": 6, | 161     self.assertResponse(query_handler, "200 OK", {"count": 2, "total": 6, | 
| 183                                                   "results": [{'domain': 'exampl
     e.org', | 162                                                   "results": [{"domain": "exampl
     e.org", | 
| 184                                                                'filter': '##Seco
     nd-Filter|', | 163                                                                "filter": "##Seco
     nd-Filter|", | 
| 185                                                                'frequency': 4}, | 164                                                                "frequency": 4}, | 
| 186                                                               {'domain': 'exampl
     e.com', | 165                                                               {"domain": "exampl
     e.com", | 
| 187                                                                'filter': '##Thir
     d-Filter|', | 166                                                                "filter": "##Thir
     d-Filter|", | 
| 188                                                                'frequency': 0}],
      "echo": 0}, | 167                                                                "frequency": 0}],
      "echo": 0}, | 
| 189                         get_params={ "skip": "2", "take": "2" }) | 168                         get_params={ "skip": "2", "take": "2" }) | 
| 190 | 169 | 
| 191 if __name__ == '__main__': | 170 if __name__ == "__main__": | 
| 192   unittest.main() | 171   unittest.main() | 
| LEFT | RIGHT | 
|---|