Package Peach :: Package Mutators :: Module number
[hide private]

Source Code for Module Peach.Mutators.number

  1   
  2  ''' 
  3  Mutators that operate on numerical types. 
  4   
  5  @author: Michael Eddington 
  6  @version: $Id$ 
  7  ''' 
  8   
  9  # 
 10  # Copyright (c) 2008 Michael Eddington 
 11  # 
 12  # Permission is hereby granted, free of charge, to any person obtaining a copy  
 13  # of this software and associated documentation files (the "Software"), to deal 
 14  # in the Software without restriction, including without limitation the rights  
 15  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
 16  # copies of the Software, and to permit persons to whom the Software is  
 17  # furnished to do so, subject to the following conditions: 
 18  # 
 19  # The above copyright notice and this permission notice shall be included in     
 20  # all copies or substantial portions of the Software. 
 21  # 
 22  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
 23  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 24  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
 25  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 26  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 27  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 28  # SOFTWARE. 
 29  # 
 30   
 31  # Authors: 
 32  #   Michael Eddington (mike@phed.org) 
 33   
 34  # $Id$ 
 35   
 36  import sys, os, time, random 
 37  from Peach.Generators.block import * 
 38  from Peach.Generators.data import * 
 39  from Peach.Generators.dictionary import * 
 40  from Peach.Generators.flipper import * 
 41  from Peach.Generators.static import Static, _StaticFromTemplate, _StaticCurrentValueFromDom 
 42  from Peach.Transformers.encode import WideChar 
 43  from Peach import Transformers 
 44  from Peach.Generators.block import * 
 45  from Peach.Generators.data import * 
 46  from Peach.Generators.dictionary import * 
 47  from Peach.Generators.flipper import * 
 48  from Peach.Generators.static import Static, _StaticFromTemplate 
 49  from Peach.Transformers.encode import WideChar 
 50  from Peach.mutator import * 
 51  from Peach.group import * 
 52  from Peach.Engine.common import * 
 53   
