sodium 0.6.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/.travis.yml +13 -6
- data/CHANGELOG.md +15 -1
- data/VERSION +1 -1
- data/lib/sodium/auth.rb +8 -8
- data/lib/sodium/box.rb +27 -27
- data/lib/sodium/buffer.rb +141 -85
- data/lib/sodium/ffi/lib_c.rb +3 -0
- data/lib/sodium/hash.rb +3 -3
- data/lib/sodium/one_time_auth.rb +8 -8
- data/lib/sodium/random.rb +1 -1
- data/lib/sodium/secret_box.rb +10 -10
- data/lib/sodium/sign.rb +11 -11
- data/tasks/extensions.rake +12 -3
- data/test/sodium/auth/hmacsha256_test.rb +2 -2
- data/test/sodium/auth/hmacsha512256_test.rb +2 -2
- data/test/sodium/auth_test.rb +2 -2
- data/test/sodium/box/curve25519xsalsa20poly1305_test.rb +5 -5
- data/test/sodium/box_test.rb +6 -6
- data/test/sodium/buffer_test.rb +79 -72
- data/test/sodium/hash/sha256_test.rb +1 -1
- data/test/sodium/hash/sha512_test.rb +1 -1
- data/test/sodium/hash_test.rb +3 -2
- data/test/sodium/one_time_auth/poly1305_test.rb +1 -1
- data/test/sodium/one_time_auth_test.rb +2 -2
- data/test/sodium/secret_box/xsalsa20poly1305_test.rb +2 -2
- data/test/sodium/secret_box_test.rb +3 -3
- data/test/sodium/sign/ed25519_test.rb +1 -1
- data/test/sodium/sign_test.rb +4 -4
- metadata +154 -159
- metadata.gz.sig +2 -4
- checksums.yaml +0 -7
- checksums.yaml.gz.sig +0 -0
data/lib/sodium/ffi/lib_c.rb
CHANGED
data/lib/sodium/hash.rb
CHANGED
@@ -8,9 +8,9 @@ class Sodium::Hash
|
|
8
8
|
|
9
9
|
Sodium::Buffer.empty self.implementation[:BYTES] do |digest|
|
10
10
|
self.implementation.nacl(
|
11
|
-
digest.
|
12
|
-
message.
|
13
|
-
message.
|
11
|
+
digest .to_ptr,
|
12
|
+
message.to_ptr,
|
13
|
+
message.bytesize
|
14
14
|
) or raise Sodium::CryptoError, 'failed to generate a hash for the message'
|
15
15
|
end
|
16
16
|
end
|
data/lib/sodium/one_time_auth.rb
CHANGED
@@ -16,10 +16,10 @@ class Sodium::OneTimeAuth
|
|
16
16
|
|
17
17
|
Sodium::Buffer.empty self.implementation[:BYTES] do |authenticator|
|
18
18
|
self.implementation.nacl(
|
19
|
-
authenticator.
|
20
|
-
message.
|
21
|
-
message.
|
22
|
-
@key.
|
19
|
+
authenticator.to_ptr,
|
20
|
+
message .to_ptr,
|
21
|
+
message .bytesize,
|
22
|
+
@key .to_ptr
|
23
23
|
) or raise Sodium::CryptoError, 'failed to generate an authenticator'
|
24
24
|
end
|
25
25
|
end
|
@@ -29,10 +29,10 @@ class Sodium::OneTimeAuth
|
|
29
29
|
authenticator = self.class._authenticator(authenticator)
|
30
30
|
|
31
31
|
self.implementation.nacl_verify(
|
32
|
-
authenticator.
|
33
|
-
message.
|
34
|
-
message.
|
35
|
-
@key.
|
32
|
+
authenticator.to_ptr,
|
33
|
+
message .to_ptr,
|
34
|
+
message .bytesize,
|
35
|
+
@key .to_ptr
|
36
36
|
)
|
37
37
|
end
|
38
38
|
|
data/lib/sodium/random.rb
CHANGED
data/lib/sodium/secret_box.rb
CHANGED
@@ -21,11 +21,11 @@ class Sodium::SecretBox
|
|
21
21
|
|
22
22
|
Sodium::Buffer.empty(message.bytesize) do |ciphertext|
|
23
23
|
self.implementation.nacl(
|
24
|
-
ciphertext.
|
25
|
-
message.
|
26
|
-
message.
|
27
|
-
nonce.
|
28
|
-
@key.
|
24
|
+
ciphertext .to_ptr,
|
25
|
+
message .to_ptr,
|
26
|
+
message .bytesize,
|
27
|
+
nonce .to_ptr,
|
28
|
+
@key .to_ptr
|
29
29
|
) or raise Sodium::CryptoError, 'failed to close the secret box'
|
30
30
|
end.ldrop self.implementation[:BOXZEROBYTES]
|
31
31
|
end
|
@@ -36,11 +36,11 @@ class Sodium::SecretBox
|
|
36
36
|
|
37
37
|
Sodium::Buffer.empty(ciphertext.bytesize) do |message|
|
38
38
|
self.implementation.nacl_open(
|
39
|
-
message.
|
40
|
-
ciphertext.
|
41
|
-
ciphertext.
|
42
|
-
nonce.
|
43
|
-
@key.
|
39
|
+
message .to_ptr,
|
40
|
+
ciphertext .to_ptr,
|
41
|
+
ciphertext .bytesize,
|
42
|
+
nonce .to_ptr,
|
43
|
+
@key .to_ptr
|
44
44
|
) or raise Sodium::CryptoError, 'failed to open the secret box'
|
45
45
|
end.ldrop self.implementation[:ZEROBYTES]
|
46
46
|
end
|
data/lib/sodium/sign.rb
CHANGED
@@ -8,8 +8,8 @@ class Sodium::Sign
|
|
8
8
|
secret_key = Sodium::Buffer.empty self.implementation[:SECRETKEYBYTES]
|
9
9
|
|
10
10
|
self.implementation.nacl_keypair(
|
11
|
-
public_key.
|
12
|
-
secret_key.
|
11
|
+
public_key.to_ptr,
|
12
|
+
secret_key.to_ptr
|
13
13
|
) or raise Sodium::CryptoError, 'failed to generate a keypair'
|
14
14
|
|
15
15
|
return secret_key, public_key
|
@@ -22,11 +22,11 @@ class Sodium::Sign
|
|
22
22
|
mlen = FFI::MemoryPointer.new(:ulong_long, 1, true)
|
23
23
|
|
24
24
|
self.implementation.nacl_open(
|
25
|
-
message.
|
25
|
+
message .to_ptr,
|
26
26
|
mlen,
|
27
|
-
signature.
|
28
|
-
signature.
|
29
|
-
key.
|
27
|
+
signature .to_ptr,
|
28
|
+
signature .bytesize,
|
29
|
+
key .to_ptr
|
30
30
|
)
|
31
31
|
end
|
32
32
|
|
@@ -40,18 +40,18 @@ class Sodium::Sign
|
|
40
40
|
slen = FFI::MemoryPointer.new(:ulong_long, 1, true)
|
41
41
|
|
42
42
|
self.implementation.nacl(
|
43
|
-
signature.
|
43
|
+
signature .to_ptr,
|
44
44
|
slen,
|
45
|
-
message.
|
46
|
-
message.
|
47
|
-
@key.
|
45
|
+
message .to_ptr,
|
46
|
+
message .bytesize,
|
47
|
+
@key .to_ptr
|
48
48
|
) or raise Sodium::CryptoError, 'failed to generate signature'
|
49
49
|
|
50
50
|
# signatures actually encode the message itself at the end, so we
|
51
51
|
# slice off only the signature bytes
|
52
52
|
signature.byteslice(
|
53
53
|
0,
|
54
|
-
slen.read_ulong_long - message.
|
54
|
+
slen.read_ulong_long - message.bytesize
|
55
55
|
)
|
56
56
|
end
|
57
57
|
|
data/tasks/extensions.rake
CHANGED
@@ -9,12 +9,18 @@ namespace :compile do
|
|
9
9
|
desc 'Compile the memory extension'
|
10
10
|
task :memory => %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}}
|
11
11
|
|
12
|
-
file %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}} =>
|
12
|
+
file %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}} => FileList[MEMORY_SRC] do
|
13
|
+
Dir.chdir(MEMORY_PATH) { ruby %{extconf.rb} }
|
13
14
|
sh %{make -C #{MEMORY_PATH} install sitearchdir="#{LIB_PATH}"}
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
task :clean do
|
18
|
+
sh %{make -C #{MEMORY_PATH} realclean} if
|
19
|
+
File.exist? %{#{MEMORY_PATH}/Makefile}
|
20
|
+
end
|
21
|
+
|
22
|
+
task :clobber do
|
23
|
+
CLOBBER.add %{#{LIB_PATH}/sodium/ffi/#{MEMORY_LIB}}
|
18
24
|
end
|
19
25
|
end
|
20
26
|
|
@@ -22,3 +28,6 @@ desc 'Compile all native extensions'
|
|
22
28
|
task :compile => %w{ compile:memory }
|
23
29
|
|
24
30
|
task :test => %w{ compile }
|
31
|
+
|
32
|
+
task :clean => :'compile:clean'
|
33
|
+
task :clobber => :'compile:clobber'
|
@@ -36,11 +36,11 @@ describe Sodium::Auth::HMACSHA256 do
|
|
36
36
|
self.klass.auth(
|
37
37
|
self.key,
|
38
38
|
self.plaintext
|
39
|
-
).
|
39
|
+
).to_s.must_equal self.authenticator
|
40
40
|
|
41
41
|
self.subject.auth(
|
42
42
|
self.plaintext
|
43
|
-
).
|
43
|
+
).to_s.must_equal self.authenticator
|
44
44
|
end
|
45
45
|
|
46
46
|
it 'must verify authenticators' do
|
@@ -35,11 +35,11 @@ describe Sodium::Auth::HMACSHA512256 do
|
|
35
35
|
self.klass.auth(
|
36
36
|
self.key,
|
37
37
|
self.plaintext
|
38
|
-
).
|
38
|
+
).to_s.must_equal self.authenticator
|
39
39
|
|
40
40
|
self.subject.auth(
|
41
41
|
self.plaintext
|
42
|
-
).
|
42
|
+
).to_s.must_equal self.authenticator
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'must verify authenticators' do
|
data/test/sodium/auth_test.rb
CHANGED
@@ -26,12 +26,12 @@ describe Sodium::Auth do
|
|
26
26
|
sodium_mock_default(self.klass) do |klass, mock|
|
27
27
|
mock.expect :[], 0, [:KEYBYTES]
|
28
28
|
|
29
|
-
klass.key.
|
29
|
+
klass.key.to_s.must_equal ''
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'must raise when instantiating with an invalid key' do
|
34
|
-
lambda { self.klass.new(self.key.
|
34
|
+
lambda { self.klass.new(self.key.to_s[0..-2]) }.
|
35
35
|
must_raise Sodium::LengthError
|
36
36
|
end
|
37
37
|
|
@@ -47,18 +47,18 @@ describe Sodium::Box::Curve25519XSalsa20Poly1305 do
|
|
47
47
|
self.subject.box(
|
48
48
|
self.plaintext,
|
49
49
|
self.nonce
|
50
|
-
).
|
50
|
+
).to_s.must_equal self.ciphertext
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'must open boxes' do
|
54
54
|
self.subject.open(
|
55
55
|
self.ciphertext,
|
56
56
|
self.nonce
|
57
|
-
).
|
57
|
+
).to_s.must_equal self.plaintext
|
58
58
|
end
|
59
59
|
|
60
60
|
it 'must generate shared keys' do
|
61
|
-
self.subject.beforenm.
|
61
|
+
self.subject.beforenm.to_s.must_equal self.shared_key
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'must generate closed boxes with shared keys' do
|
@@ -66,7 +66,7 @@ describe Sodium::Box::Curve25519XSalsa20Poly1305 do
|
|
66
66
|
self.shared_key,
|
67
67
|
self.plaintext,
|
68
68
|
self.nonce
|
69
|
-
).
|
69
|
+
).to_s.must_equal self.ciphertext
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'must open boxes with shared keys' do
|
@@ -74,6 +74,6 @@ describe Sodium::Box::Curve25519XSalsa20Poly1305 do
|
|
74
74
|
self.shared_key,
|
75
75
|
self.ciphertext,
|
76
76
|
self.nonce
|
77
|
-
).
|
77
|
+
).to_s.must_equal self.plaintext
|
78
78
|
end
|
79
79
|
end
|
data/test/sodium/box_test.rb
CHANGED
@@ -24,29 +24,29 @@ describe Sodium::Box do
|
|
24
24
|
|
25
25
|
it 'must mint keypairs from the default implementation' do
|
26
26
|
sodium_mock_default(self.klass) do |klass, mock|
|
27
|
-
mock.expect :nacl_keypair, true, [
|
27
|
+
mock.expect :nacl_keypair, true, [ FFI::Pointer, FFI::Pointer ]
|
28
28
|
mock.expect :[], 0, [:PUBLICKEYBYTES]
|
29
29
|
mock.expect :[], 0, [:SECRETKEYBYTES]
|
30
30
|
|
31
31
|
sk, pk = klass.keypair
|
32
32
|
|
33
|
-
sk.
|
34
|
-
pk.
|
33
|
+
sk.to_s.must_equal ''
|
34
|
+
pk.to_s.must_equal ''
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'must raise when instantiating with an invalid keypair' do
|
39
39
|
secret_key, public_key = self.keypair
|
40
40
|
|
41
|
-
lambda { self.klass.new(secret_key.
|
41
|
+
lambda { self.klass.new(secret_key.to_s[0..-2], public_key) }.
|
42
42
|
must_raise Sodium::LengthError
|
43
43
|
|
44
|
-
lambda { self.klass.new(secret_key, public_key.
|
44
|
+
lambda { self.klass.new(secret_key, public_key.to_s[0..-2]) }.
|
45
45
|
must_raise Sodium::LengthError
|
46
46
|
end
|
47
47
|
|
48
48
|
it 'must raise when receiving an invalid nonce' do
|
49
|
-
lambda { self.subject.box('message', self.subject.nonce.
|
49
|
+
lambda { self.subject.box('message', self.subject.nonce.to_s[0..-2]) }.
|
50
50
|
must_raise Sodium::LengthError
|
51
51
|
end
|
52
52
|
|
data/test/sodium/buffer_test.rb
CHANGED
@@ -3,29 +3,35 @@ require 'test_helper'
|
|
3
3
|
describe Sodium::Buffer do
|
4
4
|
subject { Sodium::Buffer }
|
5
5
|
|
6
|
+
def trigger_gc!
|
7
|
+
GC.start
|
8
|
+
1_000_000.times { Object.new }
|
9
|
+
GC.start
|
10
|
+
end
|
11
|
+
|
6
12
|
it '::key must securely generate random keys of specified length' do
|
7
13
|
Sodium::Random.stub(:bytes, lambda {|l| ' ' * l }) do
|
8
|
-
subject.key( 7).
|
9
|
-
subject.key( 8).
|
10
|
-
subject.key(16).
|
11
|
-
subject.key(32).
|
12
|
-
subject.key(64).
|
14
|
+
subject.key( 7).to_s.must_equal(' ' * 7)
|
15
|
+
subject.key( 8).to_s.must_equal(' ' * 8)
|
16
|
+
subject.key(16).to_s.must_equal(' ' * 16)
|
17
|
+
subject.key(32).to_s.must_equal(' ' * 32)
|
18
|
+
subject.key(64).to_s.must_equal(' ' * 64)
|
13
19
|
end
|
14
20
|
end
|
15
21
|
|
16
22
|
it '::nonce must securely generate random nonces of specified length' do
|
17
23
|
Sodium::Random.stub(:bytes, lambda {|l| ' ' * l }) do
|
18
|
-
subject.nonce( 7).
|
19
|
-
subject.nonce( 8).
|
20
|
-
subject.nonce(16).
|
21
|
-
subject.nonce(32).
|
22
|
-
subject.nonce(64).
|
24
|
+
subject.nonce( 7).to_s.must_equal(' ' * 7)
|
25
|
+
subject.nonce( 8).to_s.must_equal(' ' * 8)
|
26
|
+
subject.nonce(16).to_s.must_equal(' ' * 16)
|
27
|
+
subject.nonce(32).to_s.must_equal(' ' * 32)
|
28
|
+
subject.nonce(64).to_s.must_equal(' ' * 64)
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
26
32
|
it '::empty must generate an empty buffer of specified length' do
|
27
|
-
subject.empty(32).
|
28
|
-
subject.empty(40).
|
33
|
+
subject.empty(32).to_s.must_equal("\0" * 32)
|
34
|
+
subject.empty(40).to_s.must_equal("\0" * 40)
|
29
35
|
end
|
30
36
|
|
31
37
|
it '::empty must yield to a block when given' do
|
@@ -38,43 +44,44 @@ describe Sodium::Buffer do
|
|
38
44
|
end
|
39
45
|
|
40
46
|
it '::ljust must pad zero bytes on the end' do
|
41
|
-
subject.ljust('xyz', 5).
|
47
|
+
subject.ljust('xyz', 5).to_s.must_equal "xyz\0\0"
|
42
48
|
end
|
43
49
|
|
44
50
|
it '::ljust must not pad bytes when not needed' do
|
45
|
-
subject.ljust('xyz', 2).
|
51
|
+
subject.ljust('xyz', 2).to_s.must_equal 'xyz'
|
46
52
|
end
|
47
53
|
|
48
54
|
it '::rjust must pad zero bytes onto the front' do
|
49
|
-
subject.rjust('xyz', 5).
|
55
|
+
subject.rjust('xyz', 5).to_s.must_equal "\0\0xyz"
|
50
56
|
end
|
51
57
|
|
52
58
|
it '::rjust must not pad bytes when not needed' do
|
53
|
-
subject.rjust('xyz', 2).
|
59
|
+
subject.rjust('xyz', 2).to_s.must_equal 'xyz'
|
54
60
|
end
|
55
61
|
|
56
62
|
it '::lpad must prepend the required number of bytes' do
|
57
|
-
subject.lpad('xyz', 0).
|
58
|
-
subject.lpad('xyz', 2).
|
63
|
+
subject.lpad('xyz', 0).to_s.must_equal 'xyz'
|
64
|
+
subject.lpad('xyz', 2).to_s.must_equal "\0\0xyz"
|
59
65
|
end
|
60
66
|
|
61
67
|
it '::rpad must append the required number of bytes' do
|
62
|
-
subject.rpad('xyz', 0).
|
63
|
-
subject.rpad('xyz', 2).
|
68
|
+
subject.rpad('xyz', 0).to_s.must_equal 'xyz'
|
69
|
+
subject.rpad('xyz', 2).to_s.must_equal "xyz\0\0"
|
64
70
|
end
|
65
71
|
|
66
72
|
it '::new must create a buffer containing the specified string' do
|
67
|
-
subject.new('xyz' ).
|
68
|
-
subject.new('xyz' * 50).
|
73
|
+
subject.new('xyz' ).to_s.must_equal('xyz')
|
74
|
+
subject.new('xyz' * 50).to_s.must_equal('xyz' * 50)
|
69
75
|
end
|
70
76
|
|
71
77
|
it '::new must do optional length checking' do
|
72
|
-
lambda { subject.new('xyz', 4).
|
78
|
+
lambda { subject.new('xyz', 4).to_s }.
|
73
79
|
must_raise Sodium::LengthError
|
74
80
|
end
|
75
81
|
|
76
82
|
it '#initialize must freeze its bytes' do
|
77
|
-
subject.new('s').
|
83
|
+
subject.new('s').to_ptr.must_be :frozen?
|
84
|
+
subject.new('s').to_s .must_be :frozen?
|
78
85
|
end
|
79
86
|
|
80
87
|
it '#initialize must wipe the memory from the original string' do
|
@@ -87,27 +94,27 @@ describe Sodium::Buffer do
|
|
87
94
|
it '#initialize must prevent the string from being paged to disk'
|
88
95
|
|
89
96
|
it '#== must compare equality of two buffers' do
|
90
|
-
subject.new('xyz')
|
91
|
-
subject.new('xyz')
|
92
|
-
subject.new('xyz')
|
93
|
-
subject.new('xyz')
|
97
|
+
subject.new('xyz').must_be :==, 'xyz'
|
98
|
+
subject.new('xyz').wont_be :==, 'xy'
|
99
|
+
subject.new('xyz').wont_be :==, 'xyzz'
|
100
|
+
subject.new('xyz').wont_be :==, 'abc'
|
94
101
|
end
|
95
102
|
|
96
103
|
it '#== must compare equality of two buffers in constant time'
|
97
104
|
|
98
105
|
it '#+ must append two buffers' do
|
99
|
-
subject.new('xyz').+('abc').
|
106
|
+
subject.new('xyz').+('abc').to_s.must_equal 'xyzabc'
|
100
107
|
end
|
101
108
|
|
102
109
|
it '#^ must XOR two buffers' do
|
103
|
-
subject.new('xyz').^('xyz').
|
104
|
-
subject.new('xyz').^('xyz').
|
110
|
+
subject.new('xyz').^('xyz').to_s.must_equal "\0\0\0"
|
111
|
+
subject.new('xyz').^('xyz').to_s.must_equal "\0\0\0"
|
105
112
|
end
|
106
113
|
|
107
114
|
it '#[]= must allow replacement of byte ranges' do
|
108
|
-
subject.new('xyz').tap {|b| b[0, 3] = 'abc' }.
|
109
|
-
subject.new('xyz').tap {|b| b[0, 2] = 'ab' }.
|
110
|
-
subject.new('xyz').tap {|b| b[2, 1] = 'c' }.
|
115
|
+
subject.new('xyz').tap {|b| b[0, 3] = 'abc' }.to_s.must_equal 'abc'
|
116
|
+
subject.new('xyz').tap {|b| b[0, 2] = 'ab' }.to_s.must_equal 'abz'
|
117
|
+
subject.new('xyz').tap {|b| b[2, 1] = 'c' }.to_s.must_equal 'xyc'
|
111
118
|
end
|
112
119
|
|
113
120
|
it '#[]= must not allow resizing the buffer' do
|
@@ -117,61 +124,61 @@ describe Sodium::Buffer do
|
|
117
124
|
lambda { subject.new('xyz')[2, 2] = 'ab' }.must_raise ArgumentError
|
118
125
|
end
|
119
126
|
|
120
|
-
it '#[] must accept an indivdual byte offset to return' do
|
121
|
-
subject.new('xyz').tap do |buffer|
|
122
|
-
buffer[-4].to_str.must_equal ''
|
123
|
-
buffer[-3].to_str.must_equal 'x'
|
124
|
-
buffer[-2].to_str.must_equal 'y'
|
125
|
-
buffer[-1].to_str.must_equal 'z'
|
126
|
-
buffer[ 0].to_str.must_equal 'x'
|
127
|
-
buffer[ 1].to_str.must_equal 'y'
|
128
|
-
buffer[ 2].to_str.must_equal 'z'
|
129
|
-
buffer[ 3].to_str.must_equal ''
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
it '#[] must accept ranges of bytes to return' do
|
134
|
-
subject.new('xyz').tap do |buffer|
|
135
|
-
buffer[ 0.. 0].to_str.must_equal 'x'
|
136
|
-
buffer[ 0.. 1].to_str.must_equal 'xy'
|
137
|
-
buffer[ 0.. 2].to_str.must_equal 'xyz'
|
138
|
-
buffer[ 0.. 3].to_str.must_equal 'xyz'
|
139
|
-
buffer[ 1..-1].to_str.must_equal 'yz'
|
140
|
-
buffer[ 2..-2].to_str.must_equal ''
|
141
|
-
buffer[-3..-1].to_str.must_equal 'xyz'
|
142
|
-
buffer[-4.. 1].to_str.must_equal ''
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
127
|
it '#[] must accept an offset and number of bytes to return' do
|
147
128
|
subject.new('xyz').tap do |buffer|
|
148
|
-
buffer[ 0, 0].
|
149
|
-
buffer[ 0, 1].
|
150
|
-
buffer[ 0, 3].
|
151
|
-
buffer[ 2,
|
152
|
-
buffer[ 2, 1].to_str.must_equal 'z'
|
153
|
-
buffer[-2, 1].to_str.must_equal 'y'
|
154
|
-
buffer[ 0, -1].to_str.must_equal ''
|
129
|
+
buffer[ 0, 0].to_s.must_equal ''
|
130
|
+
buffer[ 0, 1].to_s.must_equal 'x'
|
131
|
+
buffer[ 0, 3].to_s.must_equal 'xyz'
|
132
|
+
buffer[ 2, 1].to_s.must_equal 'z'
|
155
133
|
end
|
156
134
|
end
|
157
135
|
|
158
|
-
it '#
|
136
|
+
it '#bytesize must return its length' do
|
159
137
|
subject.new('testing').bytesize.must_equal 7
|
160
138
|
end
|
161
139
|
|
162
140
|
it '#ldrop must drop bytes off the left' do
|
163
|
-
subject.new('xyz').ldrop(2).
|
141
|
+
subject.new('xyz').ldrop(2).to_s.must_equal('z')
|
164
142
|
end
|
165
143
|
|
166
144
|
it '#rdrop must drop bytes off the right' do
|
167
|
-
subject.new('xyz').rdrop(2).
|
145
|
+
subject.new('xyz').rdrop(2).to_s.must_equal('x')
|
168
146
|
end
|
169
147
|
|
170
148
|
it '#inspect must not reveal its instance variables' do
|
171
149
|
subject.new('blah').inspect.wont_include 'blah'
|
172
150
|
end
|
173
151
|
|
174
|
-
it '#
|
175
|
-
subject.new('xyz').
|
152
|
+
it '#to_s must return its internal bytes' do
|
153
|
+
subject.new('xyz').to_s.must_equal('xyz')
|
154
|
+
end
|
155
|
+
|
156
|
+
it '#to_ptr must return the live pointer to its data' do
|
157
|
+
subject.new('xyz').to_ptr.read_bytes(3).must_equal('xyz')
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
it 'must wipe its contents when garbage collected' do
|
162
|
+
address = lambda { Sodium::Buffer.new('xyz').to_ptr.address }
|
163
|
+
pointer = FFI::Pointer.new(address.call)
|
164
|
+
|
165
|
+
trigger_gc!
|
166
|
+
|
167
|
+
pointer.read_bytes(3).wont_equal('xyz')
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'must free its contents when garbage collected' do
|
171
|
+
flag = MiniTest::Mock.new
|
172
|
+
free = lambda {|pointer| flag.called(pointer) }
|
173
|
+
flag.expect :called, nil, [ FFI::Pointer ]
|
174
|
+
|
175
|
+
Sodium::FFI::LibC.stub(:free, free) do
|
176
|
+
Sodium::Buffer.new('xyz')
|
177
|
+
|
178
|
+
trigger_gc!
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
flag.verify
|
176
183
|
end
|
177
184
|
end
|