Advertisement
Guest User

aaa

a guest
May 4th, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 47.81 KB | None | 0 0
  1. import io
  2. import gzip
  3. import struct
  4. import urllib.parse
  5. import json
  6. from time import *
  7.  
  8. from google.protobuf import json_format
  9. from jsondiff import diff
  10.  
  11. from testlib.main_test_case import *
  12. from testlib.tracker_api.tracker_data_generator import *
  13. from testlib.tracker_api.tracker_db import *
  14. import testlib.tracker_api.protobuf_common_structures.CoreStructure_pb2 as CoreStructure
  15. import testlib.tracker_api.protobuf_common_structures.ExtraFileStructure_pb2 as ExtraFileStructure
  16. import testlib.tracker_api.protobuf_common_structures.MetadataStructure_pb2 as MetadataStructure
  17. import testlib.tracker_api.protobuf_common_structures.RulesStructure_pb2 as RulesStructure
  18.  
  19.  
  20. class TrackerApiTestCase(MainTestCase):
  21. request_adconfig_get = "/adconfig/get"
  22. request_corefile_get = "/corefile/get"
  23. request_corefile_ios = "/corefile/ios"
  24. request_corepatch_get = "/corepatch/get"
  25. request_extrafile_get = "/extrafile/get"
  26. request_extrafile_ios = "/extrafile/ios"
  27. request_extrafile_ios_mapping = '/e/ios?q='
  28. request_netwfile_get = "/netwfile/get"
  29. request_add_device_in_smooth = "/admin/add_device"
  30. request_encode_params = "/admin/q_encode"
  31. request_decode_params = "/admin/q_decode"
  32. request_snapshot_sync = "/admin/snapshot/sync"
  33. request_snapshot_info = "/admin/snapshot/info"
  34. request_optout_add = "/optout/add"
  35. request_optout_exists = "/optout_admin/exists"
  36. request_optout_remove = "/optout_admin/remove"
  37. request_adconfig_mapping = "/a/?q="
  38. request_corefile_mapping = '/c/?q='
  39. request_corefile_ios_mapping = '/c/ios/?q='
  40. request_corepatch_mapping = '/p/?q='
  41. request_extrafile_mapping = '/e/?q='
  42. request_netwfile_mapping = '/n/?q='
  43.  
  44. cheat = "&qHme3rK4bg=1"
  45. provider_cheat = lambda: (
  46. (True, 'cheat'),
  47. (False, 'cheat'),
  48. )
  49.  
  50. default_smooth_id_7 = 9
  51. default_smooth_id_8 = 20
  52.  
  53. files_to_deactivate = []
  54. json_diff_arr = []
  55.  
  56. db = None # type: TrackerDb
  57. cfg_injector_ver = ''
  58. db_host = ''
  59. db_port = ''
  60. db_user = ''
  61. db_pass = ''
  62.  
  63. sdk_test_method = "/sdk/test"
  64. sdk_method = "/sdk"
  65.  
  66. block_type_version_request = '_VERSION_REQUEST'
  67. block_type_rules_primitives = 'RULES_PRIMITIVES'
  68. block_type_cache_info = 'CACHE_INFO'
  69. block_type_sdk_info = 'SDK_INFO'
  70. block_type_app_info = 'APP_INFO'
  71. block_type_rule = 'RULE'
  72. block_type_network = 'NETWORK_BLOCK'
  73. block_type_decor = 'DECOR'
  74. block_type_crypto_mining_data = 'CRYPTO_MINING_DATA'
  75. block_type_extra_file = 'EXTRA_FILE_BLOCK'
  76. block_type_core_file = 'CORE_FILE_TO'
  77. block_type_core_patch = 'CORE_PATCH_TO'
  78.  
  79. block_class_by_type = {
  80. block_type_version_request: MetadataStructure.StreamMetadata.VersionRequest(),
  81. block_type_rules_primitives: RulesStructure.RulesPrimitives(),
  82. block_type_cache_info: RulesStructure.CacheInfo(),
  83. block_type_sdk_info: RulesStructure.SdkInfo(),
  84. block_type_app_info: RulesStructure.AppInfo(),
  85. block_type_rule: RulesStructure.Rule(),
  86. block_type_network: RulesStructure.NetworkBlock(),
  87. block_type_decor: RulesStructure.Decor(),
  88. block_type_crypto_mining_data: RulesStructure.CryptoMiningData(),
  89. block_type_extra_file: ExtraFileStructure.ExtraFileBlock(),
  90. block_type_core_file: CoreStructure.CoreFileTo(),
  91. block_type_core_patch: CoreStructure.CorePatchTo(),
  92. }
  93.  
  94. block_type_by_class = {
  95. 'VersionRequest': [block_type_version_request, 0],
  96. 'RulesPrimitives': [block_type_rules_primitives, 10],
  97. 'CacheInfo': [block_type_cache_info, 11],
  98. 'SdkInfo': [block_type_sdk_info, 12],
  99. 'AppInfo': [block_type_app_info, 13],
  100. 'Rule': [block_type_rule, 14],
  101. 'NetworkBlock': [block_type_network, 15],
  102. 'Decor': [block_type_decor, 16],
  103. 'CryptoMiningData': [block_type_crypto_mining_data, 17],
  104. 'ExtraFileBlock': [block_type_extra_file, 18],
  105. 'CoreFileTo': [block_type_core_file, 19],
  106. 'CorePatchTo': [block_type_core_patch, 20],
  107. }
  108.  
  109. block_exception = {
  110. "block - new - user": 'false',
  111. "date - block - new - user": 0,
  112. "owner": 197,
  113. "title": "Too many items",
  114. "geo_filter_list": 0,
  115. "analytics_url": "",
  116. "exp_update": 30,
  117. "protcore_silent": 180,
  118. }
  119.  
  120. block_exception_in_dict = {
  121. "mediator_url": "http:\ / \ / api.mediator.tpc.re",
  122. "mediator": 12,
  123. "version": 5,
  124. "link": "test",
  125. "id": 1404
  126. }
  127.  
  128. def tearDown(self):
  129. super().tearDown()
  130. self.deactivate_files()
  131.  
  132. @classmethod
  133. def preparations_before_tests(cls):
  134. super().preparations_before_tests()
  135. cls.generator = TrackerDataGenerator()
  136. cls.injector_ver = cls.define_injector_ver()
  137. cls.fill_tracker_db = cls.define_fill_tracker_db()
  138. if cls.fill_tracker_db:
  139. cls.db = TrackerDb(db=cls.db, db_host=cls.db_host, db_port=cls.db_port, db_user=cls.db_user,
  140. db_pass=cls.db_pass)
  141. cls.prepare_tables()
  142.  
  143. @classmethod
  144. def read_tests_config(cls):
  145. super().read_tests_config()
  146. cls.cfg_injector_ver = cls.config['tracker']['injector_version']
  147. cls.cfg_host = cls.config['tracker']['host']
  148. cls.ios_ver = cls.config['tracker']['ios_version']
  149. cls.db = cls.define_db_name()
  150. cls.db_host = cls.define_db_host()
  151. cls.db_port = cls.define_db_port()
  152. cls.db_user = cls.define_db_user()
  153. cls.db_pass = cls.define_db_password()
  154. cls.files_dir = cls.config['tracker']['files_path']
  155.  
  156. @classmethod
  157. def define_injector_ver(cls):
  158. (options, args) = cls.parser.parse_args()
  159. inj_ver = options.injector_ver
  160. if not inj_ver:
  161. inj_ver = cls.cfg_injector_ver
  162. return inj_ver
  163.  
  164. @classmethod
  165. def define_available_options(cls):
  166. super().define_available_options()
  167. cls.parser.add_option("-i", "--injector-ver", dest="injector_ver", help="set injector version")
  168. cls.parser.add_option("--fill-tracker-db", dest="fill_tracker_db", default="False",
  169. help="fill tracker DB",
  170. action='callback', callback=cls.optional_arg('True'))
  171. cls.parser.add_option("--db-name", dest="db_name", help="set tracker db name")
  172. cls.parser.add_option("--db-host", dest="db_host", help="set tracker db host")
  173. cls.parser.add_option("--db-port", dest="db_port", help="set tracker db port")
  174. cls.parser.add_option("--db-user", dest="db_user", help="set tracker db user")
  175. cls.parser.add_option("--db-password", dest="db_password", help="set tracker db password")
  176.  
  177. @classmethod
  178. def define_fill_tracker_db(cls):
  179. (options, args) = cls.parser.parse_args()
  180. fill_tracker_db = options.fill_tracker_db
  181. return fill_tracker_db == 'True'
  182.  
  183. @classmethod
  184. def define_db_name(cls):
  185. (options, args) = cls.parser.parse_args()
  186. db_name = options.db_name
  187. if not db_name:
  188. db_name = cls.config['tracker']['db_name']
  189. return db_name
  190.  
  191. @classmethod
  192. def define_db_host(cls):
  193. (options, args) = cls.parser.parse_args()
  194. db_host = options.db_host
  195. if not db_host:
  196. db_host = cls.config['tracker']['db_host']
  197. return db_host
  198.  
  199. @classmethod
  200. def define_db_port(cls):
  201. (options, args) = cls.parser.parse_args()
  202. db_port = options.db_port
  203. if not db_port:
  204. db_port = cls.config['tracker']['db_port']
  205. return db_port
  206.  
  207. @classmethod
  208. def define_db_user(cls):
  209. (options, args) = cls.parser.parse_args()
  210. db_user = options.db_user
  211. if not db_user:
  212. db_user = cls.config['tracker']['db_user']
  213. return db_user
  214.  
  215. @classmethod
  216. def define_db_password(cls):
  217. (options, args) = cls.parser.parse_args()
  218. db_password = options.db_password
  219. if not db_password:
  220. db_password = cls.config['tracker']['db_password']
  221. return db_password
  222.  
  223. @classmethod
  224. def prepare_tables(cls):
  225. if not cls.db.check_table_exists(cls.db.core_files_table_name):
  226. cls.db.create_table_corefile()
  227. if not cls.db.check_table_exists(cls.db.core_files_ios_table_name):
  228. cls.db.create_table_corefile_ios()
  229. if not cls.db.check_table_exists(cls.db.core_patches_table_name):
  230. cls.db.create_table_corepatch()
  231. if not cls.db.check_table_exists(cls.db.extra_files_table_name):
  232. cls.db.create_table_extrafile()
  233. if not cls.db.check_table_exists(cls.db.extra_files_ios_table_name):
  234. cls.db.create_table_extrafile_ios()
  235. if not cls.db.check_table_exists(cls.db.netw_files_table_name):
  236. cls.db.create_table_netwfile()
  237. if not cls.db.check_table_exists(cls.db.smooth_files_table_name):
  238. cls.db.create_table_smoothcore()
  239. if not cls.db.check_table_exists(cls.db.decors_table_name):
  240. cls.db.create_table_decorations()
  241. if not cls.db.check_table_exists(cls.db.publishers_table_name):
  242. cls.db.create_table_publishers()
  243. if not cls.db.check_table_exists(cls.db.apps_table_name):
  244. cls.db.create_table_applications()
  245. if not cls.db.check_table_exists(cls.db.config_table_name):
  246. cls.db.create_table_config()
  247. if not cls.db.check_table_exists(cls.db.network_key_table_name):
  248. cls.db.create_table_network_key()
  249. if not cls.db.check_table_exists(cls.db.appgroup_table_name):
  250. cls.db.create_table_appgroup()
  251. if not cls.db.check_table_exists(cls.db.adnetwork_table_name):
  252. cls.db.create_table_adnetwork()
  253. if not cls.db.check_table_exists(cls.db.campaign_table_name):
  254. cls.db.create_table_campaign()
  255.  
  256. def encode_params(self, params, cheat=False):
  257. params = urllib.parse.urlencode(params, quote_via=urllib.parse.quote)
  258. response = urllib.parse.quote(
  259. self.make_request(self.request_encode_params + "?" + params)['response']['qUrlEncoded'])
  260. if response.endswith("="):
  261. response = re.sub("=+$", "", response)
  262. if cheat:
  263. response += self.cheat
  264. return urllib.parse.unquote(response)
  265.  
  266. def assert_response_ok(self, response):
  267. self.assertEqual("ok", response["response"]["result"])
  268. self.assertEqual("", response["response"]["error"])
  269.  
  270. def assert_response_fail(self, response):
  271. self.assertEqual("fail", response["response"]["result"])
  272.  
  273. def get_core_version(self, ios=False, u=None):
  274. if ios:
  275. request = self.request_corefile_ios
  276. else:
  277. request = self.request_corefile_get
  278. params = {'i': self.injector_ver}
  279. if u:
  280. params["u"] = u
  281. r = self.make_request(request=request, params=params)
  282. return str(r['response']['vCore'])
  283.  
  284. def add_cheat_to_params(self, params):
  285. params['qHme3rK4bg'] = 1
  286. return params
  287.  
  288. def assert_good_extra_file_response(self, response, core_version):
  289. for resp in response['response']:
  290. self.assertLessEqual(int(resp['core']), int(core_version))
  291. self.assertGreater(len(resp['name']), 0)
  292. self.assertGreater(len(resp['title']), 0)
  293. self.assertGreater(len(resp['url']), 0)
  294.  
  295. def decode_params(self, params):
  296. return self.make_request(self.request_decode_params + '?value=' + params, decode_resp=False)
  297.  
  298. def is_decoded(self, params):
  299. return self.decode_params(params)['status'] == self.status_code_ok
  300.  
  301. def assert_core_without_smooth(self, response, i, v_core=None):
  302. self.assertNotEqual("", response['response']["vCore"])
  303. if v_core:
  304. self.assertEqual(v_core, response['response']["vCore"])
  305. self.assertEqual(int(i), response['response']["vInject"])
  306. self.assertEqual([], response['response']['countries'])
  307. self.assertNotEqual("", response['response']["url"])
  308.  
  309. def assert_core_in_smooth(self, response, i, v_core=None):
  310. self.assertNotEqual("", response['response']["vCore"])
  311. if v_core:
  312. self.assertEqual(v_core, response['response']["vCore"])
  313. self.assertEqual(int(i), response['response']["vInject"])
  314. self.assertNotEqual([], response['response']['countries'])
  315. self.assertNotEqual("", response['response']["url"])
  316.  
  317. def add_new_core_file(self, params=None, smooth=False, ios=False):
  318. if not self.fill_tracker_db:
  319. return
  320. data = {}
  321. if params:
  322. data = params
  323. if "vInject" not in data.keys():
  324. data["vInject"] = self.injector_ver
  325. if "file" not in data.keys():
  326. data["file"] = "%s/autotest-file-%s.zip" % (self.files_dir, uuid.uuid4().hex)
  327. self.touch_file(data["file"])
  328. if ios:
  329. snapshot_type = "IosCoreFiles"
  330. table = self.db.core_files_ios_table_name
  331. else:
  332. snapshot_type = "CoreFiles"
  333. table = self.db.core_files_table_name
  334. params = self.generator.generate_core_file(def_params=data, smooth=smooth, ios=ios)
  335. self.db.insert_core_file(params=params, ios=ios)
  336. self.sync_snapshots_and_wait([snapshot_type])
  337. self.files_to_deactivate.append({"title": params["title"], "table": table, "snapshot_type": snapshot_type})
  338. return params
  339.  
  340. def add_new_corepatch(self, params=None, core_file_title=None):
  341. if not self.fill_tracker_db:
  342. return
  343. data = {}
  344. if params:
  345. data = params
  346. if "corefileId" not in data.keys() and core_file_title:
  347. data["corefileId"] = self.db.get_corefile_id(core_file_title)
  348. if "file" not in data.keys():
  349. data["file"] = "%s/autotest-file-%s.zip" % (self.files_dir, uuid.uuid4().hex)
  350. self.touch_file(data["file"])
  351. snapshot_type = "CorePatches"
  352. table = self.db.core_patches_table_name
  353. params = self.generator.generate_corepatch_file(def_params=data)
  354. self.db.insert_corepatch_file(params)
  355. self.sync_snapshots_and_wait([snapshot_type])
  356. self.files_to_deactivate.append({"title": params["title"], "table": table, "snapshot_type": snapshot_type})
  357.  
  358. def add_new_extra_file(self, params=None, ios=False):
  359. if not self.fill_tracker_db:
  360. return
  361. data = {}
  362. if params:
  363. data = params
  364. if "file" not in data.keys():
  365. data["file"] = "%s/autotest-file-%s.zip" % (self.files_dir, uuid.uuid4().hex)
  366. self.touch_file(data["file"])
  367. if ios:
  368. snapshot_type = "IosExtraFiles"
  369. table = self.db.extra_files_ios_table_name
  370. else:
  371. snapshot_type = "ExtraFiles"
  372. table = self.db.extra_files_table_name
  373. params = self.generator.generate_extra_file(def_params=data, ios=ios)
  374. self.db.insert_extra_file(params=params, ios=ios)
  375. self.sync_snapshots_and_wait([snapshot_type])
  376. self.files_to_deactivate.append({"title": params["title"], "table": table, "snapshot_type": snapshot_type})
  377. return params
  378.  
  379. def add_new_netw_file(self, params=None):
  380. if not self.fill_tracker_db:
  381. return
  382. data = {}
  383. if params:
  384. data = params
  385. if "file" not in data.keys():
  386. data["file"] = "%s/autotest-file-%s.zip" % (self.files_dir, uuid.uuid4().hex)
  387. self.touch_file(data["file"])
  388. snapshot_type = "NetworkFiles"
  389. table = self.db.netw_files_table_name
  390. params = self.generator.generate_netw_file(def_params=data)
  391. self.db.insert_netw_file(params)
  392. self.sync_snapshots_and_wait([snapshot_type])
  393. self.files_to_deactivate.append({"title": params["title"], "table": table, "snapshot_type": snapshot_type})
  394.  
  395. def add_new_decoration(self, params=None):
  396. if not self.fill_tracker_db:
  397. return
  398. data = {}
  399. if params:
  400. data = params
  401. if "image_mdpi" not in data.keys():
  402. data["image_mdpi"] = "%s/autotest-file-mdpi-%s.png" % (self.files_dir, uuid.uuid4().hex)
  403. self.touch_file(data["image_mdpi"])
  404. if "image_hdpi" not in data.keys():
  405. data["image_hdpi"] = "%s/autotest-file-hdpi-%s.png" % (self.files_dir, uuid.uuid4().hex)
  406. self.touch_file(data["image_hdpi"])
  407. if "image_xhdpi" not in data.keys():
  408. data["image_xhdpi"] = "%s/autotest-file-xhdpi-%s.png" % (self.files_dir, uuid.uuid4().hex)
  409. self.touch_file(data["image_xhdpi"])
  410. if "image_xxhdpi" not in data.keys():
  411. data["image_xxhdpi"] = "%s/autotest-file-xxhdpi-%s.png" % (self.files_dir, uuid.uuid4().hex)
  412. self.touch_file(data["image_xxhdpi"])
  413. snapshot_type = "Decorations"
  414. table = self.db.decors_table_name
  415. params = self.generator.generate_decoration(def_params=data)
  416. self.db.insert_decoration(params)
  417. self.sync_snapshots_and_wait([snapshot_type])
  418. self.files_to_deactivate.append({"title": params["title"], "table": table, "snapshot_type": snapshot_type})
  419.  
  420. def add_new_app(self, params=None, pub_login=None):
  421. if not self.fill_tracker_db:
  422. return
  423. data = {}
  424. if params:
  425. data = params
  426. if "owner" not in data.keys() and pub_login:
  427. data["owner"] = self.db.get_publisher_id(pub_login)
  428. params = self.generator.generate_app(def_params=data)
  429. self.db.insert_app(params)
  430. self.sync_snapshots_and_wait(["Applications"])
  431. return params
  432.  
  433. def add_new_publisher(self, params=None):
  434. if not self.fill_tracker_db:
  435. return
  436. data = {}
  437. if params:
  438. data = params
  439. params = self.generator.generate_publisher(def_params=data)
  440. self.db.insert_publisher(params)
  441. return params
  442.  
  443. def add_new_config(self, params=None):
  444. if not self.fill_tracker_db:
  445. return
  446. data = {}
  447. if params:
  448. data = params
  449. params = self.generator.generate_config(def_params=data)
  450. self.db.insert_config(params)
  451. self.sync_snapshots_and_wait(["ConfigProperties"])
  452.  
  453. def add_new_network_key(self, params=None, pub_login=None):
  454. if not self.fill_tracker_db:
  455. return
  456. data = {}
  457. if params:
  458. data = params
  459. if "adnetwork" not in data.keys():
  460. adnetwork = self.add_new_adnetwork()
  461. data["adnetwork"] = "%s" % self.db.get_adnetwork_id(title=adnetwork["title"])
  462. if pub_login:
  463. data["owner"] = self.db.get_publisher_id(pub_login)
  464. params = self.generator.generate_network_key(def_params=data)
  465. self.db.insert_network_key(params)
  466. self.sync_snapshots_and_wait(["AdNetworkKeys"])
  467. return params
  468.  
  469. def add_new_appgroup(self, params=None, keys_titles=None):
  470. if not self.fill_tracker_db:
  471. return
  472. data = {}
  473. if params:
  474. data = params
  475. if "adKeys" not in data.keys() and keys_titles:
  476. keys = []
  477. for key_title in keys_titles:
  478. keys.append(self.db.get_network_key_id(title=key_title))
  479. data["adKeys"] = keys
  480. params = self.generator.generate_appgroup(def_params=data)
  481. self.db.insert_appgroup(params)
  482. self.sync_snapshots_and_wait(["AppGroups"])
  483. return params
  484.  
  485. def add_new_adnetwork(self, params=None):
  486. if not self.fill_tracker_db:
  487. return
  488. data = {}
  489. if params:
  490. data = params
  491. params = self.generator.generate_adnetwork(def_params=data)
  492. self.db.insert_adnetwork(params)
  493. self.sync_snapshots_and_wait(["AdNetworks"])
  494. return params
  495.  
  496. def add_new_campaign(self, params=None, pub_login=None):
  497. if not self.fill_tracker_db:
  498. return
  499. data = {}
  500. if params:
  501. data = params
  502. if "owner" not in data.keys() and pub_login:
  503. data["owner"] = self.db.get_publisher_id(pub_login)
  504. params = self.generator.generate_campaign(def_params=data)
  505. self.db.insert_campaign(params)
  506. self.sync_snapshots_and_wait(["Campaigns"])
  507. return params
  508.  
  509. def update_app(self, title, params):
  510. app_id = self.db.get_app_id(title)
  511. self.db.update_app(app_id, params)
  512. self.sync_snapshots_and_wait(["Applications"])
  513.  
  514. def update_campaign(self, title, params):
  515. app_id = self.db.get_campaign_id(title)
  516. self.db.update_campaign(app_id, params)
  517. self.sync_snapshots_and_wait(["Campaigns"])
  518.  
  519. def deactivate_files(self):
  520. if not self.fill_tracker_db or not self.files_to_deactivate:
  521. return
  522. snapshot_types = []
  523. for file_to_deactivate in self.files_to_deactivate:
  524. snapshot_types.append(file_to_deactivate["snapshot_type"])
  525. self.db.make_file_inactive(title=file_to_deactivate["title"], table=file_to_deactivate["table"])
  526. self.sync_snapshots_and_wait(snapshot_types)
  527. self.files_to_deactivate = []
  528.  
  529. def sync_snapshots_and_wait(self, snapshot_types, timeout=20000):
  530. info_before = self.make_request(request=self.request_snapshot_info)['response']
  531. self.make_request(request=self.request_snapshot_sync)
  532. for snapshot_type in snapshot_types:
  533. i = 0
  534. while True:
  535. info_after = self.make_request(request=self.request_snapshot_info)['response'][snapshot_type]
  536. if (int(info_before[snapshot_type]["entitiesCount"]) > int(info_after["entitiesCount"])) or (
  537. int(info_before[snapshot_type]["lastSyncTimestamp"]) < int(
  538. info_after["lastSyncTimestamp"])):
  539. break
  540. if i >= timeout:
  541. raise TimeoutError('Timeout has been reached while waiting for snapshots sync')
  542. sleep(3.0 / 1000.0)
  543. i += 1
  544.  
  545. def touch_file(self, path):
  546. if not os.path.isdir(os.path.dirname(path)):
  547. os.mkdir(os.path.dirname(path))
  548. cmd = "touch %s" % path
  549. os.system(cmd)
  550.  
  551. def get_smooth_id(self, corefile=None, core_id=None):
  552. if not self.fill_tracker_db:
  553. smooth_id = {
  554. '7': self.default_smooth_id_7,
  555. '8': self.default_smooth_id_8,
  556. }
  557. return smooth_id[str(self.injector_ver)]
  558. if not core_id and not corefile:
  559. raise Exception("Please set core file title or core file id")
  560. if not core_id and corefile:
  561. core_id = self.db.get_corefile_id(title=corefile["title"])
  562. return self.db.get_smooth_id(core_id)
  563.  
  564. def add_device_in_smooth(self, device_id, smooth_id=None, corefile=None):
  565. if not smooth_id:
  566. smooth_id = self.get_smooth_id(corefile=corefile)
  567. params = {"device": device_id, "smoothId": smooth_id}
  568. self.make_request(request=self.request_add_device_in_smooth, params=params)
  569. self.sync_snapshots_and_wait(snapshot_types=["SmoothTests"])
  570.  
  571. def assert_file_correct(self, file, min_size=10000, expected_type="core"):
  572. self.assertEqual(self.status_code_ok, file['status'])
  573. self.assertGreater(int(file['headers'].get('Content-Length')), min_size)
  574. actual_type = file['headers'].get('Content-Type')
  575. self.assert_file_content_type(actual_type, expected_type)
  576.  
  577. def assert_file_content_type(self, content_type, expected_type="core"):
  578. types = []
  579. if expected_type == "core":
  580. types = self.content_types_corefile
  581. if expected_type == "decors":
  582. types = self.content_types_decors
  583. self.assertIn(content_type, types)
  584.  
  585. @staticmethod
  586. def xor(buffer, mask='testKeyForXor'):
  587. mask = mask.encode()
  588. result = []
  589. j = 0
  590. mask_len = len(mask)
  591. for i in range(len(buffer)):
  592. result.append(buffer[i] ^ mask[j])
  593. j += 1
  594. if j == mask_len:
  595. j = 0
  596. return bytearray(result)
  597.  
  598. @staticmethod
  599. def write_blocks_to_stream(blocks):
  600. data_output_stream = io.BytesIO()
  601. stream_metadata = MetadataStructure.StreamMetadata()
  602.  
  603. blocks_metadata = []
  604. for block in blocks:
  605. serialized_message = block.SerializeToString()
  606. block_metadata = stream_metadata.BlockMetadata()
  607. block_metadata.block_size = len(serialized_message)
  608. block_metadata.block_type = 0
  609. blocks_metadata.append(block_metadata)
  610. stream_metadata.blocks_metadata.extend(blocks_metadata)
  611. serialized_metadata = stream_metadata.SerializeToString()
  612.  
  613. # write Stream Metadata size
  614. data_output_stream.write(struct.pack(">i", len(serialized_metadata)))
  615.  
  616. # write Stream Metadata
  617. data_output_stream.write(serialized_metadata)
  618.  
  619. # write Stream Body
  620. for block in blocks:
  621. data_output_stream.write(block.SerializeToString())
  622.  
  623. return data_output_stream.getvalue()
  624.  
  625. def read_blocks_from_stream(self, input_stream):
  626. result = []
  627. input_stream = io.BytesIO(input_stream)
  628.  
  629. header_size, = struct.unpack('>i', input_stream.read(4))
  630. header_bytes = input_stream.read(header_size)
  631.  
  632. stream_metadata = MetadataStructure.StreamMetadata()
  633. stream_metadata.ParseFromString(header_bytes)
  634. blocks_metadata_list = json_format.MessageToDict(stream_metadata)['blocksMetadata']
  635.  
  636. if blocks_metadata_list:
  637. for block_metadata in blocks_metadata_list:
  638. body_buffer = input_stream.read(block_metadata.get('blockSize', 0))
  639. parsed_message = self.block_class_by_type[block_metadata['blockType']]
  640.  
  641. parsed_message_default_values = {}
  642. for parsed_message_key in list(parsed_message.DESCRIPTOR.fields):
  643. try:
  644. parsed_message_default_values[
  645. self.snake_to_camel_case(parsed_message_key.name)] = parsed_message_key.default_value
  646. except NotImplementedError:
  647. parsed_message_default_values[
  648. self.snake_to_camel_case(parsed_message_key.name)] = 'NotImplemented!' # todo
  649. parsed_message.ParseFromString(body_buffer)
  650. # todo add fields with default values
  651. parsed_message = json_format.MessageToDict(parsed_message)
  652. parsed_message = {**parsed_message_default_values, **parsed_message}
  653. result.append({block_metadata['blockType']: [parsed_message, block_metadata['hash']]})
  654. return result
  655.  
  656. def make_protobuf_request(self, request, params):
  657. blocks = self.get_blocks_by_request_type(request)
  658. version_request = MetadataStructure.StreamMetadata.VersionRequest()
  659.  
  660. block_hashes = []
  661. for block in blocks:
  662. block_hash = version_request.BlockHash()
  663. block_hash.block_type = self.block_type_by_class[block.DESCRIPTOR.name][1]
  664. block_hash.hash = ""
  665. block_hashes.append(block_hash)
  666. version_request.block_hashes.extend(block_hashes)
  667.  
  668. # todo request encryption
  669. if 'id' not in params:
  670. params['id'] = '2154-2963-3801'
  671. for k, v in params.items():
  672. version_request.request_params[k] = str(v)
  673.  
  674. request = self.write_blocks_to_stream([version_request])
  675. request_gz = gzip.compress(request, compresslevel=1)
  676. request_gz_xor = self.xor(request_gz)
  677. response_raw = self.make_request(request=self.sdk_method, data=request_gz_xor, req_type='post',
  678. decode_resp=False)
  679. response_xor = self.xor(response_raw['response'].content, mask=params['id'])
  680. response_unzip = gzip.decompress(response_xor)
  681. if response_raw['status'] == self.status_code_ok:
  682. response = self.read_blocks_from_stream(response_unzip)
  683. return {'response': response, 'status': response_raw['status']}
  684. return {'response': response_raw['response'].content, 'status': response_raw['status']}
  685.  
  686. def get_blocks_by_request_type(self, request):
  687. blocks_rules = [RulesStructure.RulesPrimitives(),
  688. RulesStructure.CacheInfo(),
  689. RulesStructure.AppInfo(),
  690. RulesStructure.CryptoMiningData(),
  691. RulesStructure.NetworkBlock(),
  692. RulesStructure.Decor(),
  693. RulesStructure.Rule(),
  694. RulesStructure.SdkInfo(),
  695. ]
  696. blocks_corefile = [CoreStructure.CoreFileTo(),
  697. ]
  698. blocks_corepatch = [CoreStructure.CorePatchTo(),
  699. ]
  700. blocks_extrafile = [ExtraFileStructure.ExtraFileBlock(),
  701. ]
  702. blocks = {
  703. self.request_adconfig_get: blocks_rules,
  704. self.request_adconfig_mapping: blocks_rules,
  705. self.request_corefile_get: blocks_corefile,
  706. self.request_corefile_mapping: blocks_corefile,
  707. self.request_corefile_ios: blocks_corefile,
  708. self.request_corefile_ios_mapping: blocks_corefile,
  709. self.request_corepatch_get: blocks_corepatch,
  710. self.request_corepatch_mapping: blocks_corepatch,
  711. self.request_extrafile_get: blocks_extrafile,
  712. self.request_extrafile_mapping: blocks_extrafile,
  713. self.request_extrafile_ios: blocks_extrafile,
  714. self.request_extrafile_ios_mapping: blocks_extrafile,
  715. self.request_netwfile_get: blocks_extrafile,
  716. self.request_netwfile_mapping: blocks_extrafile,
  717. }[request]
  718. return blocks
  719.  
  720. @staticmethod
  721. def get_block(protobuf_response, block_type):
  722. result = []
  723. for block in protobuf_response:
  724. if list(block.keys())[0] == block_type:
  725. result.append(block)
  726. if len(result) != 1:
  727. raise Exception("Found {} blocks of type {}.".format(len(result), block_type))
  728. return result[0][block_type]
  729.  
  730. @staticmethod
  731. def snake_to_camel_case(value):
  732. value = value.replace('-', '_')
  733. parts = value.split('_')
  734. return {
  735. 'startdelay': 'startDelay',
  736. }.get(value, parts[0] + ''.join(x.title() for x in parts[1:]))
  737.  
  738. @staticmethod
  739. def camel_to_snake_case(value):
  740. if value in ['ruleId', # case converting rule exceptions: don't convert if both json and protobuf have 'ruleId'
  741. ]:
  742. return value
  743. return {
  744. 'startDelay': 'startdelay',
  745. }.get(value, re.sub('([a-z0-9])([A-Z])', r'\1_\2', re.sub('(.)([A-Z][a-z]+)', r'\1_\2', value)).lower())
  746.  
  747. blocks_mapping = {
  748. 'sdk': block_type_sdk_info,
  749. 'app': block_type_app_info,
  750. 'rule': block_type_rule,
  751. 'cache': block_type_cache_info,
  752. 'networks': block_type_network,
  753. 'decors': block_type_decor,
  754. }
  755.  
  756. # todo
  757. blocks_mapping2 = {
  758. block_type_sdk_info: 'sdk',
  759. block_type_app_info: 'app',
  760. block_type_rule: 'rule',
  761. block_type_cache_info: 'cache',
  762. block_type_network: 'networks',
  763. block_type_decor: 'decors',
  764. block_type_crypto_mining_data: 'crypto_mining_data',
  765. }
  766.  
  767. rules_primitives = [
  768. 'result',
  769. 'error',
  770. 'silent',
  771. 'optout',
  772. 'country',
  773. ]
  774.  
  775. def assert_protobuf_response2(self, json_response, protobuf_response, params):
  776. json_response = json_response['response']
  777. protobuf_response = protobuf_response['response']
  778. json_keys = [x for x in json_response.keys() if x not in self.rules_primitives]
  779. json_keys_primitives = [x for x in json_response.keys() if x in self.rules_primitives]
  780. diff = []
  781.  
  782. # primitives
  783. protobuf_block = self.get_block(protobuf_response, self.block_type_rules_primitives)
  784. diff = self.assert_block(diff=diff,
  785. json_keys=json_keys_primitives,
  786. json_response=json_response,
  787. protobuf_block=protobuf_block,
  788. block_type=self.block_type_rules_primitives)
  789.  
  790. # other keys
  791. for key in json_keys:
  792. json_block_keys = json_response[key].keys()
  793. protobuf_block = self.get_block(protobuf_response, self.blocks_mapping[key])
  794. diff = self.assert_block(diff=diff,
  795. json_keys=json_block_keys,
  796. json_response=json_response[key],
  797. protobuf_block=protobuf_block,
  798. block_type=self.blocks_mapping[key])
  799.  
  800. # custom keys
  801. diff = self.assert_block(diff=diff,
  802. json_keys=json_response['rule']['decors'].keys(),
  803. json_response=json_response['rule']['decors'],
  804. protobuf_block=self.get_block(protobuf_response, self.blocks_mapping['decors']),
  805. block_type=self.blocks_mapping['decors'])
  806. # networks
  807. diff = self.assert_networks(json_response['rule']['networks'],
  808. self.get_block(protobuf_response, self.blocks_mapping['networks'])[0]['networks'],
  809. diff)
  810.  
  811. # todo compare way 1
  812. # self.assertEqual(diff, [])
  813. print(params)
  814.  
  815. def assert_block(self, diff, json_keys, json_response, protobuf_block, block_type):
  816. json_keys = [x.replace('-', '_') for x in json_keys]
  817. protobuf_keys = protobuf_block[0].keys()
  818.  
  819. protobuf_keys_snake_case = [self.camel_to_snake_case(x) for x in protobuf_keys]
  820. keys_diff_json = set(json_keys) - set(protobuf_keys_snake_case)
  821.  
  822. if block_type == self.block_type_rule and 'decors' in keys_diff_json:
  823. keys_diff_json.remove('decors')
  824. if block_type == self.block_type_rule and 'networks' in keys_diff_json:
  825. keys_diff_json.remove('networks')
  826.  
  827. if keys_diff_json:
  828. diff.append([block_type, 'Keys that present in json but absent in protobuf.', keys_diff_json])
  829.  
  830. json_keys_camel_case = [self.snake_to_camel_case(x) for x in json_keys]
  831. keys_diff_protobuf = set(protobuf_keys) - set(json_keys_camel_case)
  832. if keys_diff_protobuf:
  833. diff.append([block_type, 'Keys that present in protobuf but absent in json.', keys_diff_protobuf])
  834.  
  835. block_diff = []
  836. if block_type == self.block_type_rules_primitives:
  837. for key in self.rules_primitives:
  838. block_diff = self.get_block_diff(block_diff, json_response, protobuf_block, key)
  839. else:
  840. for key in json_response:
  841. block_diff = self.get_block_diff(block_diff, json_response, protobuf_block, key)
  842. if block_diff:
  843. diff.append([block_type, 'Values diff.', block_diff])
  844. return diff
  845.  
  846. def get_block_diff(self, diff, json_response, block, key):
  847. try:
  848. json_value = json_response[key]
  849. protobuf_value = block[0][self.snake_to_camel_case(key)]
  850. if type(json_value) is bool or type(protobuf_value) is bool:
  851. if json_value in ['true', 'false']:
  852. json_value = self.bool_from_string(json_value)
  853. if type(json_value) is int and type(self.try_int_from_string(protobuf_value)) is int:
  854. protobuf_value = self.try_int_from_string(protobuf_value)
  855. if json_value is None and protobuf_value == '':
  856. json_value = ''
  857. self.assertEqual(json_value, protobuf_value)
  858. except KeyError:
  859. # diff.append(["KeyError", key])
  860. pass
  861. except AssertionError:
  862. diff.append([
  863. 'json: {} = {} ({})'.format(key, json_response[key], type(json_response[key])),
  864. 'protobuf: {} = {} ({})'.format(self.snake_to_camel_case(key), block[0][self.snake_to_camel_case(key)],
  865. type(block[0][self.snake_to_camel_case(key)]))])
  866. return diff
  867.  
  868. @staticmethod
  869. def bool_from_string(value):
  870. return {
  871. 'true': True,
  872. 'false': False,
  873. }[value]
  874.  
  875. def build_json_from_protobuf(self, protobuf_response):
  876. json_rules = {'cache': {},
  877. 'sdk': {},
  878. 'app': {},
  879. 'rule': {},
  880. 'crypto_mining_data': {},
  881. }
  882. # RULES_PRIMITIVES
  883. block_primitives = self.get_block(protobuf_response, self.block_type_rules_primitives)[0]
  884. for k, v in block_primitives.items():
  885. json_rules[self.camel_to_snake_case(k)] = v
  886. # OTHER BLOCKS
  887. for block in protobuf_response:
  888. block_type = list(block.keys())[0]
  889. if block_type not in [self.block_type_rules_primitives,
  890. self.block_type_network,
  891. self.block_type_decor,
  892. ]:
  893. block_values = {}
  894. for k, v in list(block.values())[0][0].items():
  895. block_values[self.camel_to_snake_case(k)] = v
  896. json_rules[self.blocks_mapping2[block_type]].update(block_values)
  897. continue
  898. # NETWORKS
  899. if block_type in [self.block_type_network,
  900. ]:
  901. json_rules['rule'].update(list(block.values())[0][0])
  902. continue
  903. # DECORS
  904. if block_type in [self.block_type_decor,
  905. ]:
  906. json_rules['rule']['decors'] = list(block.values())[0][0]['imgs']
  907. continue
  908. return json_rules
  909.  
  910. def assert_networks(self, json_networks, protobuf_networks, diff):
  911. diff_networks = []
  912. if len(json_networks) != len(protobuf_networks):
  913. diff_networks.append([self.block_type_network,
  914. f'Number of networks in json: {len(json_networks)} '
  915. f'!= number of networks in protobuf: {len(protobuf_networks)}'])
  916. for json_network in json_networks:
  917. protobuf_network = [x for x in protobuf_networks if x['id'] == json_network['id']][0]
  918. if 'params' in protobuf_network:
  919. for k, v in protobuf_network['params'].items():
  920. protobuf_network[k] = v
  921. del (protobuf_network['params'])
  922. diff_keys = json_network.keys() - protobuf_network.keys()
  923. if diff_keys:
  924. diff_networks.append([json_network['id'], diff_keys])
  925. for diff_key in diff_keys:
  926. del json_network[diff_key]
  927. for k, v in json_network.items():
  928. try:
  929. self.assertEqual(v, protobuf_network[k])
  930. except AssertionError:
  931. diff_networks.append(
  932. [json_network['id'], f'Values diff. json: {v}. protobuf: {protobuf_network[k]}'])
  933. diff.append(diff_networks)
  934. return diff
  935.  
  936. decor_types = [
  937. 'mdpi',
  938. 'hdpi',
  939. 'xhdpi',
  940. 'xxhdpi',
  941. ]
  942.  
  943. def remove_decors_from_json(self, json_response, decor='hdpi'):
  944. decors = self.flatten_decors(json_response['rule']['decors'][decor])
  945. json_response['rule']['decors'] = decors
  946. return json_response
  947.  
  948. @staticmethod
  949. def flatten_decors(d):
  950. result = {}
  951. for k, v in d.items():
  952. if type(v) is dict:
  953. for kk, vv in v.items():
  954. result[f'{k}.{kk}'] = vv
  955. else:
  956. result[f'default.{k}'] = v
  957. return result
  958.  
  959. def build_json_from_json(self, json_response):
  960. json_from_json = deepcopy(json_response)
  961. json_from_json = self.remove_decors_from_json(json_from_json)
  962. return json_from_json
  963.  
  964. def assert_protobuf_response(self, json_response, protobuf_response, params):
  965. # todo: Compare json and protobuf responses.
  966. # Simplify both, convert them to similar json objects, then compare.
  967. json_from_json2 = json.dumps(self.build_json_from_json(json_response['response']), sort_keys=True)
  968. json_from_protobuf2 = json.dumps(self.build_json_from_protobuf(protobuf_response['response']), sort_keys=True)
  969. json_from_json = self.build_json_from_json(json_response['response'])
  970. json_from_protobuf = self.build_json_from_protobuf(protobuf_response['response'])
  971. log_file = open('json_logs.json', 'w')
  972. log_file.write(str(json_from_json))
  973. log_file.close()
  974. log_file = open('protobuf_logs.json', 'w')
  975. log_file.write(str(json_from_protobuf))
  976. log_file.close()
  977. # print(json_from_json == json_from_protobuf)
  978. # dict_diff = {k: json_from_protobuf[k] for k in set(json_from_protobuf) - set(json_from_json)}
  979. # print(dict_diff)
  980. #
  981. # diff = []
  982. # diff = self.get_rules_diff(json_from_json, json_from_protobuf, diff)
  983. # print(diff)
  984. diff = self.check_diff(json_from_json, json_from_protobuf)
  985. print("finish")
  986. # print(diff)
  987. for i in diff:
  988. print(i)
  989. print("finish")
  990. # for i in diff:
  991. # print(i)
  992.  
  993. def get_rules_diff(self, json_from_json, json_from_protobuf, diff, key=''):
  994. for k, v in json_from_json.items():
  995. if (type(v) not in (dict, list, set)) or (type(v) is list and type(v[0]) not in (dict, list, set)):
  996. try:
  997. self.assertEqual(v, json_from_protobuf[k])
  998. except KeyError:
  999. diff.append(['KeyError', f'{key}.{k}'])
  1000. except AssertionError:
  1001. diff.append(['AssertionError',
  1002. f'Json: {k} = {v} ({type(v)})',
  1003. f'Protobuf {k} = {json_from_protobuf[k]} ({type(json_from_protobuf[k])})'])
  1004. elif type(v) is dict:
  1005. diff = self.get_rules_diff(v, json_from_protobuf[k], diff, k)
  1006. elif type(v) is list and type(v[0]) is dict:
  1007. diff = self.get_rules_diff(v, json_from_protobuf[k], diff, k)
  1008. return diff
  1009.  
  1010. @staticmethod
  1011. def check_ext(json_key, json_ext):
  1012. temp = True
  1013. # print("here in check ext",json_key)
  1014. for key in json_ext:
  1015. if key == json_key:
  1016. print('исключение', key)
  1017. temp = False
  1018. return temp
  1019. return temp
  1020.  
  1021. def check_diff(self, origin_json, protobuf_json):
  1022. res = True
  1023. for key in origin_json:
  1024. res = self.check_ext(key, self.block_exception)
  1025. if not res:
  1026. continue
  1027. try:
  1028. if key == "networks" or key == "app" or key == "sdk":
  1029. print('*****************{}*******************'.format(key))
  1030. print(diff(origin_json[key], protobuf_json[key]))
  1031. print('*****************{}*******************'.format(key))
  1032. continue
  1033.  
  1034. if (type(origin_json[key]) and type(protobuf_json[key])) is dict:
  1035. self.check_diff(origin_json[key], protobuf_json[key])
  1036. # elif (type(origin_json[key]) is dict and type(protobuf_json[key]) is not dict) or (type(origin_json[key]) not dict and type(protobuf_json[key]) not dict):
  1037. # print('diffetent types')
  1038. elif (type(origin_json[key]) and type(protobuf_json[key])) is list:
  1039. pass
  1040. # origin_sorted = sorted(origin_json[key], key=dict)
  1041. # protobuf_sorted = sorted(protobuf_json[key], key=dict)
  1042. # for origin_key in range(0, len(origin_sorted)):
  1043. # for proto_key in range(0, len(protobuf_sorted)):
  1044. # if isinstance(origin_sorted[origin_key], dict) and isinstance(
  1045. # protobuf_sorted[proto_key],
  1046. # dict):
  1047. # self.check_diff(origin_sorted[origin_key], protobuf_sorted[proto_key])
  1048. # # print('*****************json*******************')
  1049. # # print(diff(origin_json[key][origin_key], protobuf_json[key][proto_key]))
  1050. # # print('*****************json*******************')
  1051. # elif str(origin_sorted[origin_key]).lower() != str(
  1052. # protobuf_sorted[proto_key]).lower():
  1053. # self.json_diff_arr.append({
  1054. # key: (origin_sorted[origin_key], protobuf_sorted[proto_key])
  1055. # })
  1056.  
  1057. elif str(origin_json[key]).lower() != str(protobuf_json[key]).lower():
  1058. self.json_diff_arr.append({
  1059. key: (origin_json[key], protobuf_json[key])
  1060. })
  1061.  
  1062. except KeyError:
  1063. print('************************************')
  1064. print("error is here. key not found")
  1065. print('key value', key)
  1066. print("json", origin_json[key])
  1067. print("prot", protobuf_json[key])
  1068. print('************************************')
  1069. return self.json_diff_arr
  1070.  
  1071. def check_difference(self, orig, new):
  1072. diff = {}
  1073. result = False
  1074. if type(orig) != type(new):
  1075. print("Type difference")
  1076. return True
  1077. else:
  1078. if type(orig) is dict and type(new) is dict:
  1079. print("Types are both dicts")
  1080. # Check each of these dicts from the key level
  1081. diff_test = False
  1082. for key in orig:
  1083. try:
  1084. result = self.check_difference(orig[key], new[key])
  1085. except KeyError:
  1086. print("error is here")
  1087. print('result var', result)
  1088. print('key value', key)
  1089. print("json", orig[key])
  1090. print("prot", new[key])
  1091. # raise
  1092.  
  1093. if result: # Means a difference was found and returned
  1094. diff_test = True
  1095. print("key/Values different: " + str(key))
  1096. diff[key] = result
  1097. else:
  1098. result = False
  1099. # And check for keys in second dataset that aren't in first
  1100. for key in new:
  1101. if key not in orig:
  1102. diff[key] = ("KeyNotFound", new[key])
  1103. diff_test = True
  1104.  
  1105. if diff_test:
  1106. return diff
  1107. else:
  1108. return False
  1109. else:
  1110. print("Types were not dicts, likely strings")
  1111. if str(orig) == str(new):
  1112. return False
  1113. else:
  1114. return [str(orig), str(new)]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement