NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

test_skillExtractorController.py (35036B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\skilltrading\test\test_skillExtractorController.py
      2 from itertools import izip
      3 import mock
      4 import unittest
      5 from eve.client.script.ui.skilltrading.skillExtractorController import *
      6 from testsuites.testcases import ClientTestCase
      7 
      8 class SkillExtractorControllerTestImpl(SkillExtractorControllerBase):
      9 
     10     def __init__(self, *args, **kwargs):
     11         super(SkillExtractorControllerTestImpl, self).__init__(*args, **kwargs)
     12         self._mock_skill_list = []
     13         self._mock_skill_queue = []
     14         self._mock_skill_restrictions = {}
     15         self._final_extracted_skills = None
     16         self._final_itemID = None
     17 
     18     def GetSkills(self):
     19         skills = []
     20         for s in self._mock_skill_list:
     21             if hasattr(s, 'typeID'):
     22                 skills.append(s)
     23             else:
     24                 skill = SkillFixture(s['typeID'], s['sp'], s.get('rank', 1.0), s.get('requirements', None), s.get('dependencies', None))
     25                 skills.append(skill)
     26 
     27         return skills
     28 
     29     def GetSkillQueue(self):
     30         return self._mock_skill_queue
     31 
     32     def GetSkillRestrictions(self):
     33         return self._mock_skill_restrictions
     34 
     35     def PerformExtraction(self, itemID, skills):
     36         self._final_extracted_skills = skills
     37         self._final_itemID = itemID
     38 
     39 
     40 class SkillFixture(SkillBase):
     41 
     42     def __init__(self, typeID, points, rank, requirements = None, dependencies = None):
     43         super(SkillFixture, self).__init__(typeID=typeID, points=points)
     44         self._rank = rank
     45         self._requirements = requirements if requirements is not None else {}
     46         self._dependencies = dependencies if dependencies is not None else {}
     47         self.onUpdateHandler = mock.Mock()
     48         self.onUpdate.connect(self.onUpdateHandler)
     49 
     50     def GetRequirements(self):
     51         return self._requirements
     52 
     53     def GetDependencies(self):
     54         return self._dependencies
     55 
     56     def GetRank(self):
     57         return self._rank
     58 
     59 
     60 EXTRACTOR_ITEM_ID = 123
     61 SP_R1_L1 = 250
     62 SP_R1_L2 = 1415
     63 SP_R1_L3 = 8000
     64 SP_R1_L4 = 45255
     65 SP_R1_L5 = 256000
     66 SKILL_R1_L0 = {'typeID': 1,
     67  'rank': 1.0,
     68  'sp': 0,
     69  'level': 0,
     70  'requirements': {10: 1}}
     71 SKILL_R1_L0_TRAINED = {'typeID': 2,
     72  'rank': 1.0,
     73  'sp': 125,
     74  'level': 0}
     75 SKILL_R1_L1 = {'typeID': 3,
     76  'rank': 1.0,
     77  'sp': SP_R1_L1,
     78  'level': 1,
     79  'requirements': {10: 1}}
     80 SKILL_R1_L1_TRAINED = {'typeID': 4,
     81  'rank': 1.0,
     82  'sp': 500,
     83  'level': 1}
     84 SKILL_R1_L2 = {'typeID': 5,
     85  'rank': 1.0,
     86  'sp': SP_R1_L2,
     87  'level': 2}
     88 SKILL_R1_L4 = {'typeID': 6,
     89  'rank': 1.0,
     90  'sp': SP_R1_L4,
     91  'level': 4}
     92 SKILL_R1_L5 = {'typeID': 7,
     93  'rank': 1.0,
     94  'sp': SP_R1_L5,
     95  'level': 5}
     96 SKILL_R4_L5 = {'typeID': 8,
     97  'rank': 4.0,
     98  'sp': 1024000,
     99  'level': 5}
    100 SKILL_R10_L5 = {'typeID': 9,
    101  'rank': 10.0,
    102  'sp': 2560000,
    103  'level': 5}
    104 SKILL_R1_L1_PREREQ_L1 = {'typeID': 10,
    105  'rank': 1.0,
    106  'sp': SP_R1_L1,
    107  'level': 1,
    108  'dependencies': {3: 1,
    109                   1: 1}}
    110 SKILL_R1_L1_PREREQ_L1_TRAINED = {'typeID': 10,
    111  'rank': 1.0,
    112  'sp': 500,
    113  'level': 1,
    114  'dependencies': {3: 1,
    115                   1: 1}}
    116 SKILL_R1_L1_PREREQ_L5 = {'typeID': 10,
    117  'rank': 1.0,
    118  'sp': SP_R1_L5,
    119  'level': 5,
    120  'dependencies': {3: 1,
    121                   1: 1}}
    122 
    123 class TestSkill(ClientTestCase):
    124 
    125     def test_untrained_skill(self):
    126         skill = SkillFixture(typeID=1, points=0, rank=1.0)
    127         self.assertAlmostEqual(skill.progress, 0.0)
    128 
    129     def test_trained_level_zero_skill(self):
    130         skill = SkillFixture(typeID=1, points=125, rank=1.0)
    131         self.assertAlmostEqual(skill.progress, 0.5)
    132 
    133     def test_trained_level_four_skill(self):
    134         skill = SkillFixture(typeID=1, points=87404, rank=1.0)
    135         self.assertAlmostEqual(skill.progress, 0.2)
    136 
    137     def test_level_five_skill(self):
    138         skill = SkillFixture(typeID=1, points=256000, rank=1.0)
    139         self.assertAlmostEqual(skill.progress, 0.0)
    140 
    141     def test_unmodified_attributes(self):
    142         skill = SkillFixture(typeID=1, points=250, rank=1.0)
    143         skill.points = 125
    144         self.assertEqual(skill.points, 125)
    145         self.assertEqual(skill.level, 0)
    146         self.assertEqual(skill.progress, 0.5)
    147         self.assertEqual(skill.unmodifiedPoints, 250)
    148         self.assertEqual(skill.unmodifiedLevel, 1)
    149         self.assertEqual(skill.unmodifiedProgress, 0.0)
    150 
    151 
    152 @unittest.skip('Tests fail with NotImplementedError')
    153 
    154 class TestSkillExtractorController(ClientTestCase):
    155 
    156     def setUp(self):
    157         super(TestSkillExtractorController, self).setUp()
    158         self._next_skill_id = 1
    159         self.controller = SkillExtractorControllerTestImpl(EXTRACTOR_ITEM_ID)
    160         self.events = mock.Mock()
    161         self.controller.onUpdate.connect(self.events.on_update)
    162         self.controller.onSkillListUpdate.connect(self.events.on_skill_list_update)
    163 
    164     def test_get_no_skills(self):
    165         self.controller._mock_skill_list = []
    166         skills = self.controller.skills
    167         self.assertEqual(skills, [])
    168 
    169     def test_get_skills(self):
    170         self.controller._mock_skill_list = expected = [SKILL_R1_L0, SKILL_R1_L5]
    171         self.assertSkillListEqual(expected)
    172 
    173     def test_extract_nonexisting_skill(self):
    174         self.controller._mock_skill_list = []
    175         with self.assertRaises(SkillNotFoundError):
    176             self.controller.ExtractSkill(1)
    177         self.assertEqual(self.events.on_update.call_count, 0)
    178 
    179     def test_extract_untrained_skill(self):
    180         self.controller._mock_skill_list = [SKILL_R1_L0]
    181         with self.assertRaises(NoSkillpointsError):
    182             self.controller.ExtractSkill(SKILL_R1_L0['typeID'])
    183         self.assertEqual(self.events.on_update.call_count, 0)
    184 
    185     def test_extract_trained_level_zero_skill(self):
    186         self.controller._mock_skill_list = [SKILL_R1_L0_TRAINED]
    187         self.controller.ExtractSkill(SKILL_R1_L0_TRAINED['typeID'])
    188         self.assertEqual(self.controller.extractedPoints, SKILL_R1_L0_TRAINED['sp'])
    189         self.assertEqual(self.getSkill(SKILL_R1_L0_TRAINED).points, 0)
    190         self.assertEqual(self.getSkill(SKILL_R1_L0_TRAINED).level, 0)
    191 
    192     def test_skill_extraction_events(self):
    193         self.controller._mock_skill_list = [SKILL_R1_L1]
    194         self.controller.ExtractSkill(SKILL_R1_L1['typeID'])
    195         self.events.on_update.assert_called_once_with()
    196         self.getSkill(SKILL_R1_L1).onUpdateHandler.assert_called_once_with()
    197 
    198     def test_extract_level_one_skill(self):
    199         self.controller._mock_skill_list = [SKILL_R1_L1]
    200         self.controller.ExtractSkill(SKILL_R1_L1['typeID'])
    201         self.assertEqual(self.controller.extractedPoints, 250)
    202         self.assertEqual(self.getSkill(SKILL_R1_L1).points, 0)
    203         self.assertEqual(self.getSkill(SKILL_R1_L1).level, 0)
    204         self.events.on_update.assert_called_once_with()
    205 
    206     def test_extract_fully_extracted_skill(self):
    207         self.controller._mock_skill_list = [SKILL_R1_L1]
    208         self.preExtract(SKILL_R1_L1)
    209         with self.assertRaises(NoSkillpointsError):
    210             self.controller.ExtractSkill(SKILL_R1_L1['typeID'])
    211 
    212     def test_extract_level_five_skill_five_times(self):
    213         self.controller._mock_skill_list = [SKILL_R1_L5]
    214         self.controller.ExtractSkill(SKILL_R1_L5['typeID'])
    215         self.controller.ExtractSkill(SKILL_R1_L5['typeID'])
    216         self.controller.ExtractSkill(SKILL_R1_L5['typeID'])
    217         self.controller.ExtractSkill(SKILL_R1_L5['typeID'])
    218         self.controller.ExtractSkill(SKILL_R1_L5['typeID'])
    219         self.assertEqual(self.controller.extractedPoints, SKILL_R1_L5['sp'])
    220         self.assertEqual(self.getSkill(SKILL_R1_L5).points, 0)
    221         self.assertEqual(self.getSkill(SKILL_R1_L5).level, 0)
    222         self.assertEqual(self.events.on_update.call_count, 5)
    223 
    224     def test_extract_level_two_skill(self):
    225         self.controller._mock_skill_list = [SKILL_R1_L2]
    226         self.controller.ExtractSkill(SKILL_R1_L2['typeID'])
    227         self.assertEqual(self.controller.extractedPoints, 1165)
    228         self.assertEqual(self.getSkill(SKILL_R1_L2).points, 250)
    229         self.assertEqual(self.getSkill(SKILL_R1_L2).level, 1)
    230         self.events.on_update.assert_called_once_with()
    231 
    232     def test_extract_trained_level_one_skill(self):
    233         self.controller._mock_skill_list = [SKILL_R1_L1_TRAINED]
    234         self.controller.ExtractSkill(SKILL_R1_L1_TRAINED['typeID'])
    235         self.assertEqual(self.controller.extractedPoints, 250)
    236         self.assertEqual(self.getSkill(SKILL_R1_L1_TRAINED).points, 250)
    237         self.assertEqual(self.getSkill(SKILL_R1_L1_TRAINED).level, 1)
    238         self.events.on_update.assert_called_once_with()
    239 
    240     def test_fully_extract_trained_level_one_skill(self):
    241         self.controller._mock_skill_list = [SKILL_R1_L1_TRAINED]
    242         self.controller.ExtractSkill(SKILL_R1_L1_TRAINED['typeID'])
    243         self.controller.ExtractSkill(SKILL_R1_L1_TRAINED['typeID'])
    244         self.assertEqual(self.controller.extractedPoints, SKILL_R1_L1_TRAINED['sp'])
    245         self.assertEqual(self.getSkill(SKILL_R1_L1_TRAINED).points, 0)
    246         self.assertEqual(self.getSkill(SKILL_R1_L1_TRAINED).level, 0)
    247         self.assertEqual(self.events.on_update.call_count, 2)
    248 
    249     def test_extraction_skillpoint_goal(self):
    250         self.controller._mock_skill_list = [SKILL_R4_L5]
    251         self.controller.ExtractSkill(SKILL_R4_L5['typeID'])
    252         self.assertEqual(self.controller.extractedPoints, self.controller.SKILL_POINT_GOAL)
    253         self.assertEqual(self.getSkill(SKILL_R4_L5).points, 524000)
    254         self.assertEqual(self.getSkill(SKILL_R4_L5).level, 4)
    255 
    256     def test_extract_skill_with_goal_reached(self):
    257         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R10_L5]
    258         self.preExtract(SKILL_R10_L5)
    259         with self.assertRaises(GoalAlreadyReachedError):
    260             self.controller.ExtractSkill(SKILL_R1_L1['typeID'])
    261         self.assertEqual(self.controller.extractedPoints, self.controller.SKILL_POINT_GOAL)
    262         self.assertEqual(self.getSkill(SKILL_R1_L1).points, SKILL_R1_L1['sp'])
    263         self.assertEqual(self.getSkill(SKILL_R1_L1).level, SKILL_R1_L1['level'])
    264         self.assertEqual(self.events.on_update.call_count, 0)
    265 
    266     def test_revert_unextracted_skill(self):
    267         self.controller._mock_skill_list = [SKILL_R1_L1]
    268         with self.assertRaises(SkillNotExtractedError):
    269             self.controller.Revert(SKILL_R1_L1['typeID'])
    270         self.assertEqual(self.controller.extractedPoints, 0)
    271         self.assertEqual(self.getSkill(SKILL_R1_L1).points, SKILL_R1_L1['sp'])
    272         self.assertEqual(self.getSkill(SKILL_R1_L1).onUpdateHandler.call_count, 0)
    273 
    274     def test_revert_unextracted_skill_with_other_skill_extracted(self):
    275         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R1_L5]
    276         self.preExtract(SKILL_R1_L1)
    277         with self.assertRaises(SkillNotExtractedError):
    278             self.controller.Revert(SKILL_R1_L5['typeID'])
    279         self.assertEqual(self.controller.extractedPoints, SKILL_R1_L1['sp'])
    280         self.assertEqual(self.getSkill(SKILL_R1_L1).points, 0)
    281         self.assertEqual(self.getSkill(SKILL_R1_L5).points, SKILL_R1_L5['sp'])
    282         self.assertEqual(self.getSkill(SKILL_R1_L5).onUpdateHandler.call_count, 0)
    283 
    284     def test_revert_single_skill_level(self):
    285         self.controller._mock_skill_list = [SKILL_R1_L1]
    286         self.preExtract(SKILL_R1_L1)
    287         self.controller.Revert(SKILL_R1_L1['typeID'])
    288         self.assertEqual(self.controller.extractedPoints, 0)
    289         self.assertEqual(self.getSkill(SKILL_R1_L1).points, SKILL_R1_L1['sp'])
    290         self.getSkill(SKILL_R1_L1).onUpdateHandler.assert_called_once_with()
    291 
    292     def test_revert_skill_after_extracting_other_different_skill(self):
    293         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R1_L5]
    294         self.preExtract(SKILL_R1_L1, SKILL_R1_L5)
    295         self.controller.Revert(SKILL_R1_L1['typeID'])
    296         self.assertEqual(self.controller.extractedPoints, SKILL_R1_L5['sp'] - SKILL_R1_L4['sp'])
    297         self.assertEqual(self.getSkill(SKILL_R1_L1).points, SKILL_R1_L1['sp'])
    298         self.getSkill(SKILL_R1_L1).onUpdateHandler.assert_called_once_with()
    299         self.assertEqual(self.getSkill(SKILL_R1_L5).points, SKILL_R1_L4['sp'])
    300         self.assertEqual(self.getSkill(SKILL_R1_L5).onUpdateHandler.call_count, 0)
    301 
    302     def test_revert_skill_after_extracting_it_twice(self):
    303         self.controller._mock_skill_list = [SKILL_R1_L5]
    304         self.preExtract(SKILL_R1_L5, SKILL_R1_L5)
    305         self.controller.Revert(SKILL_R1_L5['typeID'])
    306         self.assertEqual(self.controller.extractedPoints, SKILL_R1_L5['sp'] - SKILL_R1_L4['sp'])
    307         self.assertEqual(self.getSkill(SKILL_R1_L5).points, SKILL_R1_L4['sp'])
    308         self.getSkill(SKILL_R1_L5).onUpdateHandler.assert_called_once_with()
    309 
    310     def test_extract_required_skill_level(self):
    311         self.controller._mock_skill_list = [SKILL_R1_L1_PREREQ_L1, SKILL_R1_L1]
    312         self.assertTrue(self.getSkill(SKILL_R1_L1_PREREQ_L1).isRequired)
    313         with self.assertRaises(SkillLockedError):
    314             self.controller.ExtractSkill(SKILL_R1_L1_PREREQ_L1['typeID'])
    315 
    316     def test_extract_required_skill_nonrequired_level(self):
    317         self.controller._mock_skill_list = [SKILL_R1_L1_PREREQ_L5, SKILL_R1_L1]
    318         self.assertFalse(self.getSkill(SKILL_R1_L1_PREREQ_L5).isRequired)
    319         self.controller.ExtractSkill(SKILL_R1_L1_PREREQ_L5['typeID'])
    320         self.assertFalse(self.getSkill(SKILL_R1_L1_PREREQ_L5).isRequired)
    321 
    322     def test_extract_required_half_trained_skill(self):
    323         self.controller._mock_skill_list = [SKILL_R1_L1_PREREQ_L1_TRAINED, SKILL_R1_L1]
    324         self.assertFalse(self.getSkill(SKILL_R1_L1_PREREQ_L1_TRAINED).isRequired)
    325         self.controller.ExtractSkill(SKILL_R1_L1_PREREQ_L1_TRAINED['typeID'])
    326         self.assertTrue(self.getSkill(SKILL_R1_L1_PREREQ_L1_TRAINED).isRequired)
    327 
    328     def test_extracting_dependent_skill_unlocks_requirements(self):
    329         self.controller._mock_skill_list = [SKILL_R1_L1_PREREQ_L1, SKILL_R1_L1]
    330         self.assertTrue(self.getSkill(SKILL_R1_L1_PREREQ_L1).isRequired)
    331         self.controller.ExtractSkill(SKILL_R1_L1['typeID'])
    332         self.assertFalse(self.getSkill(SKILL_R1_L1_PREREQ_L1).isRequired)
    333 
    334     def test_extract_required_skill_after_dependent_skill(self):
    335         self.controller._mock_skill_list = [SKILL_R1_L1_PREREQ_L1, SKILL_R1_L1]
    336         self.preExtract(SKILL_R1_L1)
    337         self.controller.ExtractSkill(SKILL_R1_L1_PREREQ_L1['typeID'])
    338         self.assertFalse(self.getSkill(SKILL_R1_L1_PREREQ_L1).isRequired)
    339         self.getSkill(SKILL_R1_L1_PREREQ_L1).onUpdateHandler.assert_called_once_with()
    340 
    341     def test_revert_updates_required_skill(self):
    342         self.controller._mock_skill_list = [SKILL_R1_L1_PREREQ_L1_TRAINED, SKILL_R1_L1]
    343         self.preExtract(SKILL_R1_L1_PREREQ_L1_TRAINED)
    344         self.controller.Revert(SKILL_R1_L1_PREREQ_L1_TRAINED['typeID'])
    345         self.assertFalse(self.getSkill(SKILL_R1_L1_PREREQ_L1_TRAINED).isRequired)
    346 
    347     def test_revert_updates_dependent_skill(self):
    348         self.controller._mock_skill_list = [SKILL_R1_L1_PREREQ_L1, SKILL_R1_L1]
    349         self.preExtract(SKILL_R1_L1)
    350         self.controller.Revert(SKILL_R1_L1['typeID'])
    351         self.assertTrue(self.getSkill(SKILL_R1_L1_PREREQ_L1).isRequired)
    352         self.getSkill(SKILL_R1_L1).onUpdateHandler.assert_called_once_with()
    353 
    354     def test_revert_dependent_skill_also_reverts_required_skills(self):
    355         self.controller._mock_skill_list = [SKILL_R1_L1_PREREQ_L1, SKILL_R1_L1]
    356         self.preExtract(SKILL_R1_L1, SKILL_R1_L1_PREREQ_L1)
    357         self.controller.Revert(SKILL_R1_L1['typeID'])
    358         self.assertEqual(self.controller.extractedPoints, 0)
    359         self.assertEqual(self.getSkill(SKILL_R1_L1).points, SKILL_R1_L1['sp'])
    360         self.assertEqual(self.getSkill(SKILL_R1_L1_PREREQ_L1).points, SKILL_R1_L1_PREREQ_L1['sp'])
    361         self.getSkill(SKILL_R1_L1).onUpdateHandler.assert_called_once_with()
    362         self.getSkill(SKILL_R1_L1_PREREQ_L1).onUpdateHandler.assert_called_once_with()
    363 
    364     def test_revert_dependent_skill_also_reverts_whole_chain_of_required_skills(self):
    365         SKILL_A = {'typeID': 100,
    366          'rank': 1.0,
    367          'sp': SP_R1_L1,
    368          'level': 1,
    369          'requirements': {101: 1}}
    370         SKILL_B = {'typeID': 101,
    371          'rank': 1.0,
    372          'sp': SP_R1_L1,
    373          'level': 1,
    374          'requirements': {102: 1},
    375          'dependencies': {100: 1}}
    376         SKILL_C = {'typeID': 102,
    377          'rank': 1.0,
    378          'sp': SP_R1_L1,
    379          'level': 1,
    380          'dependencies': {101: 1}}
    381         self.controller._mock_skill_list = [SKILL_A, SKILL_B, SKILL_C]
    382         self.preExtract(SKILL_A, SKILL_B, SKILL_C)
    383         self.controller.Revert(SKILL_A['typeID'])
    384         self.assertEqual(self.controller.extractedPoints, 0)
    385         self.assertEqual(self.getSkill(SKILL_A).points, SKILL_A['sp'])
    386         self.assertEqual(self.getSkill(SKILL_B).points, SKILL_B['sp'])
    387         self.assertEqual(self.getSkill(SKILL_C).points, SKILL_C['sp'])
    388         self.getSkill(SKILL_A).onUpdateHandler.assert_called_once_with()
    389         self.getSkill(SKILL_B).onUpdateHandler.assert_called_once_with()
    390         self.getSkill(SKILL_C).onUpdateHandler.assert_called_once_with()
    391 
    392     def test_revert_dependent_skill_reverts_requirements_to_minimum_required_level(self):
    393         SKILL_B = self.addSkill(points=SP_R1_L3)
    394         SKILL_A = self.addSkill(points=SP_R1_L1, requirements=[(SKILL_B, 2)])
    395         self.preExtract(SKILL_A, SKILL_B, SKILL_B)
    396         self.controller.Revert(SKILL_A.typeID)
    397         self.assertEqual(SKILL_B.level, 2)
    398         self.assertEqual(SKILL_B.points, SP_R1_L2)
    399         SKILL_A.onUpdateHandler.assert_called_once_with()
    400         SKILL_B.onUpdateHandler.assert_called_once_with()
    401 
    402     def test_commit_with_nothing_extracted(self):
    403         with self.assertRaises(NotEnoughExtractedError):
    404             self.controller.Commit()
    405         self.assertFalse(self.controller.isCompleted)
    406 
    407     def test_commit_with_less_than_needed_extracted(self):
    408         self.controller._mock_skill_list = [SKILL_R1_L1]
    409         self.controller.ExtractSkill(SKILL_R1_L1['typeID'])
    410         with self.assertRaises(NotEnoughExtractedError):
    411             self.controller.Commit()
    412         self.assertFalse(self.controller.isCompleted)
    413 
    414     def test_commit_with_enough_extracted(self):
    415         self.controller._mock_skill_list = [SKILL_R10_L5]
    416         self.preExtract(SKILL_R10_L5)
    417         expected = {SKILL_R10_L5['typeID']: 500000}
    418         self.controller.Commit()
    419         self.assertTrue(self.controller.isCompleted)
    420         self.events.on_update.assert_called_once_with()
    421         self.assertEqual(self.controller._final_itemID, EXTRACTOR_ITEM_ID)
    422         self.assertDictEqual(self.controller._final_extracted_skills, expected)
    423 
    424     def test_commit_with_multiple_levels_of_a_skill(self):
    425         self.controller._mock_skill_list = [SKILL_R1_L5, SKILL_R10_L5]
    426         self.preExtract(SKILL_R1_L5, SKILL_R1_L5, SKILL_R1_L5, SKILL_R1_L5, SKILL_R1_L5, SKILL_R10_L5)
    427         expected = {SKILL_R1_L5['typeID']: 256000,
    428          SKILL_R10_L5['typeID']: 244000}
    429         self.controller.Commit()
    430         self.assertTrue(self.controller.isCompleted)
    431         self.events.on_update.assert_called_once_with()
    432         self.assertEqual(self.controller._final_itemID, EXTRACTOR_ITEM_ID)
    433         self.assertDictEqual(self.controller._final_extracted_skills, expected)
    434 
    435     def test_skills_in_queue_are_set_as_such(self):
    436         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R1_L2]
    437         self.controller._mock_skill_queue = [(SKILL_R1_L1['typeID'], 2)]
    438         self.assertTrue(self.getSkill(SKILL_R1_L1).isQueued)
    439         self.assertFalse(self.getSkill(SKILL_R1_L2).isQueued)
    440 
    441     def test_extract_skill_in_queue(self):
    442         self.controller._mock_skill_list = [SKILL_R1_L1]
    443         self.controller._mock_skill_queue = [(SKILL_R1_L1['typeID'], 2)]
    444         with self.assertRaises(SkillLockedError):
    445             self.controller.ExtractSkill(SKILL_R1_L1['typeID'])
    446 
    447     def test_queue_updated(self):
    448         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R1_L2]
    449         self.assertFalse(self.getSkill(SKILL_R1_L1).isQueued)
    450         self.assertFalse(self.getSkill(SKILL_R1_L2).isQueued)
    451         self.controller._mock_skill_queue = [(SKILL_R1_L1['typeID'], 2)]
    452         self.controller.OnSkillQueueUpdated()
    453         self.assertTrue(self.getSkill(SKILL_R1_L1).isQueued)
    454         self.assertFalse(self.getSkill(SKILL_R1_L2).isQueued)
    455         self.getSkill(SKILL_R1_L1).onUpdateHandler.assert_called_once_with()
    456 
    457     def test_unextracted_skill_added_to_queue(self):
    458         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R1_L2]
    459         self.preExtract(SKILL_R1_L1)
    460         self.controller._mock_skill_queue = [(SKILL_R1_L2['typeID'], 3)]
    461         self.controller.OnSkillQueueUpdated()
    462         self.assertEqual(self.controller.extractedPoints, SKILL_R1_L1['sp'])
    463         self.assertEqual(self.events.on_update.call_count, 0)
    464         self.assertEqual(self.getSkill(SKILL_R1_L1).onUpdateHandler.call_count, 0)
    465         self.getSkill(SKILL_R1_L2).onUpdateHandler.assert_called_once_with()
    466 
    467     def test_extracted_skill_added_to_queue(self):
    468         self.controller._mock_skill_list = [SKILL_R1_L1]
    469         self.preExtract(SKILL_R1_L1)
    470         self.controller._mock_skill_queue = [(SKILL_R1_L1['typeID'], 2)]
    471         self.controller.OnSkillQueueUpdated()
    472         skill = self.getSkill(SKILL_R1_L1)
    473         self.assertEqual(skill.level, SKILL_R1_L1['level'])
    474         self.assertEqual(skill.points, SKILL_R1_L1['sp'])
    475         skill.onUpdateHandler.assert_called_once_with()
    476         self.assertEqual(self.controller.extractedPoints, 0)
    477         self.events.on_update.assert_called_once_with()
    478 
    479     def test_queued_dependent_skill_prevents_requirement_from_being_extracted(self):
    480         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R1_L1_PREREQ_L1]
    481         self.controller._mock_skill_queue = [(SKILL_R1_L1['typeID'], 2)]
    482         with self.assertRaises(SkillLockedError):
    483             self.controller.ExtractSkill(SKILL_R1_L1_PREREQ_L1['typeID'])
    484         self.assertTrue(self.getSkill(SKILL_R1_L1_PREREQ_L1).isRequired)
    485 
    486     def test_untrained_queued_dependent_skill_prevents_requirements_being_extracted(self):
    487         self.controller._mock_skill_list = [SKILL_R1_L0, SKILL_R1_L1_PREREQ_L1]
    488         self.controller._mock_skill_queue = [(SKILL_R1_L0['typeID'], 1)]
    489         with self.assertRaises(SkillLockedError):
    490             self.controller.ExtractSkill(SKILL_R1_L1_PREREQ_L1['typeID'])
    491         self.assertTrue(self.getSkill(SKILL_R1_L1_PREREQ_L1).isRequired)
    492 
    493     def test_dependent_skill_in_queue_removed_from_queue(self):
    494         self.controller._mock_skill_list = [SKILL_R1_L0, SKILL_R1_L1_PREREQ_L1]
    495         self.controller._mock_skill_queue = [(SKILL_R1_L0['typeID'], 1)]
    496         self.controller.skills
    497         self.controller._mock_skill_queue = []
    498         self.controller.OnSkillQueueUpdated()
    499         self.assertFalse(self.getSkill(SKILL_R1_L1_PREREQ_L1).isRequired)
    500         self.getSkill(SKILL_R1_L1_PREREQ_L1).onUpdateHandler.assert_called_once_with()
    501 
    502     def test_dependent_untrained_skill_added_to_queue_resets_requirements(self):
    503         self.controller._mock_skill_list = [SKILL_R1_L0, SKILL_R1_L1_PREREQ_L1]
    504         self.preExtract(SKILL_R1_L1_PREREQ_L1)
    505         self.controller._mock_skill_queue = [(SKILL_R1_L0['typeID'], 1)]
    506         self.controller.OnSkillQueueUpdated()
    507         self.assertEqual(self.getSkill(SKILL_R1_L1_PREREQ_L1).points, SKILL_R1_L1_PREREQ_L1['sp'])
    508         self.getSkill(SKILL_R1_L1_PREREQ_L1).onUpdateHandler.assert_called_once_with()
    509 
    510     def test_dependent_skill_added_to_queue_reverts_chain_of_required_skills(self):
    511         SKILL_A = self.addSkill(points=SP_R1_L1)
    512         SKILL_B = self.addSkill(points=SP_R1_L1, requirements=[(SKILL_A, 1)])
    513         SKILL_C = self.addSkill(points=SP_R1_L1, requirements=[(SKILL_B, 1)])
    514         self.preExtract(SKILL_C, SKILL_B, SKILL_A)
    515         self.controller._mock_skill_queue = [(SKILL_C.typeID, 2)]
    516         self.controller.OnSkillQueueUpdated()
    517         self.assertEqual(self.controller.extractedPoints, 0)
    518         self.assertEqual(SKILL_A.points, SP_R1_L1)
    519         self.assertEqual(SKILL_B.points, SP_R1_L1)
    520         self.assertEqual(SKILL_C.points, SP_R1_L1)
    521         SKILL_A.onUpdateHandler.assert_called_once_with()
    522         SKILL_B.onUpdateHandler.assert_called_once_with()
    523         SKILL_C.onUpdateHandler.assert_called_once_with()
    524 
    525     def test_skill_trained(self):
    526         self.controller._mock_skill_list = [SKILL_R1_L0]
    527         self.controller.OnSkillTrained(SKILL_R1_L0['typeID'], SKILL_R1_L1['sp'])
    528         self.assertEqual(self.getSkill(SKILL_R1_L0).points, SKILL_R1_L1['sp'])
    529         self.assertEqual(self.getSkill(SKILL_R1_L0).level, 1)
    530         self.assertEqual(self.events.on_update.call_count, 0)
    531         self.getSkill(SKILL_R1_L0).onUpdateHandler.assert_called_once_with()
    532 
    533     def test_extracted_skill_trained(self):
    534         self.controller._mock_skill_list = [SKILL_R1_L1]
    535         self.preExtract(SKILL_R1_L1)
    536         self.controller.OnSkillTrained(SKILL_R1_L1['typeID'], SKILL_R1_L2['sp'])
    537         skill = self.getSkill(SKILL_R1_L1)
    538         self.assertEqual(skill.points, SKILL_R1_L2['sp'])
    539         self.assertEqual(skill.unmodifiedPoints, skill.points)
    540         self.assertEqual(self.controller.extractedPoints, 0)
    541         self.events.on_update.assert_called_once_with()
    542         skill.onUpdateHandler.assert_called_once_with()
    543 
    544     def test_extracted_skill_removed(self):
    545         self.controller._mock_skill_list = [SKILL_R1_L1]
    546         self.preExtract(SKILL_R1_L1)
    547         self.controller.OnSkillTrained(SKILL_R1_L1['typeID'], -1)
    548         self.assertEqual(self.controller.extractedPoints, 0)
    549         self.events.on_update.assert_called_once_with()
    550 
    551     def test_unknown_skill_trained(self):
    552         self.controller._mock_skill_list = [SKILL_R1_L1]
    553         self.controller.skills
    554         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R4_L5]
    555         self.controller.OnSkillTrained(SKILL_R4_L5['typeID'], SKILL_R4_L5['sp'])
    556         self.assertSkillListEqual([SKILL_R1_L1, SKILL_R4_L5])
    557         self.events.on_update.assert_called_once_with()
    558         self.events.on_skill_list_update.assert_called_once_with()
    559 
    560     def test_skill_removed(self):
    561         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R4_L5]
    562         self.controller.skills
    563         self.controller._mock_skill_list = [SKILL_R1_L1]
    564         self.controller.OnSkillTrained(SKILL_R4_L5['typeID'], -1)
    565         self.assertSkillListEqual([SKILL_R1_L1])
    566         self.events.on_update.assert_called_once_with()
    567         self.events.on_skill_list_update.assert_called_once_with()
    568 
    569     def test_skill_list_update_with_extracted_skill(self):
    570         self.controller._mock_skill_list = [SKILL_R1_L1]
    571         self.preExtract(SKILL_R1_L1)
    572         self.controller._mock_skill_list = [SKILL_R1_L1, SKILL_R4_L5]
    573         self.controller.OnSkillTrained(SKILL_R4_L5['typeID'], SKILL_R4_L5['sp'])
    574         skill = self.getSkill(SKILL_R1_L1)
    575         self.assertEqual(skill.points, 0)
    576 
    577     def test_restricted_skill_properties(self):
    578         skill_a = self.addSkill(points=SP_R1_L1, restrictedLevel=1)
    579         skill_b = self.addSkill(points=SP_R1_L2, restrictedLevel=1)
    580         self.controller.skills
    581         self.assertTrue(skill_a.isRestricted)
    582         self.assertFalse(skill_b.isRestricted)
    583 
    584     def test_extract_restricted_skill(self):
    585         restricted_skill = self.addSkill(points=SP_R1_L1, restrictedLevel=1)
    586         with self.assertRaises(SkillLockedError):
    587             self.controller.ExtractSkill(restricted_skill.typeID)
    588         self.assertEqual(self.controller.extractedPoints, 0)
    589         self.assertEqual(restricted_skill.points, SP_R1_L1)
    590         self.assertEqual(restricted_skill.onUpdateHandler.call_count, 0)
    591 
    592     def test_extract_restricted_skill_of_higher_level(self):
    593         restricted_skill = self.addSkill(points=SP_R1_L2, restrictedLevel=1)
    594         self.controller.ExtractSkill(restricted_skill.typeID)
    595         with self.assertRaises(SkillLockedError):
    596             self.controller.ExtractSkill(restricted_skill.typeID)
    597         self.assertEqual(self.controller.extractedPoints, SP_R1_L2 - SP_R1_L1)
    598         self.assertEqual(restricted_skill.points, SP_R1_L1)
    599         restricted_skill.onUpdateHandler.assert_called_once_with()
    600 
    601     def test_revert_extracted_restricted_skill(self):
    602         restricted_skill = self.addSkill(points=SP_R1_L2, restrictedLevel=1)
    603         self.preExtract(restricted_skill)
    604         self.controller.Revert(restricted_skill.typeID)
    605         self.assertEqual(self.controller.extractedPoints, 0)
    606         self.assertFalse(restricted_skill.isRestricted)
    607         self.assertEqual(restricted_skill.points, SP_R1_L2)
    608 
    609     def test_on_restrictions_updated_skill_properties_are_updated(self):
    610         skill_a = self.addSkill(points=SP_R1_L1)
    611         skill_b = self.addSkill(points=SP_R1_L1, restrictedLevel=1)
    612         self.controller.skills
    613         self.restrictSkill(skill_a, 1)
    614         self.restrictSkill(skill_b, 0)
    615         self.controller.OnSkillRestrictionsUpdated()
    616         self.assertTrue(skill_a.isRestricted)
    617         self.assertFalse(skill_b.isRestricted)
    618 
    619     def test_on_restrictions_updated_restricted_skills_are_reverted(self):
    620         skill = self.addSkill(points=SP_R1_L1)
    621         self.preExtract(skill)
    622         self.restrictSkill(skill, 1)
    623         self.controller.OnSkillRestrictionsUpdated()
    624         self.assertEqual(self.controller.extractedPoints, 0)
    625         self.assertTrue(skill.isRestricted)
    626         self.assertEqual(skill.points, SP_R1_L1)
    627         skill.onUpdateHandler.assert_called_once_with()
    628         self.events.on_update.assert_called_once_with()
    629 
    630     def test_on_restrictions_updated_restricted_skills_are_reverted_up_to_restricted_level(self):
    631         skill = self.addSkill(points=SP_R1_L2)
    632         self.preExtract(skill, skill)
    633         self.restrictSkill(skill, 1)
    634         self.controller.OnSkillRestrictionsUpdated()
    635         self.assertEqual(self.controller.extractedPoints, SP_R1_L2 - SP_R1_L1)
    636         self.assertTrue(skill.isRestricted)
    637         self.assertEqual(skill.points, SP_R1_L1)
    638         skill.onUpdateHandler.assert_called_once_with()
    639         self.events.on_update.assert_called_once_with()
    640 
    641     def test_on_restrictions_updated_restricted_skills_and_requirements_are_reverted(self):
    642         skill_a = self.addSkill(points=SP_R1_L1)
    643         skill_b = self.addSkill(points=SP_R1_L1, requirements=[(skill_a, 1)])
    644         self.preExtract(skill_b, skill_a)
    645         self.restrictSkill(skill_b, 1)
    646         self.controller.OnSkillRestrictionsUpdated()
    647         self.assertEqual(self.controller.extractedPoints, 0)
    648         self.assertEqual(skill_a.points, SP_R1_L1)
    649         self.assertEqual(skill_b.points, SP_R1_L1)
    650         self.assertTrue(skill_a.isRequired)
    651         self.assertTrue(skill_b.isRestricted)
    652         skill_a.onUpdateHandler.assert_called_once_with()
    653         skill_b.onUpdateHandler.assert_called_once_with()
    654         self.events.on_update.assert_called_once_with()
    655 
    656     def test_extracted_restricted_skill_added_to_queue(self):
    657         skill = self.addSkill(points=SP_R1_L2, restrictedLevel=1)
    658         self.preExtract(skill)
    659         self.controller._mock_skill_queue = [(skill.typeID, 3)]
    660         self.controller.OnSkillQueueUpdated()
    661         self.assertEqual(self.controller.extractedPoints, 0)
    662         self.assertEqual(skill.points, SP_R1_L2)
    663         self.assertTrue(skill.isQueued)
    664         self.assertFalse(skill.isRestricted)
    665         skill.onUpdateHandler.assert_called_once_with()
    666         self.events.on_update.assert_called_once_with()
    667 
    668     def test_restricted_skill_trained(self):
    669         skill = self.addSkill(points=SP_R1_L1, restrictedLevel=1)
    670         self.controller.skills
    671         updated_skill = self.addSkill(typeID=skill.typeID, points=SP_R1_L2)
    672         self.controller.OnSkillTrained(skill.typeID, SP_R1_L2)
    673         self.assertFalse(updated_skill.isRestricted)
    674 
    675     def test_restricted_skill_has_reason(self):
    676         skill = self.addSkill(restrictedLevel=1, restrictionReason=RESTRICTION_IMPLANT)
    677         self.controller.skills
    678         self.assertEqual(skill.restrictionReason, RESTRICTION_IMPLANT)
    679 
    680     def test_over_trained_skills_are_restricted(self):
    681         skill = self.addSkill(points=10000000, restrictedLevel=5)
    682         self.controller.skills
    683         self.assertTrue(skill.isRestricted)
    684 
    685     def assertSkillListEqual(self, expected):
    686         skills = self.controller.skills
    687         sorted_skills = sorted(skills, key=lambda s: s.typeID)
    688         sorted_expected = sorted(expected, key=lambda e: e['typeID'])
    689         self.assertEqual(len(skills), len(expected))
    690         for skill, expected_skill in izip(sorted_skills, sorted_expected):
    691             self.assertEqual(skill.typeID, expected_skill['typeID'])
    692             self.assertEqual(skill.points, expected_skill['sp'])
    693             self.assertEqual(skill.level, expected_skill['level'])
    694             self.assertEqual(skill.rank, expected_skill['rank'])
    695 
    696     def addSkill(self, typeID = None, points = SP_R1_L1, rank = 1.0, requirements = None, restrictedLevel = None, restrictionReason = None):
    697         if typeID is None:
    698             typeID = self._next_skill_id
    699             self._next_skill_id += 1
    700         skill = SkillFixture(typeID=typeID, points=points, rank=rank)
    701         self.controller._mock_skill_list = filter(lambda s: s.typeID != typeID, self.controller._mock_skill_list)
    702         self.controller._mock_skill_list.append(skill)
    703         requirements = requirements or []
    704         for requiredSkill, requiredLevel in requirements:
    705             skill._requirements[requiredSkill.typeID] = requiredLevel
    706             requiredSkill._dependencies[skill.typeID] = requiredLevel
    707 
    708         if restrictedLevel is not None:
    709             self.restrictSkill(skill, restrictedLevel, restrictionReason)
    710         return skill
    711 
    712     def restrictSkill(self, skill, level, reason = None):
    713         if level == 0:
    714             del self.controller._mock_skill_restrictions[skill.typeID]
    715         else:
    716             if reason is None:
    717                 reason = RESTRICTION_CLONE_STATE
    718             restriction = SkillRestriction(level, reason)
    719             self.controller._mock_skill_restrictions[skill.typeID] = restriction
    720 
    721     def getSkill(self, target):
    722         skills = self.controller.skills
    723         for skill in skills:
    724             if skill.typeID == target['typeID']:
    725                 return skill
    726 
    727         self.fail('Skill with ID %s not found in the controller' % target['typeID'])
    728 
    729     def preExtract(self, *skills):
    730         for skill in skills:
    731             try:
    732                 typeID = skill.typeID
    733             except AttributeError:
    734                 typeID = skill['typeID']
    735 
    736             self.controller.ExtractSkill(typeID)
    737 
    738         for skill in self.controller.skills:
    739             skill.onUpdateHandler.reset_mock()
    740 
    741         self.events.on_update.reset_mock()
    742 
    743 
    744 def __SakeReloadHook():
    745     try:
    746         import sys
    747         suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
    748         unittest.TextTestRunner(stream=sys.stdout, verbosity=1).run(suite)
    749     except:
    750         import log
    751         log.LogException()