def test_determine_writer_trust_later(self): x = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: JeevesLib.jhas(octxt, ictxt)) x.update(self.aliceUser, self.aliceUser, 42) self.assertEqual(JeevesLib.concretize([self.aliceUser], x.v), 42) self.assertEqual(JeevesLib.concretize([], x.v), 0)
def test_prevent_untrusted_writes_through_implicit_flows(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser)) x.update(self.aliceUser, self.aliceUser, 42) y = ProtectedRef(1, None, self.allowUserWrite(self.bobUser)) y.update(self.bobUser, self.bobUser, 2 if x.v == 42 else 3) self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 3) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 3)
def test_permitted_writer_overwrite(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) assert x.update(self.aliceUser, self.aliceUser, 42) == UpdateResult.Unknown assert x.update(self.bobUser, self.bobUser, 43) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 43) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 43) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 43)
def test_determine_writer_trust_later(self): x = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda octxt: JeevesLib.jhas( octxt, ictxt)) x.update(self.aliceUser, self.aliceUser, 42) self.assertEqual(JeevesLib.concretize([self.aliceUser], x.v), 42) self.assertEqual(JeevesLib.concretize([], x.v), 0)
def test_not_tracking_implicit_flows(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser), False) x.update(self.aliceUser, self.aliceUser, 42) y = ProtectedRef(1, None, self.allowUserWrite(self.bobUser), False) y.update(self.bobUser, self.bobUser, 2 if x.v == 42 else 3) self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 2) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 2)
def test_output_write_policies_involving_this_can_update(self): x = ProtectedRef(0, None , lambda v: lambda ictxt: lambda _: v == 0 and ictxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 1) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 1) x.update(self.aliceUser, self.aliceUser, 3) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 1)
def test_output_varies_depending_on_viewer(self): x = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser and octxt == self.bobUser) x.update(self.aliceUser, self.aliceUser, 42) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 0) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 0)
def test_output_varies_depending_on_viewer(self): x = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.bobUser) x.update(self.aliceUser, self.aliceUser, 42) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 0) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 0)
def test_prevent_flow_of_untrusted_writes(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser)) assert x.update(self.aliceUser, self.aliceUser, 42) == UpdateResult.Unknown y = ProtectedRef(1, None, self.allowUserWrite(self.bobUser)) assert y.update(self.bobUser, self.bobUser, x.v) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 0) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 0)
def test_function_facets_cannot_write(self): def id(x): return x def inc(x): return x+1 x = ProtectedRef(id, None, self.allowUserWrite(self.bobUser)) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v)(1), 1) x.update(self.aliceUser, self.aliceUser, inc) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v)(1), 1)
def test_combining_write_policies_in_operation(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) y = ProtectedRef(2, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.bobUser) y.update(self.aliceUser, self.aliceUser, 43) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v + y.v), 44) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v + y.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v + y.v), 44)
def test_combining_write_policies_in_operation(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) y = ProtectedRef( 2, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser and octxt == self.bobUser) y.update(self.aliceUser, self.aliceUser, 43) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v + y.v), 44) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v + y.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v + y.v), 44)
def test_output_write_policies_involving_this_can_update(self): x = ProtectedRef(0, None , lambda v: lambda ictxt: lambda _: v == 0 and ictxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 1) print x.v.prettyPrint() self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 1) x.update(self.aliceUser, self.aliceUser, 3) print x.v.prettyPrint() self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 1)
def test_prevent_implicit_flows_of_confidential_values(self): x = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 42) y = ProtectedRef(1, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.bobUser or ictxt == self.aliceUser) y.update(self.bobUser, self.bobUser, 2 if x.v == 42 else 3) self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 2) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 3)
def test_prevent_implicit_flows_of_confidential_values(self): # Alice may write to x. Only Alice may see the updates. x = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser and octxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 42) # Alice and Bob may both write to y. y = ProtectedRef( 1, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. bobUser or ictxt == self.aliceUser) y.update(self.bobUser, self.bobUser, 2 if x.v == 42 else 3) # self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 2) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 3)
def test_prevent_implicit_flows_of_confidential_values(self): # Alice may write to x. Only Alice may see the updates. x = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 42) # Alice and Bob may both write to y. y = ProtectedRef(1, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.bobUser or ictxt == self.aliceUser) y.update(self.bobUser, self.bobUser, 2 if x.v == 42 else 3) # self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 2) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 3)
def test_write_allowed_for_all_viewers(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser)) assert x.update(self.aliceUser, self.aliceUser, 42) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 42)
def test_write_selectively_allowed(self): x = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.bobUser) assert x.update(self.aliceUser, self.aliceUser, 42) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 0) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 0)
class Square: @jeeves def __init__(self, owner): self.owner = owner self.shipRef = ProtectedRef(NoShip() # Policy for updating: must be owner and there can't be a ship there # already. , lambda ship: lambda ic: ship == NoShip() , lambda ship: lambda ic: lambda _oc: self.isOwner(ic)) self.hasBombRef = ProtectedRef(None , lambda _bomb: lambda ic: True , lambda _bomb: lambda ic: lambda _oc: self.hasTurn(ic) and self.allShipsPlaced(ic) and (not self.gameOver(ic))) def isOwner(self, ctxt): return ctxt.user == self.owner # TODO: Make sure function applications get applied correctly here. # Do we need another @jeeves annotation? def hasTurn(self, ctxt): return ctxt.game.hasTurn(ctxt.user) def allShipsPlaced(self, ctxt): return ctxt.game.allShipsPlaced() def gameOver(self, ctxt): return ctxt.game.gameOver() @jeeves def mkShipSecret(self, ship): a = JeevesLib.mkLabel("ship") JeevesLib.restrict(a , lambda ctxt: self.hasBomb() or self.isOwner(ctxt) or self.gameOver(ctxt)); return JeevesLib.mkSensitive(a, ship, NoShip()) # Returns whether updating a square's ship reference succeeded. def updateShip(self, ctxt, ship): return self.shipRef.update(ctxt, ctxt, self.mkShipSecret(ship)) == UpdateResult.Success def hasShip(self): return not self.shipRef.v == NoShip() def getShip(self): return self.shipRef.v def bomb(self, ctxt, bomb): return self.hasBombRef.update(ctxt, ctxt, bomb) == UpdateResult.Success def hasBomb(self): return not (self.hasBombRef.v == None)
def testBehavioralGood(self): touchedBadData = False def f(x): return x+1 x = ProtectedRef(lambda x: x, None , lambda _this: lambda ic: lambda touchedBad: not touchedBad) self.assertEqual(JeevesLib.concretize(None, (x.v)(1)), 1) assert x.update(None, None, f) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(None, (x.v)(1)), 2)
class Protein: # TODO: Figure out what kinds of policies should go here... def __init__(self, name, initValue=0): self.name = name self._vRef = ProtectedRef(initValue # We also support policies where the write checks get concretized right # away in the context of the user. , None # Flow is only permitted if there is an edge. # The policy takes the current value (v), the input channel (ic), and # the output channel. , lambda v: lambda ic: lambda oc: JeevesLib.jhasElt(self.edges, lambda edge: edge.v == oc)) self._edges = [] def addEdge(self, node, edgeType): self._edges.append(Edge(node, edgeType)) def updateValue(self, ictxt, f): self._vRef.update(ictxt, ictxt, f(self._vRef.v))
class Square: def __init__(self, owner): self.owner = owner self.shipRef = ProtectedRef(NoShip() # Policy for updating: must be owner and there can't be a ship there # already. , lambda ship: lambda ic: ship == NoShip() and self.isOwner(ic) , None) self.hasBombRef = ProtectedRef(None , lambda _bomb: lambda ic: self.hasTurn(ic) and self.allShipsPlaced(ic) and not self.gameOver(ic) , None) def isOwner(self, ctxt): return ctxt.user == self.owner def hasTurn(self, ctxt): return ctxt.game.hasTurn(ctxt.user) def allShipsPlaced(self, ctxt): return ctxt.game.allShipsPlaced() def gameOver(self, ctxt): return ctxt.game.gameOver() def mkShipSecret(self, ship): a = JeevesLib.mkLabel("ship") JeevesLib.restrict(a , lambda ctxt: self.hasBomb() or self.isOwner(ctxt) or self.gameOver(ctxt)); return JeevesLib.mkSensitive(a, ship, NoShip()) # Returns whether updating a square's ship reference succeeded. def updateShip(self, ctxt, ship): return self.shipRef.update(ctxt, ctxt, self.mkShipSecret(ship)) == UpdateResult.Success def hasShip(self): return not self.shipRef.v == NoShip() def getShip(self): return self.shipRef.v def bomb(self, ctxt, bomb): r = self.hasBombRef.update(ctxt, ctxt, bomb) print 'moooooooooo', r return r == UpdateResult.Success def hasBomb(self): return not (self.hasBombRef.v == None)
def test_write_policies_with_confidentiality(self): # Make a sensitive value that is either Bob or the nobody user. Only Bob # can see this. a = JeevesLib.mkLabel () JeevesLib.restrict(a, lambda ctxt: ctxt == self.bobUser) secretWriter = JeevesLib.mkSensitive(a, self.bobUser, self.nobodyUser) # We now make a protected reference where the input channel has to be the # secret writer. x = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == secretWriter) x.update(self.bobUser, self.bobUser, 42) self.assertEqual(JeevesLib.concretize(self.bobUser, secretWriter) , self.bobUser) self.assertEqual(JeevesLib.concretize(self.aliceUser, secretWriter) , self.nobodyUser) self.assertEqual(JeevesLib.concretize(self.aliceUser, secretWriter) , self.nobodyUser) # Only Bob should be able to see the value he wrote. self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 0) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 0)
def testBehavioralSanitizationBad(self): touchedBadData = False def f(s): global touchedBadData if s == "bad": touchedBadData = True return s x = ProtectedRef("dunno", None , lambda _this: lambda ic: lambda oc: not touchedBadData) assert x.update(None, None, f("bad")) == UpdateResult.Unknown print touchedBadData self.assertEqual(JeevesLib.concretize(None, x.v), "dunno")
def test_input_write_policies_with_confidentiality(self): # Make a sensitive value that is either Bob or the nobody user. Only Bob # can see this. a = JeevesLib.mkLabel() JeevesLib.restrict(a, lambda ctxt: ctxt == self.bobUser) secretWriter = JeevesLib.mkSensitive(a, self.bobUser, self.nobodyUser) # We now make a protected reference where the input channel has to be the # secret writer. x = ProtectedRef(0, lambda _this: lambda ictxt: ictxt == secretWriter, None) x.update(self.bobUser, self.bobUser, 42) self.assertEqual(JeevesLib.concretize(self.bobUser, secretWriter), self.bobUser) self.assertEqual(JeevesLib.concretize(self.aliceUser, secretWriter), self.nobodyUser) self.assertEqual(JeevesLib.concretize(self.aliceUser, secretWriter), self.nobodyUser) # Only Bob should be able to see the value he wrote. self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 42)
class Protein: # TODO: Figure out what kinds of policies should go here... def __init__(self, name, initValue=0): self.name = name self._vRef = ProtectedRef( initValue # We also support policies where the write checks get concretized right # away in the context of the user. , None # Flow is only permitted if there is an edge. # The policy takes the current value (v), the input channel (ic), and # the output channel. , lambda v: lambda ic: lambda oc: JeevesLib.jhasElt( self.edges, lambda edge: edge.v == oc)) self._edges = [] def addEdge(self, node, edgeType): self._edges.append(Edge(node, edgeType)) def updateValue(self, ictxt, f): self._vRef.update(ictxt, ictxt, f(self._vRef.v))
def test_output_write_policy_with_this_cannot_update(self): x = ProtectedRef(0, None , lambda v: lambda ictxt: lambda _octxt: (not (v == 3)) and ictxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 1) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 1) x.update(self.aliceUser, self.aliceUser, 3) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 3) x.update(self.aliceUser, self.aliceUser, 5) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 3)
def test_prevent_flow_of_operations_on_untrusted_writes(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser)) x.update(self.aliceUser, self.aliceUser, 42) y = ProtectedRef(1, None, self.allowUserWrite(self.bobUser)) y.update(self.bobUser, self.bobUser, 43) z = ProtectedRef(0, None, self.allowUserWrite(self.carolUser)) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 1) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 1) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 1)
def test_combining_values_into_permissive_write(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) y = ProtectedRef(1, None, self.allowUserWrite(self.aliceUser)) y.update(self.aliceUser, self.aliceUser, 43) z = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda otxt: ictxt == self. aliceUser or ictxt == self.bobUser or ictxt == self.carolUser) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 85)
def test_combining_values_into_permissive_write(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) y = ProtectedRef(1, None, self.allowUserWrite(self.aliceUser)) y.update(self.aliceUser, self.aliceUser, 43) z = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda otxt: ictxt == self.aliceUser or ictxt == self.bobUser or ictxt == self.carolUser) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 85)
def test_combining_confidentiality_with_operations(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) y = ProtectedRef(2, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.bobUser) y.update(self.aliceUser, self.aliceUser, 43) z = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser or ictxt == self.bobUser or ictxt == self.carolUser) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 44) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 44)
def test_combining_confidentiality_with_operations(self): # Only Bob is allowed to write to x. Bob writes to x. x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) # Only Alice is allowed to write to y and only Bob can see the result. # Alice writes to y. y = ProtectedRef( 2, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser and octxt == self.bobUser) y.update(self.aliceUser, self.aliceUser, 43) # Alice, Bob, and Carol are allowed to write to z. z = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser or ictxt == self.bobUser or ictxt == self.carolUser) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 44) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 44)
def test_combining_confidentiality_with_operations(self): # Only Bob is allowed to write to x. Bob writes to x. x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) # Only Alice is allowed to write to y and only Bob can see the result. # Alice writes to y. y = ProtectedRef(2, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.bobUser) y.update(self.aliceUser, self.aliceUser, 43) # Alice, Bob, and Carol are allowed to write to z. z = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser or ictxt == self.bobUser or ictxt == self.carolUser) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 44) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 44)
class GamePiece: __metaclass__ = ABCMeta def __init__(self, owner): self.owner = owner self._placedRef = ProtectedRef(False , lambda hasShip: lambda ic: (not hasShip) and self.isOwner(ic) , None) # TODO: See if we can do away with this... self._placed = False self.bombedRef = ProtectedRef(False , lambda hasBomb: lambda ic: not hasBomb , None) # TODO: See if we can do away with this... self.bombed = False self._squares = [] def __eq__(self, other): return (self.__class__.__name__ == other.__class__.__name__ and self.owner == other.owner) def isOwner(self, ctxt): return ctxt.user == self.owner # If the current user is allowed to place the pice, then we mark the current # piece as placed and return True. Otherwise we return False. def placePiece(self, ctxt): if (self._placedRef.update(ctxt, ctxt, True) == UpdateResult.Success): self._placed = True return True else: return False # This is always a concrete value. def isPlaced(self): return self._placed # If the current user is allowed to bomb the piece, then we mark the piece # and return True. Otherwise we return False. def bombPiece(self, ctxt): if (self.bombedRef.update(ctxt, ctxt, true) == UpdateResult.Success): self.bombed = True; return True else: return False # This is always a concrete value. def isBombed(self): return self.bombed # Gets the board coordinates associated with a given piece. @jeeves def getPiecePoints(self, start, end): if start.inLine(end) and start.distance(end) == self.size: # If we are on the same horizontal line... if start.x == end.x: yPts = range(start.y , end.y) if start.y < end.y else range(end.y, start.y) return map(lambda yPt: Point(start.x, yPt), yPts) else: xPts = range(start.x , end.x) if start.x < end.x else range(end.x, start.x) return map(lambda xPt: Point(xPt, start.y), xPts) else: return None # Adds a piece to the list of squares associated with a given piece. def addSquare(self, s): self._squares.append(s) return True def getSquares(self): return self._squares
def test_write_disallowed_for_all_viewers(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser)) assert x.update(self.bobUser, self.bobUser, 42) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 0) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 0) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 0)
class GamePiece: __metaclass__ = ABCMeta def __init__(self, owner): self.owner = owner self._placedRef = ProtectedRef( False, lambda hasShip: lambda ic: (not hasShip) and self.isOwner(ic), None) # TODO: See if we can do away with this... self._placed = False self._bombed = False self._squares = [] def __eq__(self, other): return (self.name == other.name and self.owner == other.owner) def isOwner(self, ctxt): return ctxt.user == self.owner # If the current user is allowed to place the pice, then we mark the current # piece as placed and return True. Otherwise we return False. def placePiece(self, ctxt): if (self._placedRef.update(ctxt, ctxt, True) == UpdateResult.Success): self._placed = True return True else: return False # This is always a concrete value. def isPlaced(self): return self._placed # If the current user is allowed to bomb the piece, then we mark the piece # and return True. Otherwise we return False. def bombPiece(self, ctxt): self._bombed = True return True # This is always a concrete value. def isBombed(self): return self._bombed # Gets the board coordinates associated with a given piece. def getPiecePoints(self, start, end): if start.inLine(end) and start.distance(end) == self.size: # If we are on the same horizontal line... if start.x == end.x: yPts = range(start.y, end.y) if start.y < end.y else range( end.y, start.y) return map(lambda yPt: Point(start.x, yPt), yPts) else: xPts = range(start.x, end.x) if start.x < end.x else range( end.x, start.x) return map(lambda xPt: Point(xPt, start.y), xPts) else: return None # Adds a piece to the list of squares associated with a given piece. def addSquare(self, s): self._squares.append(s) return True def getSquares(self): return self._squares