54 -class NumericalVarianceMutator(Mutator):
55 ''' 56 Produce numbers that are defaultValue - N to defaultValue + N. 57 ''' 58
59 - def __init__(self, peach):
60 Mutator.__init__(self) 61 62 self.name = "NumericalVarianceMutator" 63 self._peach = peach 64 65 self._stateMasterCount = -1 66 self._masterGroup = GroupSequence() 67 self._masterCount = 0 68 self._countThread = None 69 self._countGroup = GroupSequence() 70 self._actions = [] 71 self._N = 50 72 self._origN = 50 73 74 # All active groups 75 self._activeGroups = [] 76 77 # Hashtable, key is element, value is [group, generator] 78 self._generatorMap = {} 79 self._countGeneratorMap = {}
80
81 - def isFinite(self):
82 ''' 83 Some mutators could contine forever, this 84 should indicate. 85 ''' 86 return True
87
88 - def reset(self):
89 ''' 90 Reset mutator 91 ''' 92 93 self._masterGroup = GroupSequence() 94 self._activeGroups = [] 95 self._generatorMap = {} 96 self._masterCount = 0 97 self._actions = []
98
99 - def next(self):
100 ''' 101 Goto next mutation. When this is called 102 the state machine is updated as needed. 103 ''' 104 105 try: 106 # Check if we set our state and need 107 # to skip ahead. We need todo this in 108 # next() to assure we have all our action 109 # templates added into our masterGroup 110 if self._stateMasterCount > -1: 111 for cnt in xrange(self._masterCount, self._stateMasterCount): 112 self._masterGroup.next() 113 self._masterCount += 1 114 self._stateMasterCount = -1 115 else: 116 self._masterGroup.next() 117 self._masterCount += 1 118 119 except GroupCompleted: 120 raise MutatorCompleted()
121
122 - def getState(self):
123 ''' 124 Return a binary string that contains 125 any information about current state of 126 Mutator. This state information should be 127 enough to let the same mutator "restart" 128 and continue when setState() is called. 129 ''' 130 131 # Ensure a minor overlap of testing 132 return str(self._masterCount - 2)
133
134 - def setState(self, state):
135 ''' 136 Set the state of this object. Should put us 137 back in the same place as when we said 138 "getState()". 139 ''' 140 self._stateMasterCount = int(state) 141 try: 142 self.next() 143 except: 144 pass
145
146 - def getCount(self):
147 if self._countThread != None and self._countThread.hasCountEvent.isSet(): 148 self._count = self._countThread.count 149 self._countThread = None 150 self._countGroup = None 151 self._countGeneratorMap = None 152 153 return self._count
154
155 - def calculateCount(self):
156 157 count = 0 158 try: 159 while True: 160 count += 1 161 self._countGroup.next() 162 163 except GroupCompleted: 164 pass 165 166 return count
167
168 - def _getNumberElements(self, node):
169 170 elements = [] 171 172 for e in node._children: 173 if e.elementType == 'number' and not e.isStatic: 174 elements.append(e) 175 176 if e.hasChildren: 177 for ee in self._getNumberElements(e): 178 elements.append(ee) 179 180 return elements
181
182 - def _getN(self, node):
183 ''' 184 Gets N by checking node for hint, or returnign default 185 ''' 186 187 n = self._origN 188 189 for c in node._children: 190 if isinstance(c, Hint) and c.name == 'NumericalVarianceMutator-N': 191 try: 192 n = int(c.value) 193 except: 194 raise PeachException("Expected numerical value for Hint named [%s]" % c.name) 195 196 return n
197 198 ##################################################### 199 # Callbacks when Action needs a value 200
201 - def getActionValue(self, action):
202 203 if action not in self._actions: 204 205 self._generatorMap[action] = {} 206 self._countGeneratorMap[action] = {} 207 208 # Walk data tree and locate each string type. 209 numberElements = self._getNumberElements(action.template) 210 211 for e in numberElements: 212 group = Group() 213 214 value = e.getInternalValue() 215 216 if value == None: 217 value = 0 218 219 n = self._getN(e) 220 221 gen = NumberVariance(None, long(value), n) 222 gen = WithDefault(group, _StaticFromTemplate(action, e), gen) 223 self._masterGroup.append(group) 224 self._generatorMap[action][e.getFullnameInDataModel()] = gen 225 226 group = Group() 227 gen = NumberVariance(None, long(value), n) 228 gen = WithDefault(group, _StaticFromTemplate(action, e), gen) 229 self._countGroup.append(group) 230 self._countGeneratorMap[action][e.getFullnameInDataModel()] = gen 231 232 self._actions.append(action) 233 234 # Set values 235 for name in self._generatorMap[action].keys(): 236 self._getElementByName(action.template, name).setValue(self._generatorMap[action][name].getValue()) 237 238 return action.template.getValue()
239
240 - def getActionParamValue(self, action):
241 return self.getActionValue(action)
242
243 - def getActionChangeStateValue(self, action, value):
244 return value
245 246 247 ##################################################### 248 # Event callbacks for state machine 249
250 - def onStateMachineComplete(self, stateMachine):
251 252 # Lets calc our count if we haven't already 253 if self._count == -1 and self._countThread == None: 254 self._countThread = MutatorCountCalculator(self) 255 self._countThread.start() 256 257 elif self._countThread != None: 258 if self._countThread.hasCountEvent.isSet(): 259 self._count = self._countThread.count 260 self._countThread = None 261 self._countGroup = None 262 self._countGeneratorMap = None
263 264
265 -class NumericalEdgeCaseMutator(Mutator):
266 ''' 267 This is a straight up generation class. Produces values 268 that have nothing todo with defaultValue :) 269 ''' 270
271 - def __init__(self, peach):
272 Mutator.__init__(self) 273 274 self.name = "NumericalEdgeCaseMutator" 275 self._peach = peach 276 277 self._stateMasterCount = -1 278 self._masterGroup = GroupSequence() 279 self._masterCount = 0 280 self._countThread = None 281 self._countGroup = GroupSequence() 282 self._actions = [] 283 self._origN = 50 284 285 # All active groups 286 self._activeGroups = [] 287 288 # Hashtable, key is element, value is [group, generator] 289 self._generatorMap = {} 290 self._countGeneratorMap = {}
291
292 - def isFinite(self):
293 ''' 294 Some mutators could contine forever, this 295 should indicate. 296 ''' 297 return True
298
299 - def reset(self):
300 ''' 301 Reset mutator 302 ''' 303 304 self._masterGroup = GroupSequence() 305 self._activeGroups = [] 306 self._generatorMap = {} 307 self._masterCount = 0 308 self._actions = []
309
310 - def next(self):
311 ''' 312 Goto next mutation. When this is called 313 the state machine is updated as needed. 314 ''' 315 316 try: 317 # Check if we set our state and need 318 # to skip ahead. We need todo this in 319 # next() to assure we have all our action 320 # templates added into our masterGroup 321 if self._stateMasterCount > -1: 322 for cnt in xrange(self._masterCount, self._stateMasterCount): 323 self._masterGroup.next() 324 self._masterCount += 1 325 self._stateMasterCount = -1 326 else: 327 self._masterGroup.next() 328 self._masterCount += 1 329 330 except GroupCompleted: 331 raise MutatorCompleted()
332
333 - def getState(self):
334 ''' 335 Return a binary string that contains 336 any information about current state of 337 Mutator. This state information should be 338 enough to let the same mutator "restart" 339 and continue when setState() is called. 340 ''' 341 342 # Ensure a minor overlap of testing 343 return str(self._masterCount - 2)
344
345 - def setState(self, state):
346 ''' 347 Set the state of this object. Should put us 348 back in the same place as when we said 349 "getState()". 350 ''' 351 352 self._stateMasterCount = int(state) 353 try: 354 self.next() 355 except: 356 pass
357
358 - def getCount(self):
359 if self._countThread != None and self._countThread.hasCountEvent.isSet(): 360 self._count = self._countThread.count 361 self._countThread = None 362 self._countGroup = None 363 self._countGeneratorMap = None 364 365 return self._count
366
367 - def calculateCount(self):
368 369 count = 0 370 try: 371 while True: 372 count += 1 373 self._countGroup.next() 374 375 except GroupCompleted: 376 pass 377 378 return count
379
380 - def _getNumberElements(self, node):
381 382 elements = [] 383 384 for e in node._children: 385 if e.elementType == 'number' and not e.isStatic: 386 elements.append(e) 387 388 if e.hasChildren: 389 for ee in self._getNumberElements(e): 390 elements.append(ee) 391 392 return elements
393
394 - def _getN(self, node):
395 ''' 396 Gets N by checking node for hint, or returnign default 397 ''' 398 399 n = self._origN 400 401 for c in node._children: 402 if isinstance(c, Hint) and c.name == 'NumericalEdgeCaseMutator-N': 403 try: 404 n = int(c.value) 405 except: 406 raise PeachException("Expected numerical value for Hint named [%s]" % c.name) 407 408 return n
409 410 ##################################################### 411 # Callbacks when Action needs a value 412
413 - def getActionValue(self, action):
414 415 if action not in self._actions: 416 417 self._generatorMap[action] = {} 418 self._countGeneratorMap[action] = {} 419 420 # Walk data tree and locate each string type. 421 numberElements = self._getNumberElements(action.template) 422 423 for e in numberElements: 424 group = Group() 425 426 n = self._getN(e) 427 428 if e.size == 8: 429 gen = BadNumbers8() 430 elif e.size == 16: 431 gen = BadNumbers16(None, n) 432 elif e.size == 24: 433 gen = BadNumbers24(None, n) 434 elif e.size == 32: 435 gen = BadNumbers32(None, n) 436 else: 437 gen = BadNumbers(None, n) 438 439 gen = WithDefault(group, _StaticFromTemplate(action, e), gen) 440 441 self._masterGroup.append(group) 442 self._generatorMap[action][e.getFullnameInDataModel()] = gen 443 444 group = Group() 445 446 if e.size == 8: 447 gen = BadNumbers8() 448 elif e.size == 16: 449 gen = BadNumbers16(None, n) 450 elif e.size == 24: 451 gen = BadNumbers24(None, n) 452 elif e.size == 32: 453 gen = BadNumbers32(None, n) 454 else: 455 gen = BadNumbers(None, n) 456 457 gen = WithDefault(group, _StaticFromTemplate(action, e), gen) 458 459 self._countGroup.append(group) 460 self._countGeneratorMap[action][e.getFullnameInDataModel()] = gen 461 462 self._actions.append(action) 463 464 # Set values 465 for key in self._generatorMap[action].keys(): 466 try: 467 self._getElementByName(action.template, key).setValue(self._generatorMap[action][key].getValue()) 468 except: 469 print "Caught exception on _getElementByName looking for [%s]" % key 470 raise 471 472 return action.template.getValue()
473
474 - def getActionParamValue(self, action):
475 return self.getActionValue(action)
476
477 - def getActionChangeStateValue(self, action, value):
478 return value
479 480 481 ##################################################### 482 # Event callbacks for state machine 483
484 - def onStateStart(self, state):
485 pass
486
487 - def onStateComplete(self, state):
488 pass
489
490 - def onActionStart(self, action):
491 pass
492
493 - def onActionComplete(self, action):
494 pass
495
496 - def onStateMachineStart(self, stateMachine):
497 pass
498
499 - def onStateMachineComplete(self, stateMachine):
500 501 # Lets calc our count if we haven't already 502 if self._count == -1 and self._countThread == None: 503 self._countThread = MutatorCountCalculator(self) 504 self._countThread.start() 505 506 elif self._countThread != None: 507 if self._countThread.hasCountEvent.isSet(): 508 self._count = self._countThread.count 509 self._countThread = None 510 self._countGroup = None 511 self._countGeneratorMap = None
512 513
514 -class FiniteRandomNumbersMutator(Mutator):
515 ''' 516 Produce a finite number of random numbers for 517 each <Number> element. 518 ''' 519
520 - def __init__(self, peach):
521 Mutator.__init__(self) 522 523 self.name = "FiniteRandomNumbersMutator" 524 self._peach = peach 525 self._countThread = None 526 527 self._random = random.Random() 528 self._random.seed(12345) 529 530 self._stateActionPos = -1 531 self._statePos = -1 532 self._masterCount = 0 533 534 self._origN = 5000 535 self._maxCount = 5000 536 self._pos = 0 537 self._actionPos = 0 538 539 self._actions = [] 540 # key = action, value = array(numbername, cnt,min,max) 541 self._map = {} 542 self._value = 0 543 544 self._masterCount = 0 545 self._stateMasterCount = -1
546
547 - def isFinite(self):
548 ''' 549 Some mutators could contine forever, this 550 should indicate. 551 ''' 552 return True
553
554 - def reset(self):
555 ''' 556 Reset mutator 557 ''' 558 559 self._random = random.Random() 560 self._random.seed(12345) 561 self._countThread = None 562 563 self._stateActionPos = -1 564 self._statePos = -1 565 self._masterCount = 0 566 567 self._origN = 5000 568 self._maxCount = 5000 569 self._pos = 0 570 self._actionPos = 0 571 572 self._actions = [] 573 # key = action, value = array(numbername, cnt,min,max) 574 self._map = {} 575 self._value = 0
576
577 - def next(self):
578 ''' 579 Goto next mutation. When this is called 580 the state machine is updated as needed. 581 ''' 582 583 # Check if we set our state and need 584 # to skip ahead. We need todo this in 585 # next() to assure we have all our action 586 # templates added into our masterGroup 587 if self._stateActionPos > -1: 588 while self._actionPos < self._stateActionPos: 589 self.realNext() 590 591 while self._pos < self._statePos: 592 self.realNext() 593 594 self._stateActionPos = -1 595 self._statePos = -1 596 597 else: 598 self.realNext() 599 600 self._masterCount += 1
601
602 - def realNext(self):
603 604 if len(self._map[self._actions[self._actionPos]]) > 0: 605 (name, cnt, min, max, self._maxCount) = self._map[self._actions[self._actionPos]][self._pos] 606 cnt += 1 607 self._map[self._actions[self._actionPos]][self._pos][1] = cnt 608 609 else: 610 # Trigger next 611 cnt = self._maxCount + 1 612 613 if cnt > self._maxCount: 614 try: 615 self._map[self._actions[self._actionPos]][self._pos][1] = 0 616 except: 617 pass 618 619 self._pos += 1 620 621 if self._pos >= len(self._map[self._actions[self._actionPos]]): 622 self._pos = 0 623 self._actionPos += 1 624 625 if self._actionPos >= len(self._actions): 626 self._actionPos -= 1 627 raise MutatorCompleted() 628 629 # Only generate the value once. So even if our .getValue() was called 20 630 # times per round we always do the correct thing. 631 if len(self._map[self._actions[self._actionPos]]) > 0: 632 (name, cnt, min, max, self._maxCount) = self._map[self._actions[self._actionPos]][self._pos] 633 self._value = self._random.randint(min, max) 634 else: 635 self._value = 0
636
637 - def getState(self):
638 ''' 639 Return a binary string that contains 640 any information about current state of 641 Mutator. This state information should be 642 enough to let the same mutator "restart" 643 and continue when setState() is called. 644 ''' 645 646 return str(self._masterCount)
647
648 - def setState(self, state):
649 ''' 650 Set the state of this object. Should put us 651 back in the same place as when we said 652 "getState()". 653 ''' 654 655 self._stateMasterCount = int(self._masterCount) 656 try: 657 for i in xrange(self._masterCount, self._stateMasterCont): 658 self.next() 659 660 self._stateMasterCount = -1 661 except: 662 pass
663
664 - def getCount(self):
665 if self._countThread != None and self._countThread.hasCountEvent.isSet(): 666 self._count = self._countThread.count 667 self._countThread = None 668 self._countGroup = None 669 self._countGeneratorMap = None 670 671 return self._count
672
673 - def calculateCount(self):
674 675 count = 0 676 for action in self._actions: 677 for obj in self._map[action]: 678 count += obj[4] 679 680 return count
681
682 - def _getNumberElements(self, node):
683 684 elements = [] 685 686 for e in node._children: 687 if e.elementType == 'number' and not e.isStatic and e.size > 8: 688 elements.append(e) 689 690 if e.hasChildren: 691 for ee in self._getNumberElements(e): 692 elements.append(ee) 693 694 return elements
695
696 - def _getN(self, node):
697 ''' 698 Gets N by checking node for hint, or returnign default 699 ''' 700 701 n = self._origN 702 703 for c in node._children: 704 if isinstance(c, Hint) and c.name == 'FiniteRandomNumbersMutator-N': 705 try: 706 n = int(c.value) 707 except: 708 raise PeachException("Expected numerical value for Hint named [%s]" % c.name) 709 710 return n
711 712 ##################################################### 713 # Callbacks when Action needs a value 714
715 - def getActionValue(self, action):
716 717 if action not in self._actions: 718 719 # Walk data tree and locate each string type. 720 numberElements = self._getNumberElements(action.template) 721 722 self._map[action] = [] 723 for e in numberElements: 724 self._map[action].append([ 725 e.getFullnameInDataModel(), 726 0, 727 e.getMinValue(), 728 e.getMaxValue(), 729 self._getN(e) 730 ]) 731 732 self._actions.append(action) 733 734 # Set values 735 if self._actions[self._actionPos] == action and len(self._map[action]) > 0: 736 (name, cnt, min, max, maxCount) = self._map[action][self._pos] 737 action.template.findDataElementByName(name).setValue(self._value) 738 739 # return value 740 return action.template.getValue()
741
742 - def getActionParamValue(self, action):
743 return self.getActionValue(action)
744
745 - def getActionChangeStateValue(self, action, value):
746 return value
747 748 749 ##################################################### 750 # Event callbacks for state machine 751
752 - def onStateMachineComplete(self, stateMachine):
753 754 # Lets calc our count if we haven't already 755 if self._count == -1 and self._countThread == None: 756 self._countThread = MutatorCountCalculator(self) 757 self._countThread.start() 758 759 elif self._countThread != None: 760 if self._countThread.hasCountEvent.isSet(): 761 self._count = self._countThread.count 762 self._countThread = None 763 self._countGroup = None 764 self._countGeneratorMap = None
765 766 767 # end 768