bitcoin 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. metadata +17 -288
  2. data/.rspec +0 -1
  3. data/.rvmrc +0 -1
  4. data/Gemfile +0 -4
  5. data/Gemfile.lock +0 -98
  6. data/Guardfile +0 -38
  7. data/README.markdown +0 -24
  8. data/Rakefile +0 -1
  9. data/bin/rbcoin +0 -8
  10. data/bitcoin.gemspec +0 -40
  11. data/config/cucumber.yml +0 -5
  12. data/config/darcs.boring +0 -121
  13. data/doc/DEFINITION_OF_DONE.markdown +0 -12
  14. data/doc/HISTORY.markdown +0 -19
  15. data/doc/LICENCE.markdown +0 -25
  16. data/doc/TODO.markdown +0 -31
  17. data/doc/UBIQUITOUS_LANGUAGE.markdown +0 -15
  18. data/features/descriptions/command_help.feature +0 -31
  19. data/features/descriptions/satoshi_wallet/add_address.feature +0 -49
  20. data/features/descriptions/satoshi_wallet/show_addresses.feature +0 -18
  21. data/features/descriptions/satoshi_wallet/show_version.feature +0 -17
  22. data/features/descriptions/satoshi_wallet/subcommand_help.feature +0 -20
  23. data/features/fixtures/ABOUT_FIXTURES.markdown +0 -6
  24. data/features/fixtures/addressbook_wallet.dat +0 -0
  25. data/features/fixtures/new_wallet.dat +0 -0
  26. data/features/step_definitions/command_steps.rb +0 -3
  27. data/features/step_definitions/wallet_steps.rb +0 -11
  28. data/features/support/env.rb +0 -9
  29. data/lib/bitcoin.rb +0 -5
  30. data/lib/bitcoin/cli.rb +0 -35
  31. data/lib/bitcoin/commands.rb +0 -3
  32. data/lib/bitcoin/commands/help_command.rb +0 -32
  33. data/lib/bitcoin/commands/satoshi_wallet.rb +0 -11
  34. data/lib/bitcoin/commands/satoshi_wallet/add_address_command.rb +0 -61
  35. data/lib/bitcoin/commands/satoshi_wallet/show_addresses_command.rb +0 -16
  36. data/lib/bitcoin/commands/satoshi_wallet/show_version_command.rb +0 -15
  37. data/lib/bitcoin/commands/satoshi_wallet_command.rb +0 -37
  38. data/lib/bitcoin/commands/satoshi_wallet_command_environment.rb +0 -28
  39. data/lib/bitcoin/console/capturing_stream_bundle.rb +0 -42
  40. data/lib/bitcoin/console/stream_bundle.rb +0 -21
  41. data/lib/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository.rb +0 -155
  42. data/lib/bitcoin/data_access/satoshi/satoshi_version.rb +0 -58
  43. data/lib/bitcoin/data_access/satoshi/satoshi_wallet.rb +0 -39
  44. data/lib/bitcoin/domain/address_book.rb +0 -19
  45. data/lib/bitcoin/domain/bitcoin_address.rb +0 -33
  46. data/lib/bitcoin/filesystem/empty_temp_dir.rb +0 -74
  47. data/lib/bitcoin/rspec/argument_matchers.rb +0 -1
  48. data/lib/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher.rb +0 -23
  49. data/lib/bitcoin/rspec/directory_helpers.rb +0 -22
  50. data/lib/bitcoin/version.rb +0 -3
  51. data/spec/bitcoin/cli_spec.rb +0 -128
  52. data/spec/bitcoin/commands/help_command_spec.rb +0 -53
  53. data/spec/bitcoin/commands/satoshi_wallet/add_address_command_spec.rb +0 -149
  54. data/spec/bitcoin/commands/satoshi_wallet/show_addresses_command_spec.rb +0 -26
  55. data/spec/bitcoin/commands/satoshi_wallet/show_version_command_spec.rb +0 -26
  56. data/spec/bitcoin/commands/satoshi_wallet_command_environment_spec.rb +0 -76
  57. data/spec/bitcoin/commands/satoshi_wallet_command_spec.rb +0 -73
  58. data/spec/bitcoin/console/_contracts/stream_bundle_contract.rb +0 -29
  59. data/spec/bitcoin/console/capturing_stream_bundle_spec.rb +0 -74
  60. data/spec/bitcoin/console/stream_bundle_spec.rb +0 -13
  61. data/spec/bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository_spec.rb +0 -78
  62. data/spec/bitcoin/data_access/satoshi/satoshi_version_spec.rb +0 -112
  63. data/spec/bitcoin/data_access/satoshi/satoshi_wallet_spec.rb +0 -102
  64. data/spec/bitcoin/domain/address_book_spec.rb +0 -63
  65. data/spec/bitcoin/domain/bitcoin_address_spec.rb +0 -52
  66. data/spec/bitcoin/filesystem/empty_temp_dir_spec.rb +0 -170
  67. data/spec/bitcoin/rspec/argument_matchers/block_evaluating_to_matcher_spec.rb +0 -36
  68. data/spec/spec_helper.rb +0 -29
