require 'spec_helper' require 'masscan/command' describe Masscan::Command do describe described_class::Port do describe "#validate" do context "when given an Integer" do let(:value) { 443 } it "must return true" do expect(subject.validate(value)).to be(true) end context "but it's less than 1" do let(:value) { 0 } it "must return [false, \"(...) not within the range of acceptable values (1..65535)\"]" do expect(subject.validate(value)).to eq( [false, "(#{value.inspect}) not within the range of acceptable values (1..65535)"] ) end end context "but it's greater than 65535" do let(:value) { 65536 } it "must return [false, \"(...) not within the range of acceptable values (1..65535)\"]" do expect(subject.validate(value)).to eq( [false, "(#{value.inspect}) not within the range of acceptable values (1..65535)"] ) end end end context "when given a String" do context "and it's a number" do let(:value) { '443' } it "must return true" do expect(subject.validate(value)).to be(true) end context "but it's less than 1" do let(:value) { '0' } it "must return [false, \"must be a valid port number (...)\"]" do expect(subject.validate(value)).to eq( [false, "must be a valid port number (#{value.inspect})"] ) end end context "but it's greater than 65535" do let(:value) { '65536' } it "must return [false, \"must be a valid port number (...)\"]" do expect(subject.validate(value)).to eq( [false, "must be a valid port number (#{value.inspect})"] ) end end end context "but it contains numbers" do let(:value) { "foo" } it "must return [false, \"must be a valid port number (...)\"]" do expect(subject.validate(value)).to eq( [false, "must be a valid port number (#{value.inspect})"] ) end end end end end describe described_class::PortRange do describe "#validate" do context "when given an Integer value" do let(:value) { 443 } it "must return true" do expect(subject.validate(value)).to be(true) end context "but it's less than 1" do let(:value) { 0 } it "must return [false, \"(...) not within the range of acceptable values (1..65535)\"]" do expect(subject.validate(value)).to eq( [false, "(#{value.inspect}) not within the range of acceptable values (1..65535)"] ) end end context "but it's greater than 65535" do let(:value) { 65536 } it "must return [false, \"(...) not within the range of acceptable values (1..65535)\"]" do expect(subject.validate(value)).to eq( [false, "(#{value.inspect}) not within the range of acceptable values (1..65535)"] ) end end end context "when given a String value" do let(:value) { '443' } it "must return true" do expect(subject.validate(value)).to be(true) end context "but it's less than 1" do let(:value) { '0' } it "must return [false, \"must be a valid port range or port number (...)\"]" do expect(subject.validate(value)).to eq( [false, "must be a valid port range or port number (#{value.inspect})"] ) end end context "but it's greater than 65535" do let(:value) { '65536' } it "must return [false, \"must be a valid port range or port number (...)\"]" do expect(subject.validate(value)).to eq( [false, "must be a valid port range or port number (#{value.inspect})"] ) end end end context "when given a Range of port numbers" do let(:value) { (1..1024) } it "must return true" do expect(subject.validate(value)).to be(true) end end end describe "#format" do context "when given a single port number" do let(:value) { 443 } it "must return the formatted port number" do expect(subject.format(value)).to eq(value.to_s) end end context "when given a Range of port numbers" do let(:value) { 1..1024 } it "must return the formatted port number range (ex: 1-102)" do expect(subject.format(value)).to eq("#{value.begin}-#{value.end}") end end end end describe described_class::PortList do describe "#validate" do context "when given a single port number" do let(:value) { 443 } it "must return true" do expect(subject.validate(value)).to be(true) end end context "when given a Range of port numbers" do let(:value) { (1..1024) } it "must return true" do expect(subject.validate(value)).to be(true) end end context "when given an Array of port numbers" do let(:value) { [80, 443] } it "must return true" do expect(subject.validate(value)).to be(true) end context "and the Array contains Ranges" do let(:value) { [80, (1..42), 443] } it "must return true" do expect(subject.validate(value)).to be(true) end end end context "when given a String" do context "and it contains a single number" do let(:value) { "443" } it "must return true" do expect(subject.validate(value)).to be(true) end context "and it's prefixed by 'U:'" do let(:value) { "U:#{super()}" } it "must return true" do expect(subject.validate(value)).to be(true) end end end context "and it contains a range of ports" do let(:value) { "1-1024" } it "must return true" do expect(subject.validate(value)).to be(true) end context "and it's prefixed by 'U:'" do let(:value) { "U:#{super()}" } it "must return true" do expect(subject.validate(value)).to be(true) end end end context "and it contains a comma separated list of port numbers" do let(:value) { "80,443" } it "must return true" do expect(subject.validate(value)).to be(true) end context "and it's prefixed by 'U:'" do let(:value) { "U:#{super()}" } it "must return true" do expect(subject.validate(value)).to be(true) end end end context "and it contains a comma separated list of port ranges" do let(:value) { "1-42,80-8080" } it "must return true" do expect(subject.validate(value)).to be(true) end context "and it's prefixed by 'U:'" do let(:value) { "U:#{super()}" } it "must return true" do expect(subject.validate(value)).to be(true) end end end context "and it contains a comma separated list of port numbers and ranges" do let(:value) { "1-42,50,60,70,80-8080,9000" } it "must return true" do expect(subject.validate(value)).to be(true) end context "and it's prefixed by 'U:'" do let(:value) { "U:#{super()}" } it "must return true" do expect(subject.validate(value)).to be(true) end end end context "when it contains non-digits" do let(:value) { "1,2,3,4,a,b,c" } it "must return false and a validation error message" do expect(subject.validate(value)).to eq( [false, "not a valid port list (#{value.inspect})"] ) end end context "when it contains whitespace" do let(:value) { "1,2, 3,4" } it "must return false and a validation error message" do expect(subject.validate(value)).to eq( [false, "not a valid port list (#{value.inspect})"] ) end end context "when it contains new-lines" do let(:value) { "1,2,\n3,4" } it "must return false and a validation error message" do expect(subject.validate(value)).to eq( [false, "not a valid port list (#{value.inspect})"] ) end end end end describe "#format" do context "when given a single port number" do let(:value) { 443 } it "must return the formatted port number" do expect(subject.format(value)).to eq(value.to_s) end end context "when given a Range of port numbers" do let(:value) { (1..1024) } it "must return the formatted port number range (ex: 1-102)" do expect(subject.format(value)).to eq("#{value.begin}-#{value.end}") end end context "when given an Array of port numbers" do let(:value) { [80, 443] } it "must return the formatted list of port numbers" do expect(subject.format(value)).to eq(value.join(',')) end context "and the Array contains Ranges" do let(:value) { [80, (1..42), 443] } it "must return the formatted list of port numbers and port ranges" do expect(subject.format(value)).to eq("#{value[0]},#{value[1].begin}-#{value[1].end},#{value[2]}") end end end context "when given a String" do let(:value) { "22,25,80,443" } it "must return the String" do expect(subject.format(value)).to eq(value) end end end end describe described_class::Shards do describe "#validate" do context "when given a Rational value" do let(:value) { (1/2r) } it "must return true" do expect(subject.validate(value)).to be(true) end end context "when given an Array value" do let(:value) { [1, 2] } it "must return true" do expect(subject.validate(value)).to be(true) end context "but the Array length is 1" do let(:value) { [1] } it "must return a validation error" do expect(subject.validate(value)).to eq( [false, "must contain two elements (#{value.inspect})"] ) end end context "but the Array length is > 2" do let(:value) { [1,2,3] } it "must return a validation error" do expect(subject.validate(value)).to eq( [false, "must contain two elements (#{value.inspect})"] ) end end end context "when given a String" do context "and it matches X/Y" do let(:value) { "1/2" } it "must return true" do expect(subject.validate(value)).to be(true) end end context "but it does not match X/Y" do let(:value) { "1" } it "must return a validation error" do expect(subject.validate(value)).to eq( [false, "invalid shards value (#{value.inspect})"] ) end end end context "otherwise" do let(:value) { :"1/2" } it "must return true" do expect(subject.validate(value)).to be(true) end end end describe "#format" do context "when given a Rational value" do let(:value) { (1/2r) } it "must format it into \#{numerator}/\#{denominator}" do expect(subject.format(value)).to eq( "#{value.numerator}/#{value.denominator}" ) end end context "when given an Array value" do let(:value) { [1, 2] } it "must format it into \#{array[0]}/\#{array[1]}" do expect(subject.format(value)).to eq( "#{value[0]}/#{value[1]}" ) end end context "otherwise" do let(:value) { :"1/2" } it "must convert the value to a String" do expect(subject.format(value)).to eq(value.to_s) end end end end describe described_class::RotateTime do describe "#validate" do context "when given an Integer" do let(:value) { 42 } it "must return true" do expect(subject.validate(value)).to be(true) end end context "when given a String" do context "but the String is a number" do let(:value) { '42' } it "must return true" do expect(subject.validate(value)).to be(true) end end context "but the String is 'hourly'" do let(:value) { 'hourly' } it "must return true" do expect(subject.validate(value)).to be(true) end end context "but the String is '<N>hours'" do let(:value) { '2hours' } it "must return true" do expect(subject.validate(value)).to be(true) end end context "but the String is '<N>min'" do let(:value) { '10min' } it "must return true" do expect(subject.validate(value)).to be(true) end end context "but the String is not a number" do let(:value) { "abc" } it "must return a validation error" do expect(subject.validate(value)).to eq([false, "invalid rotation time (#{value.inspect})"]) end end context "but the String contains a new-line" do let(:value) { "10\nfoo" } it "must return a validation error" do expect(subject.validate(value)).to eq([false, "invalid rotation time (#{value.inspect})"]) end end end end end describe described_class::MACAddress do describe "#validate" do context "when given a String" do context "and it's a valid MAC address" do let(:value) { "00:11:22:33:44:55" } it "must return true" do expect(subject.validate(value)).to be(true) end end context "but an octent contains less than two hex digits" do let(:value) { "0:11:22:33:44" } it "must return [false, \"invalid MAC address (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid MAC address (#{value.inspect})"] ) end end context "but an octent contains more than two hex digits" do let(:value) { "000:11:22:33:44" } it "must return [false, \"invalid MAC address (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid MAC address (#{value.inspect})"] ) end end context "but it's contains less than six octets" do let(:value) { "00:11:22:33:44" } it "must return [false, \"invalid MAC address (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid MAC address (#{value.inspect})"] ) end end context "but it's contains more than six octets" do let(:value) { "00:11:22:33:44:55:66" } it "must return [false, \"invalid MAC address (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid MAC address (#{value.inspect})"] ) end end context "but it contains non-hex characters" do let(:value) { "000:11:22:33:44:xx" } it "must return [false, \"invalid MAC address (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid MAC address (#{value.inspect})"] ) end end context "but it is not separated by ':' characters" do let(:value) { "00.11.22.33.44.55" } it "must return [false, \"invalid MAC address (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid MAC address (#{value.inspect})"] ) end end context "but it contains spaces" do let(:value) { "00:11:22: 33:44:55" } it "must return [false, \"invalid MAC address (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid MAC address (#{value.inspect})"] ) end end context "but it contains new-line characters" do let(:value) { "00:11:22:\n33:44:55" } it "must return [false, \"invalid MAC address (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid MAC address (#{value.inspect})"] ) end end end end end describe described_class::Target do describe "#validate" do context "when given an IPAddr object" do let(:value) { IPAddr.new('127.0.0.1') } it "must return true" do expect(subject.validate(value)).to be(true) end end context "when given a String" do context "and it's an IPv4 address" do let(:value) { '127.0.0.1' } it "must return true" do expect(subject.validate(value)).to be(true) end end context "and it's an IPv4 range" do let(:value) { '127.0.0.1/24' } it "must return true" do expect(subject.validate(value)).to be(true) end end context "and it's an IPv6 address" do context "but it's in compressed notation" do let(:value) { '::1' } it "must return true" do expect(subject.validate(value)).to be(true) end end context "and it's in full notation" do let(:value) { '2606:2800:220:1:248:1893:25c8:1946' } it "must return true" do expect(subject.validate(value)).to be(true) end end end context "and it's an IPv6 range" do context "but it's in compressed notation" do let(:value) { '::1/32' } it "must return true" do expect(subject.validate(value)).to be(true) end end context "and it's in full notation" do let(:value) { '2606:2800:220:1:248:1893:25c8:1946/32' } it "must return true" do expect(subject.validate(value)).to be(true) end end end context "but it contains non-hex characters" do let(:value) { '2606:2800:220:1:248:1893:25c8:xxxx/32' } it "must return [false, \"invalid IP or IP range (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid IP or IP range (#{value.inspect})"] ) end end context "but it contains spaces" do let(:value) { '2606:2800:220:1: 248:1893:25c8:1946/32' } it "must return [false, \"invalid IP or IP range (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid IP or IP range (#{value.inspect})"] ) end end context "but it contains new-line characters" do let(:value) { "2606:2800:220:1:\n248:1893:25c8:1946/32" } it "must return [false, \"invalid IP or IP range (...)\"]" do expect(subject.validate(value)).to eq( [false, "invalid IP or IP range (#{value.inspect})"] ) end end end end end end