|  | // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | library MintMakerTest; | 
|  |  | 
|  | import 'dart:async'; | 
|  | import 'dart:isolate'; | 
|  | import 'package:unittest/unittest.dart'; | 
|  | import "remote_unittest_helper.dart"; | 
|  |  | 
|  | class Mint { | 
|  | Map<SendPort, Purse> _registry; | 
|  | SendPort port; | 
|  |  | 
|  | Mint() : _registry = new Map<SendPort, Purse>() { | 
|  | ReceivePort mintPort = new ReceivePort(); | 
|  | port = mintPort.sendPort; | 
|  | serveMint(mintPort); | 
|  | } | 
|  |  | 
|  | void serveMint(ReceivePort port) { | 
|  | port.listen((message) { | 
|  | int balance = message[0]; | 
|  | Purse purse = createPurse(balance); | 
|  | message[1].send(purse.port); | 
|  | }); | 
|  | } | 
|  |  | 
|  | Purse createPurse(int balance) { | 
|  | Purse purse = new Purse(this, balance); | 
|  | _registry[purse.port] = purse; | 
|  | return purse; | 
|  | } | 
|  |  | 
|  | Purse lookupPurse(SendPort port) { | 
|  | return _registry[port]; | 
|  | } | 
|  | } | 
|  |  | 
|  | class MintWrapper { | 
|  | SendPort _mint; | 
|  | MintWrapper(SendPort this._mint) {} | 
|  |  | 
|  | void createPurse(int balance, handlePurse(PurseWrapper purse)) { | 
|  | ReceivePort reply = new ReceivePort(); | 
|  | reply.first.then((SendPort purse) { | 
|  | handlePurse(new PurseWrapper(purse)); | 
|  | }); | 
|  | _mint.send([balance, reply.sendPort]); | 
|  | } | 
|  | } | 
|  |  | 
|  | class Purse { | 
|  | Mint mint; | 
|  | int balance; | 
|  | SendPort port; | 
|  |  | 
|  | Purse(this.mint, this.balance) { | 
|  | ReceivePort recipient = new ReceivePort(); | 
|  | port = recipient.sendPort; | 
|  | servePurse(recipient); | 
|  | } | 
|  |  | 
|  | void servePurse(ReceivePort recipient) { | 
|  | recipient.listen((message) { | 
|  | String command = message[0]; | 
|  | if (command == "balance") { | 
|  | SendPort replyTo = message.last; | 
|  | replyTo.send(queryBalance()); | 
|  | } else if (command == "deposit") { | 
|  | Purse source = mint.lookupPurse(message[2]); | 
|  | deposit(message[1], source); | 
|  | } else if (command == "sprout") { | 
|  | SendPort replyTo = message.last; | 
|  | Purse result = sproutPurse(); | 
|  | replyTo.send(result.port); | 
|  | } else { | 
|  | // TODO: Send an exception back. | 
|  | throw UnsupportedError("Unsupported commend: $command"); | 
|  | } | 
|  | }); | 
|  | } | 
|  |  | 
|  | int queryBalance() { | 
|  | return balance; | 
|  | } | 
|  |  | 
|  | Purse sproutPurse() { | 
|  | return mint.createPurse(0); | 
|  | } | 
|  |  | 
|  | void deposit(int amount, Purse source) { | 
|  | // TODO: Throw an exception if the source purse doesn't hold | 
|  | // enough dough. | 
|  | balance += amount; | 
|  | source.balance -= amount; | 
|  | } | 
|  | } | 
|  |  | 
|  | class PurseWrapper { | 
|  | SendPort _purse; | 
|  |  | 
|  | PurseWrapper(this._purse) {} | 
|  |  | 
|  | void _sendReceive(message, replyHandler(reply)) { | 
|  | ReceivePort reply = new ReceivePort(); | 
|  | _purse.send([message, reply.sendPort]); | 
|  | reply.first.then(replyHandler); | 
|  | } | 
|  |  | 
|  | void queryBalance(handleBalance(int balance)) { | 
|  | _sendReceive("balance", handleBalance); | 
|  | } | 
|  |  | 
|  | void sproutPurse(handleSprouted(PurseWrapper sprouted)) { | 
|  | _sendReceive("sprout", (SendPort sprouted) { | 
|  | handleSprouted(new PurseWrapper(sprouted)); | 
|  | }); | 
|  | } | 
|  |  | 
|  | void deposit(PurseWrapper source, int amount) { | 
|  | _purse.send(["deposit", amount, source._purse]); | 
|  | } | 
|  | } | 
|  |  | 
|  | mintMakerWrapper(SendPort replyPort) { | 
|  | ReceivePort receiver = new ReceivePort(); | 
|  | replyPort.send(receiver.sendPort); | 
|  | receiver.listen((SendPort replyTo) { | 
|  | Mint mint = new Mint(); | 
|  | replyTo.send(mint.port); | 
|  | }); | 
|  | } | 
|  |  | 
|  | class MintMakerWrapper { | 
|  | final SendPort _port; | 
|  |  | 
|  | static Future<MintMakerWrapper> create() { | 
|  | ReceivePort reply = new ReceivePort(); | 
|  | return Isolate | 
|  | .spawn(mintMakerWrapper, reply.sendPort) | 
|  | .then((_) => reply.first.then((port) => new MintMakerWrapper._(port))); | 
|  | } | 
|  |  | 
|  | MintMakerWrapper._(this._port); | 
|  |  | 
|  | void makeMint(handleMint(MintWrapper mint)) { | 
|  | ReceivePort reply = new ReceivePort(); | 
|  | reply.first.then((SendPort mint) { | 
|  | handleMint(new MintWrapper(mint)); | 
|  | }); | 
|  | _port.send(reply.sendPort); | 
|  | } | 
|  | } | 
|  |  | 
|  | _checkBalance(PurseWrapper wrapper, expected) { | 
|  | wrapper.queryBalance(expectAsync((int balance) { | 
|  | expect(balance, equals(expected)); | 
|  | })); | 
|  | } | 
|  |  | 
|  | void main([args, port]) { | 
|  | if (testRemote(main, port)) return; | 
|  | test("creating purse, deposit, and query balance", () { | 
|  | MintMakerWrapper.create().then(expectAsync((mintMaker) { | 
|  | mintMaker.makeMint(expectAsync((MintWrapper mint) { | 
|  | mint.createPurse(100, expectAsync((PurseWrapper purse) { | 
|  | _checkBalance(purse, 100); | 
|  | purse.sproutPurse(expectAsync((PurseWrapper sprouted) { | 
|  | _checkBalance(sprouted, 0); | 
|  | _checkBalance(purse, 100); | 
|  |  | 
|  | sprouted.deposit(purse, 5); | 
|  | _checkBalance(sprouted, 0 + 5); | 
|  | _checkBalance(purse, 100 - 5); | 
|  |  | 
|  | sprouted.deposit(purse, 42); | 
|  | _checkBalance(sprouted, 0 + 5 + 42); | 
|  | _checkBalance(purse, 100 - 5 - 42); | 
|  | })); | 
|  | })); | 
|  | })); | 
|  | })); | 
|  | }); | 
|  | } |