pants 0.1.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.
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ require 'pants/readers/file_reader'
3
+
4
+
5
+ describe Pants::Readers::FileReader do
6
+ let(:core_stopper_callback) do
7
+ double "EventMachine.Callback", call: true
8
+ end
9
+
10
+ let(:tick_loop) do
11
+ tl = double "EventMachine::TickLoop"
12
+ tl.stub(:on_stop)
13
+
14
+ tl
15
+ end
16
+
17
+ before do
18
+ EventMachine.stub(:tick_loop).and_return(tick_loop)
19
+ EventMachine::Iterator.stub_chain(:new, :each)
20
+ end
21
+
22
+ subject do
23
+ Pants::Readers::FileReader.new('some file', core_stopper_callback)
24
+ end
25
+
26
+ describe "#start" do
27
+ let(:file) { double "File" }
28
+ let(:starter) { double "EventMachine::Callback starter" }
29
+ let(:stopper) { double "EventMachine::Callback stopper" }
30
+
31
+ before do
32
+ File.should_receive(:open).and_return(file)
33
+ subject.should_receive(:starter).and_return(starter)
34
+ subject.should_receive(:stopper).and_return(stopper)
35
+ end
36
+
37
+ it "defines an EventMachine Callback" do
38
+ EventMachine.should_receive(:Callback).times.and_yield.and_call_original
39
+
40
+ EventMachine.should_receive(:attach) do |arg1, arg2, arg3, arg4, arg5|
41
+ arg1.should == file
42
+ arg2.should == Pants::Readers::FileReaderConnection
43
+ arg3.should be_a EventMachine::Channel
44
+ arg4.should == starter
45
+ arg5.should == stopper
46
+ end
47
+
48
+ subject.start
49
+ end
50
+ end
51
+ end
52
+
53
+ describe Pants::Readers::FileReaderConnection do
54
+ let(:channel) { double "EventMachine::Channel" }
55
+ let(:starter) { double "EventMachine::Callback starter" }
56
+ let(:stopper) { double "EventMachine::Callback stopper" }
57
+
58
+ subject do
59
+ Pants::Readers::FileReaderConnection.new(1, channel, starter, stopper)
60
+ end
61
+
62
+ describe "#post_init" do
63
+ let(:starter) { double "EventMachine::Callback" }
64
+
65
+ it "tells the starter that it's started" do
66
+ starter.should_receive(:call)
67
+ subject
68
+ end
69
+ end
70
+
71
+ describe "#receive_data" do
72
+ let(:data) { "some data" }
73
+
74
+ before do
75
+ Pants::Readers::FileReaderConnection.any_instance.stub(:post_init)
76
+ end
77
+
78
+ it "directly writes it to the channel" do
79
+ channel.should_receive(:<<).with(data)
80
+ subject.receive_data(data)
81
+ end
82
+ end
83
+
84
+ describe "#unbind" do
85
+ before do
86
+ Pants::Readers::FileReaderConnection.any_instance.stub(:post_init)
87
+ end
88
+
89
+ it "tells the stopper that it's stopped" do
90
+ stopper.should_receive(:call)
91
+ subject.unbind
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+ require 'pants/version'
3
+
4
+
5
+ describe Pants do
6
+ specify { Pants::VERSION.should == '0.1.0' }
7
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ require 'pants/writers/base_writer'
3
+
4
+
5
+ describe Pants::Writers::BaseWriter do
6
+ let(:channel) { double "EventMachine::Channel" }
7
+
8
+ subject do
9
+ Pants::Writers::BaseWriter.new(channel)
10
+ end
11
+
12
+ describe "#starter" do
13
+ context "@starter not yet defined" do
14
+ it "creates a new deferrable that sets @running to true" do
15
+ subject.should_not be_running
16
+ subject.starter.call
17
+ subject.should be_running
18
+ end
19
+ end
20
+ end
21
+
22
+ describe "#stopper" do
23
+ context "@stopper not yet defined and @running is true" do
24
+ before do
25
+ subject.instance_variable_set(:@running, true)
26
+ end
27
+
28
+ it "creates a new deferrable that sets @running to false" do
29
+ subject.should be_running
30
+ subject.stopper.call
31
+ subject.should_not be_running
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+ require 'pants/writers/file_writer'
3
+
4
+
5
+ describe Pants::Writers::FileWriter do
6
+ let(:channel) { EventMachine::Channel.new }
7
+
8
+ subject do
9
+ Pants::Writers::FileWriter.new(file, channel)
10
+ end
11
+
12
+ describe "#stop" do
13
+ let(:file) do
14
+ c = double "File"
15
+ c.should_receive(:closed?).and_return(false)
16
+ c.should_receive(:close)
17
+
18
+ c
19
+ end
20
+
21
+ let(:stopper) do
22
+ s = double "EventMachine::Callback"
23
+ s.should_receive(:call)
24
+
25
+ s
26
+ end
27
+
28
+ before do
29
+ File.stub(:open)
30
+ subject.instance_variable_set(:@file, file)
31
+ end
32
+
33
+ it "closes the file and calls succeed on the stopper" do
34
+ subject.should_receive(:stopper).and_return(stopper)
35
+ subject.stop
36
+ end
37
+ end
38
+
39
+ describe "#start" do
40
+ let(:data) do
41
+ '0' * 100
42
+ end
43
+
44
+ let(:file) do
45
+ f = double "File"
46
+ f.should_receive(:write_nonblock).once.with(data).and_return(data.size)
47
+ f.should_receive(:closed?).and_return(true)
48
+
49
+ f
50
+ end
51
+
52
+ let(:tick_loop) do
53
+ t = double "EventMachine::TickLoop"
54
+ t.should_receive(:on_stop).and_yield
55
+
56
+ t
57
+ end
58
+
59
+ before do
60
+ File.should_receive(:open).and_return(file)
61
+ end
62
+
63
+ it "subscribes to the channel and writes data as it comes in" do
64
+ EM.should_receive(:defer).and_yield
65
+ channel.should_receive(:subscribe).and_yield(data).and_call_original
66
+ EventMachine.should_receive(:tick_loop).and_yield.and_return(tick_loop)
67
+
68
+ subject.start
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+ require 'pants/writers/udp_writer'
3
+
4
+
5
+ describe Pants::Writers::UDPWriter do
6
+ let(:channel) { double "EventMachine::Channel" }
7
+ let(:ip) { '127.0.0.1' }
8
+ let(:port) { 1234 }
9
+ before { subject.stub(:log) }
10
+
11
+ subject do
12
+ Pants::Writers::UDPWriter.new(ip, port, channel)
13
+ end
14
+
15
+ describe "#start" do
16
+ let(:starter) do
17
+ s = double "EventMachine::Callback"
18
+ s.should_receive(:call)
19
+
20
+ s
21
+ end
22
+
23
+ let(:tick_loop) do
24
+ t = double "EventMachine::TickLoop"
25
+ t.should_receive(:on_stop).and_yield
26
+
27
+ t
28
+ end
29
+
30
+ before do
31
+ subject.stub(:starter).and_return(starter)
32
+ end
33
+
34
+ it "opens a datagram socket on 0.0.0.0 then calls succeed on the starter" do
35
+ EventMachine.should_receive(:defer).and_yield
36
+ EventMachine.should_receive(:open_datagram_socket).with(
37
+ '0.0.0.0', 0, Pants::Writers::UDPWriterConnection, channel, ip, port
38
+ ).and_return(true)
39
+ EventMachine.should_receive(:tick_loop).and_yield.and_return(tick_loop)
40
+
41
+ subject.start
42
+ end
43
+ end
44
+
45
+ describe "#stop" do
46
+ let(:connection) do
47
+ c = double "EventMachine::Connection"
48
+ c.should_receive(:close_connection_after_writing)
49
+
50
+ c
51
+ end
52
+
53
+ let(:stopper) do
54
+ s = double "EventMachine::Callback"
55
+ s.should_receive(:call)
56
+
57
+ s
58
+ end
59
+
60
+ before do
61
+ subject.instance_variable_set(:@connection, connection)
62
+ subject.stub(:stopper).and_return(stopper)
63
+ end
64
+
65
+ it "closes the socket and calls succeed on the stopper" do
66
+ subject.stop
67
+ end
68
+ end
69
+ end
70
+
71
+ describe Pants::Writers::UDPWriterConnection do
72
+ let(:channel) { EventMachine::Channel.new }
73
+ let(:port) { 1234 }
74
+ let(:ip) { '127.0.0.1' }
75
+
76
+ subject do
77
+ Pants::Writers::UDPWriterConnection.new(1, channel, ip, port)
78
+ end
79
+
80
+ describe "#initialize" do
81
+ before do
82
+ Pants::Writers::UDPWriterConnection.any_instance.stub(:post_init)
83
+ end
84
+
85
+ context "multicast IP address" do
86
+ let(:ip) { '224.0.0.1' }
87
+
88
+ it "sets up the socket to do multicast" do
89
+ Pants::Writers::UDPWriterConnection.any_instance.
90
+ should_receive(:setup_multicast_socket).with(ip)
91
+
92
+ Pants::Writers::UDPWriterConnection.new(0, channel, ip, port)
93
+ end
94
+ end
95
+
96
+ context "unicast IP address" do
97
+ let(:ip) { '223.0.0.1' }
98
+
99
+ it "does not set up the socket to do multicast" do
100
+ Pants::Writers::UDPWriterConnection.any_instance.
101
+ should_not_receive(:setup_multicast_socket)
102
+
103
+ Pants::Writers::UDPWriterConnection.new(0, channel, ip, port)
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "#post_init" do
109
+ around(:each) do |example|
110
+ EM.run do
111
+ example.run
112
+ EM.stop
113
+ end
114
+ end
115
+
116
+ before do
117
+ channel.should_receive(:subscribe).and_yield(data).and_call_original
118
+ end
119
+
120
+ context "data is bigger than PACKET_SPLIT_THRESHOLD" do
121
+ let(:data) do
122
+ "0" * Pants::Writers::UDPWriterConnection::PACKET_SPLIT_THRESHOLD * split_count
123
+ end
124
+
125
+ let(:split_count) { 3 }
126
+
127
+ it "splits the data by PACKET_SPLIT_SIZE and sends each chunk" do
128
+ subject.should_receive(:send_datagram).exactly(split_count + 1).times
129
+ channel << data
130
+ subject
131
+ end
132
+ end
133
+
134
+ context "data is smaller than PACKET_SPLIT_THRESHOLD" do
135
+ let(:data) do
136
+ "0" * 100
137
+ end
138
+
139
+ it "sends the data as it is" do
140
+ subject.should_receive(:send_datagram).once.with(data, ip, port)
141
+ channel << data
142
+ subject
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require "pants"
3
+
4
+
5
+ describe Pants do
6
+ end
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'thor'
4
+ require 'benchmark'
5
+ require './lib/pants'
6
+ require 'bundler/setup'
7
+
8
+
9
+ class Pantsmark < Thor
10
+ desc "file_copy [FILE]", "Copies [FILE] --times number of times and benchmarks it"
11
+ method_option :times, type: :numeric, :default => 100
12
+ def file_copy(file_path)
13
+ Benchmark.bm do |x|
14
+ Pants.log = false
15
+
16
+ x.report("\tpants:") do
17
+ Pants.read(file_path) do |tee|
18
+ options[:times].times do |i|
19
+ tee.write_to("pants_test#{i}")
20
+ end
21
+ end
22
+ end
23
+
24
+ options[:times].times do |i|
25
+ result = %x[diff "#{file_path}" pants_test#{i}]
26
+ puts "Diff result: #{result}" unless result.empty?
27
+ end
28
+
29
+ x.report(" FileUtils.cp:") do
30
+ threads = []
31
+
32
+ options[:times].times do |i|
33
+ threads << Thread.new do
34
+ FileUtils.cp('pants_test1', "fu_cp_test#{i}")
35
+ end
36
+
37
+ threads.last.join
38
+ end
39
+ end
40
+
41
+ x.report(" cp:") do
42
+ threads = []
43
+
44
+ options[:times].times do |i|
45
+ threads << Thread.new do
46
+ `cp pants_test1 cp_test#{i}`
47
+ end
48
+
49
+ threads.last.join
50
+ end
51
+ end
52
+ end
53
+ rescue
54
+ FileUtils.rm_rf(Dir["./pants_test*"])
55
+ FileUtils.rm_rf(Dir["./fu_cp_test*"])
56
+ FileUtils.rm_rf(Dir["./cp_test*"])
57
+
58
+ raise
59
+ ensure
60
+ FileUtils.rm_rf(Dir["./pants_test*"])
61
+ FileUtils.rm_rf(Dir["./fu_cp_test*"])
62
+ FileUtils.rm_rf(Dir["./cp_test*"])
63
+ end
64
+ end
65
+
66
+ Pantsmark.start
@@ -0,0 +1,43 @@
1
+ require_relative './lib/pants'
2
+
3
+
4
+ Pants.log = true
5
+
6
+ #EM.threadpool_size = 200
7
+ #EM.kqueue
8
+ #EM.epoll
9
+
10
+ orig_file = 'spec/support/pants.wav'
11
+ dest_file = 'dest_test_file'
12
+ #Pants.read('udp://127.0.0.1:1234') do |reader|
13
+ Pants.read(orig_file) do |reader|
14
+ 10.times do |i|
15
+ reader.add_writer(dest_file)
16
+ reader.add_writer("udp://127.0.0.1:#{1235 + i}")
17
+ end
18
+ reader.add_writer('udp://10.221.222.90:9000')
19
+ end
20
+
21
+ if defined? orig_file
22
+ pants_file_size = File.stat(dest_file).size
23
+ orig_file_size = File.stat(orig_file).size
24
+ puts "Pants file size: #{pants_file_size}"
25
+ puts "Original file size: #{orig_file_size}"
26
+ puts "Difference: #{orig_file_size - pants_file_size}"
27
+ end
28
+
29
+ #==============
30
+ core = Pants::Core.new
31
+ udp_reader = core.read 'udp://127.0.0.1:1234'
32
+ udp_reader.write_to 'udp://127.0.0.1:1235'
33
+
34
+ udp_reader2 = core.add_reader(Pants::Readers::UDPReader, '127.0.0.1', 1234)
35
+ udp_reader2.add_writer(Pants::Writers::UDPWriter, '127.0.0.1', 1235)
36
+
37
+ udp_reader3 = Pants::Readers::UDPReader.new('127.0.0.1', 1234, core.callback)
38
+ udp_writer3 = Pants::Writers::UDPWriter.new('127.0.0.1', 1235, udp_reader3.write_to_channel)
39
+ core.add_reader(udp_reader3)
40
+ udp_reader3.add_writer(udp_writer3)
41
+
42
+ seam = udp_reader.add_seam(Pants::SimpleSeam)
43
+ seam.write_to 'my_file'