@@ -1,13 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'bitcoin/console/stream_bundle'
4
-
5
- require_relative '_contracts/stream_bundle_contract'
6
-
7
- module Bitcoin
8
- module Console
9
- describe StreamBundle do
10
- it_satisfies_contract "StreamBundle"
11
- end
12
- end
13
- end
@@ -1,78 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'bitcoin/data_access/satoshi/bdb_satoshi_wallet_repository'
4
- require 'bitcoin/rspec/directory_helpers'
5
-
6
- module Bitcoin
7
- module DataAccess
8
- module Satoshi
9
- describe BDBSatoshiWalletRepository, adapter: :slow do
10
- include Bitcoin::RSpec::DirectoryHelpers
11
-
12
- TEMP_DB_DIR = File.join(PROJECT_ROOT, "tmp", "db").freeze
13
- ensure_empty_test_dir(TEMP_DB_DIR)
14
-
15
- # Temporary means to get a copy of the fixture file
16
- before(:each) do
17
- FileUtils.cp(File.join(PROJECT_ROOT, "features", "fixtures", wallet_fixture_filename), TEMP_DB_DIR)
18
- end
19
-
20
- def wallet_filename
21
- File.join(PROJECT_ROOT, "tmp", "db", wallet_fixture_filename)
22
- end
23
-
24
- let(:wallet_fixture_filename) { "addressbook_wallet.dat" }
25
-
26
- subject { BDBSatoshiWalletRepository.new(wallet_filename, db_dirname: TEMP_DB_DIR) }
27
-
28
- it "has a less naive write_compact_size"
29
-
30
- describe "4-byte unsigned little endian integers stored immediately (no compact length in the value)" do
31
- specify {
32
- subject.get_value_immediate_uint32le("version").should eq 32400
33
- }
34
-
35
- specify {
36
- expect {
37
- subject.set_value_immediate_uint32le("version", 32500)
38
- }.to change {
39
- subject.get_value_immediate_uint32le("version")
40
- }.from(32400).to(32500)
41
- }
42
- end
43
-
44
- describe "string key data, string value data" do
45
- it "lets you read all values" do
46
- subject.get_key_and_value_data_string_utf8("name").should eq [
47
- [ "13f2t2WKnCZh1rZbDhdUKB6fY1rZNWZVzd", "Receiving address 2" ],
48
- [ "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", "Bitcoin Monitor" ],
49
- [ "16kzGRdP8LToECecna3EynghiApUM9duLw", "Receiving address 1" ],
50
- [ "1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw", "Bitcoincharts" ]
51
- ]
52
- end
53
-
54
- it "lets you read individual values" do
55
- subject.get_value_with_key_data_string_utf8("name", "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz").should eq "Bitcoin Monitor"
56
- end
57
-
58
- it "lets you create" do
59
- expect {
60
- subject.set_value_with_key_data_string_utf8("name", "1ThisIsAMadeUpKeyKudFr63EwHqQT2njz", "New Value")
61
- }.to change {
62
- subject.get_value_with_key_data_string_utf8("name", "1ThisIsAMadeUpKeyKudFr63EwHqQT2njz")
63
- }.from(nil).to("New Value")
64
- end
65
-
66
- it "lets you update" do
67
- expect {
68
- subject.set_value_with_key_data_string_utf8("name", "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", "Really is Bitcoin Monitor")
69
- }.to change {
70
- subject.get_value_with_key_data_string_utf8("name", "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz")
71
- }.from("Bitcoin Monitor").to("Really is Bitcoin Monitor")
72
- end
73
- end
74
- end
75
- end
76
- end
77
- end
78
-
@@ -1,112 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'bitcoin/data_access/satoshi/satoshi_version'
4
-
5
- module Bitcoin
6
- module DataAccess
7
- module Satoshi
8
- describe SatoshiVersion do
9
- describe ".from_wallet_bytes" do
10
- it "supports the data format as extracted from the BDB database" do
11
- SatoshiVersion.from_wallet_bytes([144, 126, 0, 0]).should eq SatoshiVersion.new(0, 3, 24)
12
- end
13
- end
14
-
15
- describe ".from_wallet_int" do
16
- it "supports the data format as extracted from the BDB database" do
17
- SatoshiVersion.from_wallet_int(32400).should eq SatoshiVersion.new(0, 3, 24)
18
- end
19
- end
20
-
21
- describe "three-part form" do
22
- it "compares equality" do
23
- SatoshiVersion.new(0, 3, 24).should eq SatoshiVersion.new(0, 3, 24)
24
-
25
- SatoshiVersion.new(0, 3, 24).should_not eq SatoshiVersion.new(0, 3, 25)
26
- SatoshiVersion.new(0, 3, 24).should_not eq SatoshiVersion.new(0, 4, 24)
27
- SatoshiVersion.new(0, 3, 24).should_not eq SatoshiVersion.new(1, 3, 24)
28
- end
29
-
30
- it "has a total ordering" do
31
- SatoshiVersion.new(0, 3, 24).should be < SatoshiVersion.new(0, 3, 25)
32
- SatoshiVersion.new(0, 3, 24).should be > SatoshiVersion.new(0, 3, 23)
33
-
34
- SatoshiVersion.new(0, 3, 24).should be < SatoshiVersion.new(0, 4, 23)
35
- SatoshiVersion.new(0, 3, 24).should be > SatoshiVersion.new(0, 2, 25)
36
-
37
- SatoshiVersion.new(1, 3, 24).should be < SatoshiVersion.new(2, 2, 23)
38
- SatoshiVersion.new(1, 3, 24).should be > SatoshiVersion.new(0, 4, 25)
39
- end
40
- end
41
-
42
- describe "four-part form" do
43
- # We cheat slightly here and make assumptions about the implementation
44
- # (by not re-specifying every conceivable possibility)
45
-
46
- it "compares equality" do
47
- SatoshiVersion.new(0, 3, 24, 0).should eq SatoshiVersion.new(0, 3, 24, 0)
48
- SatoshiVersion.new(0, 3, 24, 0).should_not eq SatoshiVersion.new(0, 3, 24, 1)
49
- end
50
-
51
- it "has a total ordering" do
52
- SatoshiVersion.new(0, 3, 24, 1).should be < SatoshiVersion.new(0, 3, 25, 2)
53
- SatoshiVersion.new(0, 3, 24, 1).should be > SatoshiVersion.new(0, 3, 23, 0)
54
-
55
- SatoshiVersion.new(0, 3, 24, 1).should be < SatoshiVersion.new(0, 3, 25, 0)
56
- SatoshiVersion.new(0, 3, 24, 1).should be > SatoshiVersion.new(0, 3, 23, 2)
57
-
58
- # etc, for the rest of the components...
59
- end
60
- end
61
-
62
- describe "-beta version suffixes" do
63
- it "are not supported", because: "this is hardcoded into the Satoshi client" do
64
- # As of 0.3.24, the "beta" status is determined in the C++ code with this value:
65
- # static const bool VERSION_IS_BETA = true;
66
- false.should be_false
67
- end
68
- end
69
-
70
- describe "comparing three- and four-part forms" do
71
- # This is not explicit in the Satoshi code, but seems a reasonable assumption for now,
72
- # until it breaks...
73
- it "assumes an implicit 0 at the end of the three-part form" do
74
- SatoshiVersion.new(0, 3, 24).should eq SatoshiVersion.new(0, 3, 24, 0)
75
- SatoshiVersion.new(0, 3, 24, 0).should eq SatoshiVersion.new(0, 3, 24)
76
- # it seems safe to assume the rest of the comparisons work by induction
77
- end
78
- end
79
-
80
- describe "conversion" do
81
- describe "to strings" do
82
- it "supports #to_s", because: "we need to be usable with IO#<<" do
83
- SatoshiVersion.new(0, 3, 24).to_s.should eq "0.3.24"
84
- SatoshiVersion.new(0, 3, 24, 1).to_s.should eq "0.3.24.1"
85
- end
86
-
87
- it "truncates a fourth zero", because: "the standard client does this (semantic versioning?)" do
88
- SatoshiVersion.new(0, 3, 24, 0).to_s.should eq "0.3.24"
89
- end
90
-
91
- it "does not truncate a third version", because: "the standard client does this (semantic versioning?)" do
92
- SatoshiVersion.new(0, 4, 0).to_s.should eq "0.4.0"
93
- end
94
-
95
- it "supports #to_str as an alias of :to_s" do
96
- version = SatoshiVersion.new(0, 3, 24)
97
- to_s_method = version.method(:to_s)
98
- to_str_method = version.method(:to_str)
99
- to_str_method.should eq to_s_method
100
- end
101
- end
102
-
103
- describe "to Satoshi-format wallet bytes" do
104
- it "creates the same bytes as came from the BDB database" do
105
- SatoshiVersion.new(0, 3, 24).to_wallet_bytes.should eq [144, 126, 0, 0]
106
- end
107
- end
108
- end
109
- end
110
- end
111
- end
112
- end
@@ -1,102 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'bitcoin/data_access/satoshi/satoshi_wallet'
4
-
5
- module Bitcoin
6
- module DataAccess
7
- module Satoshi
8
- describe SatoshiWallet do
9
- describe ".open" do
10
- let(:satoshi_wallet_repository) { mock(BDBSatoshiWalletRepository) }
11
- let(:satoshi_wallet) { mock(SatoshiWallet) }
12
-
13
- before(:each) do
14
- BDBSatoshiWalletRepository.stub(new: satoshi_wallet_repository)
15
- SatoshiWallet.stub(new: satoshi_wallet)
16
- end
17
-
18
- it "makes a BDBSatoshiWalletRepository" do
19
- BDBSatoshiWalletRepository.should_receive(:new).with("wallet.dat", db_dirname: "/db/dir")
20
- SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir", & ->(wallet) { :noop })
21
- end
22
-
23
- it "makes a SatoshiWallet with the BDBSatoshiWalletRepository" do
24
- SatoshiWallet.should_receive(:new).with(satoshi_wallet_repository)
25
- SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir", & ->(wallet) { :noop })
26
- end
27
-
28
- it "yields the wallet" do
29
- SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir") do |wallet|
30
- wallet.should eq satoshi_wallet
31
- end
32
- end
33
-
34
- it "returns the value of the block" do
35
- SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir") { |wallet|
36
- :block_value
37
- }.should eq :block_value
38
- end
39
-
40
- it "raises an error if no block is given", because: "we use blocks to manage the opening and closing of the BDB database" do
41
- expect {
42
- SatoshiWallet.open(wallet_filename: "wallet.dat", db_dirname: "/db/dir")
43
- }.to raise_error(ArgumentError) { |error|
44
- error.message.should =~ /you must provide a block to SatoshiWallet\.new/i
45
- }
46
- end
47
- end
48
-
49
- describe "instance methods" do
50
- let(:satoshi_wallet_repository) { mock(BDBSatoshiWalletRepository) }
51
-
52
- before(:each) do
53
- BDBSatoshiWalletRepository.stub(new: satoshi_wallet_repository)
54
- end
55
-
56
- subject { SatoshiWallet.new(satoshi_wallet_repository) }
57
-
58
- describe "#version" do
59
- it "returns the version from the wallet" do
60
- satoshi_wallet_repository.should_receive(:get_value_immediate_uint32le).with("version").and_return(32400)
61
- subject.version.should eq SatoshiVersion.new(0, 3, 24)
62
- end
63
- end
64
-
65
- describe "#addresses" do
66
- before(:each) do
67
- satoshi_wallet_repository.stub(
68
- get_key_and_value_data_string_utf8: [
69
- [ "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", "Bitcoin Monitor" ],
70
- [ "1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw", "Bitcoincharts" ]
71
- ]
72
- )
73
- end
74
-
75
- it "fetches the data" do
76
- satoshi_wallet_repository.should_receive(:get_key_and_value_data_string_utf8).with("name")
77
- subject.addresses
78
- end
79
-
80
- it "returns an AddressBook with the wallet addresses" do
81
- subject.addresses.should be_a Domain::AddressBook
82
- expected_addresses = Domain::AddressBook.new([
83
- { address: Domain::BitcoinAddress.new("14Z1mazY4HfysZyMaKudFr63EwHqQT2njz"), name: "Bitcoin Monitor" },
84
- { address: Domain::BitcoinAddress.new("1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw"), name: "Bitcoincharts" }
85
- ]).to_a
86
- subject.addresses.to_a.should =~ expected_addresses
87
- end
88
- end
89
-
90
- describe "#add_address" do
91
- it "adds the BitcoinAddress to the Wallet" do
92
- satoshi_wallet_repository.should_receive(:set_value_with_key_data_string_utf8).with(
93
- "name", "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", "Bitcoin Monitor"
94
- )
95
- subject.add_address(Domain::BitcoinAddress.new("14Z1mazY4HfysZyMaKudFr63EwHqQT2njz"), name: "Bitcoin Monitor")
96
- end
97
- end
98
- end
99
- end
100
- end
101
- end
102
- end
@@ -1,63 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'bitcoin/domain/address_book'
4
-
5
- module Bitcoin
6
- module Domain
7
- describe AddressBook do
8
- context "made with no addresses" do
9
- subject { AddressBook.new }
10
- its(:to_a) { should eq [ ] }
11
- end
12
-
13
- context "made with addresses" do
14
- let(:address_hashes) {
15
- [
16
- { address: "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", name: "Bitcoin Monitor" },
17
- { address: "1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw", name: "Bitcoincharts" }
18
- ]
19
- }
20
-
21
- subject {
22
- AddressBook.new(address_hashes)
23
- }
24
-
25
- its(:to_a) {
26
- should =~ [
27
- { address: "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz", name: "Bitcoin Monitor" },
28
- { address: "1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw", name: "Bitcoincharts" }
29
- ]
30
- }
31
-
32
- # We're assuming the output comes out in the input order, so this example is
33
- # overly precise until we know how we'll handle presentation
34
- its(:to_s) {
35
- should eq(
36
- -%{
37
- 14Z1mazY4HfysZyMaKudFr63EwHqQT2njz Bitcoin Monitor
38
- 1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw Bitcoincharts
39
- }
40
- )
41
- }
42
-
43
- describe "argument cloning" do
44
- # Ensure this is created before we try changing the input arguments
45
- before(:each) { subject }
46
-
47
- it "does not mutate the args" do
48
- expect {
49
- address_hashes.delete_if { true }
50
- }.to_not change {
51
- subject.to_a.length
52
- }.from(2).to(0)
53
- end
54
-
55
- it "makes a deep copy" do
56
- address_hashes.first[:name] = "changed"
57
- subject.to_a.map { |hash| hash[:name] }.should_not include("changed")
58
- end
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,52 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'bitcoin/domain/bitcoin_address'
4
-
5
- module Bitcoin
6
- module Domain
7
- describe BitcoinAddress do
8
- context "created with a valid real network address" do
9
- subject { BitcoinAddress.new("14Z1mazY4HfysZyMaKudFr63EwHqQT2njz") }
10
-
11
- its(:to_s) { should eq "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz" }
12
-
13
- describe "#==" do
14
- it "is equal to another BitcoinAddress with the same address" do
15
- subject.should eq BitcoinAddress.new("14Z1mazY4HfysZyMaKudFr63EwHqQT2njz")
16
- end
17
-
18
- it "is not equal to a BitcoinAddress with a different address" do
19
- subject.should_not eq BitcoinAddress.new("1Nqr3MqVyUp6k3o3QPePAdn4Yg4tzgB9kw")
20
- end
21
-
22
- it "is not equal to a String" do
23
- subject.should_not eq "14Z1mazY4HfysZyMaKudFr63EwHqQT2njz"
24
- end
25
- end
26
- end
27
-
28
- context "creating with an invalid address" do
29
- invalid_addresses = [
30
- # Not actually sure the reasons here are valid in general but it's just enough to
31
- # get us going (the point of the exercise is to put an error protocol in place)
32
- { address: "14Z1mazY4HfysZyMaKudFr63EwHqQT2nj", because: "this is too short" },
33
- { address: "14Z1mazY4HfysZyMaKudFr63EwHqQT2njzX", because: "this is too long" }
34
- # Hash doesn't match
35
- # Wrong version
36
- # ... etc ...
37
- # (When we know more about Bitcoin crypto we can come back and finish this off)
38
- ]
39
-
40
- invalid_addresses.each do |invalid_address|
41
- it "raises an error for address #{invalid_address[:address]} because #{invalid_address[:because]}" do
42
- expect {
43
- BitcoinAddress.new(invalid_address[:address])
44
- }.to raise_error(BitcoinAddress::InvalidBitcoinAddressError) { |error|
45
- error.message.should eq %'The address "#{invalid_address[:address]}" is not a valid Bitcoin address'
46
- }
47
- end
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,170 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'bitcoin/filesystem/empty_temp_dir'
4
- require 'bitcoin/rspec/directory_helpers'
5
-
6
- module Bitcoin
7
- module FileSystem
8
- describe EmptyTempDir do
9
- include Bitcoin::RSpec::DirectoryHelpers
10
-
11
- TEMP_TEST_DIR = File.join(PROJECT_ROOT, "tmp", "test").freeze
12
-
13
- ensure_empty_test_dir(TEMP_TEST_DIR)
14
-
15
- describe ".open" do
16
- describe "integration" do # refactoring invariant
17
- it "lets you create a temporary file inside the temporary directory" do
18
- expected_temp_dir_name = File.join(TEMP_TEST_DIR, "temp_dir")
19
-
20
- EmptyTempDir.open(with_name: "temp_dir", parallel_to: File.join(TEMP_TEST_DIR, "wallet.dat")) do |temp_dir|
21
- File.open(File.join(temp_dir.absolute_path, "test_file"), "w") do |file|
22
- file << "some unimportant contents"
23
- end
24
- Dir.entries(temp_dir.absolute_path).should eq %w[ . .. test_file ]
25
- end
26
-
27
- File.exist?(expected_temp_dir_name).should be_false
28
- end
29
- end
30
-
31
- describe "interactions" do
32
- let(:block_runner) { mock(EmptyTempDir::BlockRunner, run: :block_runner_run_value) }
33
-
34
- before(:each) do
35
- EmptyTempDir::BlockRunner.stub(new: block_runner)
36
- end
37
-
38
- it "raises an error if no block is provided", because: "this would be a pointless thing to do" do
39
- expect {
40
- EmptyTempDir.open(with_name: "temp_dir", parallel_to: File.join(TEMP_TEST_DIR, "wallet.dat"))
41
- }.to raise_error(ArgumentError) { |error|
42
- error.message.should =~ /you must provide a block to EmptyTempDir\.open/i
43
- }
44
- end
45
-
46
- describe "creating the BlockRunner" do
47
- it "calculates a directory name parallel to the file" do
48
- EmptyTempDir::BlockRunner.should_receive(:new).with("/foo/bar/temp_dir")
49
- EmptyTempDir.open(with_name: "temp_dir", parallel_to: "/foo/bar/baz", & -> { :noop })
50
- end
51
-
52
- it "always passed absolute directories" do
53
- EmptyTempDir::BlockRunner.should_receive(:new).with(File.join(PROJECT_ROOT, "/foo/bar/anything"))
54
- EmptyTempDir.open(with_name: "anything", parallel_to: "foo/bar/baz", & -> { :noop })
55
- end
56
- end
57
-
58
- it "runs the block" do
59
- block = -> { :block_value }
60
- block_runner.should_receive(:run).with(block_evaluating_to(:block_value))
61
- EmptyTempDir.open(with_name: "anything", parallel_to: "/foo/bar/baz", &block)
62
- end
63
-
64
- it "returns the value of the block" do
65
- EmptyTempDir.open(with_name: "temp_dir", parallel_to: "/foo/bar/baz", & -> { :noop }).should eq :block_runner_run_value
66
- end
67
- end
68
- end
69
-
70
- describe EmptyTempDir::BlockRunner do
71
- describe ".new" do
72
- # Yes, I actually did this to myself.
73
- describe "raising an error on unsafe paths", because: "otherwise it could format your hard drive!" do
74
- [ "", "/", "//" ].each do |unacceptable_path|
75
- it "blocks #{unacceptable_path.inspect}" do
76
- expect {
77
- EmptyTempDir::BlockRunner.new(unacceptable_path)
78
- }.to raise_error(ArgumentError) { |error|
79
- error.message.should eq "Unacceptable directory name for EmptyTempDir"
80
- }
81
- end
82
- end
83
- end
84
- end
85
-
86
- describe "#run" do
87
- shared_examples "EmptyTempDir::BlockRunner#run" do
88
- let(:expected_temp_dir_name) { File.join(TEMP_TEST_DIR, "temp_dir") }
89
- subject { EmptyTempDir::BlockRunner.new(expected_temp_dir_name) }
90
-
91
- it "ensures the directory exists" do
92
- subject.run(
93
- ->(temp_dir) { File.directory?(expected_temp_dir_name) }
94
- ).should be_true
95
- end
96
-
97
- it "ensures the directory is empty" do
98
- subject.run(
99
- ->(temp_dir) { Dir.entries(expected_temp_dir_name) }
100
- ).should =~ %w[ . .. ]
101
- end
102
-
103
- it "removes the directory at the end (even if a file was created inside it)" do
104
- subject.run(
105
- ->(temp_dir) {
106
- File.open(File.join(temp_dir.absolute_path, "test_file"), "w") do |file|
107
- file << "unimportant contents"
108
- end
109
- Dir.entries(temp_dir.absolute_path).should eq %w[ . .. test_file ]
110
- }
111
- )
112
-
113
- File.exist?(expected_temp_dir_name).should be_false
114
- end
115
-
116
- it "removes the directory even if the block raises an error" do
117
- expect {
118
- subject.run(->(temp_dir) { raise RuntimeError.new("I'm trying to make the temp dir persist!") })
119
- }.to raise_error
120
-
121
- File.exist?(expected_temp_dir_name).should be_false
122
- end
123
-
124
- it "re-raises any error thrown in the block" do
125
- expected_error = RuntimeError.new("I'm trying to make the temp dir persist!")
126
-
127
- expect {
128
- subject.run(->(temp_dir) { raise expected_error })
129
- }.to raise_error { |actual_error|
130
- actual_error.should equal expected_error
131
- }
132
- end
133
-
134
- it "has the expected path name" do
135
- subject.run(->(temp_dir) { temp_dir.absolute_path.should eq expected_temp_dir_name })
136
- end
137
-
138
- it "returns the value of the block", because: "all the examples rely on this" do
139
- subject.run(->(temp_dir) {
140
- :block_value
141
- }).should eq :block_value
142
- end
143
- end
144
-
145
- context "where the target directory does not exist" do
146
- before(:each) do
147
- FileUtils.rm_rf(expected_temp_dir_name)
148
- end
149
-
150
- it_behaves_like "EmptyTempDir::BlockRunner#run"
151
- end
152
-
153
- context "where the target directory exists" do
154
- before(:each) do
155
- existing_file_name = File.join(expected_temp_dir_name, "intermediate_dir", "test_file")
156
-
157
- # Make the target directory and a file inside a nested folder inside it
158
- FileUtils.mkdir_p(File.dirname(existing_file_name))
159
- File.open(existing_file_name, "w") do |file|
160
- file << "some unimportant contents"
161
- end
162
- end
163
-
164
- it_behaves_like "EmptyTempDir::BlockRunner#run"
165
- end
166
- end
167
- end
168
- end
169
- end
170
- end