codesake 0.0.1 → 0.15.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/History.md +40 -0
- data/README.md +25 -3
- data/Rakefile +22 -2
- data/bin/codesake +36 -0
- data/codesake.gemspec +3 -0
- data/features/codesake_complains_if_missing_target.feature +8 -0
- data/features/codesake_process_jsp_file.feature +88 -0
- data/features/codesake_process_text_file.feature +23 -0
- data/features/step_definition/codesake_steps.rb +164 -0
- data/features/support/env.rb +1 -0
- data/lib/codesake.rb +8 -3
- data/lib/codesake/cli.rb +90 -0
- data/lib/codesake/engine/core.rb +10 -0
- data/lib/codesake/engine/generic.rb +12 -0
- data/lib/codesake/engine/jsp.rb +165 -0
- data/lib/codesake/engine/text.rb +36 -0
- data/lib/codesake/kernel.rb +39 -0
- data/lib/codesake/utils/files.rb +25 -0
- data/lib/codesake/utils/secrets.rb +45 -0
- data/lib/codesake/version.rb +2 -1
- data/spec/cli_spec.rb +65 -0
- data/spec/engine_core_spec.rb +45 -0
- data/spec/file_utils_spec.rb +59 -0
- data/spec/jsp_engine_spec.rb +114 -0
- data/spec/kernel_spec.rb +63 -0
- data/spec/secrets_utils_spec.rb +79 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/text_engine_spec.rb +72 -0
- metadata +92 -3
data/lib/codesake/version.rb
CHANGED
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "codesake command line interface" do
|
4
|
+
before(:all) do
|
5
|
+
@cli = Codesake::Cli.new
|
6
|
+
end
|
7
|
+
it "has a parse method" do
|
8
|
+
@cli.should respond_to(:parse)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns an empty has if no command line is given" do
|
12
|
+
@cli.parse(nil).should == {:vulnerabilities=>:all}
|
13
|
+
@cli.parse("").should == {:vulnerabilities=>:all}
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
it "understands --version flag" do
|
18
|
+
@cli.parse("--version").should == {:version=>true, :vulnerabilities=>:all}
|
19
|
+
end
|
20
|
+
it "understands --output flag" do
|
21
|
+
@cli.parse("-o file").should == {:output=>:file, :vulnerabilities=>:all}
|
22
|
+
@cli.parse("-o json").should == {:output=>:json, :vulnerabilities=>:all}
|
23
|
+
@cli.parse("-o db").should == {:output=>:db, :vulnerabilities=>:all}
|
24
|
+
|
25
|
+
end
|
26
|
+
it "understands --verbose flag" do
|
27
|
+
@cli.parse("--verbose").should == {:verbose=>true, :vulnerabilities=>:all}
|
28
|
+
@cli.parse("-V").should == {:verbose=>true, :vulnerabilities=>:all}
|
29
|
+
end
|
30
|
+
|
31
|
+
it "saves targets" do
|
32
|
+
@cli.parse("file1")
|
33
|
+
@cli.targets.should == [{:target=>"file1", :valid=>false}]
|
34
|
+
@cli.parse("file1 file2")
|
35
|
+
@cli.targets.should == [{:target=>"file1", :valid=>false}, {:target=>"file2", :valid=>false}]
|
36
|
+
@cli.parse("Gemfile")
|
37
|
+
@cli.targets.should == [{:target=>"Gemfile", :valid=>true}]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "the target should be either a file or a directory" do
|
41
|
+
@cli.is_good_target?("Gemfile").should be_true
|
42
|
+
@cli.is_good_target?("file1").should be_false
|
43
|
+
end
|
44
|
+
it "must produce a non nil option Hash" do
|
45
|
+
@cli.parse("").should_not be_nil
|
46
|
+
@cli.parse("-nonsense").should_not be_nil
|
47
|
+
@cli.parse("-v -h").should_not be_nil
|
48
|
+
@cli.parse("-j drift").should_not be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it "understand --keys flag" do
|
52
|
+
ret = {:keywords => ["a","b","c"], :vulnerabilities=>:all}
|
53
|
+
@cli.parse("-k a,b,c").should == ret
|
54
|
+
end
|
55
|
+
|
56
|
+
it "understand --all-vulnerabilities" do
|
57
|
+
ret = {:vulnerabilities=>:all}
|
58
|
+
@cli.parse("-A").should == ret
|
59
|
+
end
|
60
|
+
it "understand --confirmed-vulnerabilities" do
|
61
|
+
ret = {:vulnerabilities=>:confirmed}
|
62
|
+
@cli.parse("-C").should == ret
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
dummy_text = <<EOT
|
4
|
+
This is a text
|
5
|
+
This is a text
|
6
|
+
This is a text
|
7
|
+
This is a text
|
8
|
+
secret
|
9
|
+
This is a text
|
10
|
+
This is a text
|
11
|
+
This is a text
|
12
|
+
EOT
|
13
|
+
|
14
|
+
class Test
|
15
|
+
include Codesake::Utils::Files
|
16
|
+
include Codesake::Engine::Core
|
17
|
+
end
|
18
|
+
|
19
|
+
shared_examples_for Codesake::Engine::Core do
|
20
|
+
before(:all) do
|
21
|
+
@mock = Test.new
|
22
|
+
File.open("test_secrets.txt", "w") do |f|
|
23
|
+
f.puts(dummy_text)
|
24
|
+
end
|
25
|
+
|
26
|
+
@mock.filename="test_secrets.txt"
|
27
|
+
@mock.read_file
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
after(:all) do
|
32
|
+
File.delete("test_secrets.txt")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "provide an analyse method" do
|
36
|
+
@mock.should respond_to(:analyse)
|
37
|
+
end
|
38
|
+
|
39
|
+
context "has an analyse method returning an empty array if the input is" do
|
40
|
+
it "null" do
|
41
|
+
@mock.analyse.class.should == Array
|
42
|
+
@mock.analyse.should be_empty
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
dummy_text = <<EOT
|
4
|
+
This is a text
|
5
|
+
This is a text
|
6
|
+
This is a text
|
7
|
+
This is a text
|
8
|
+
EOT
|
9
|
+
|
10
|
+
class Test
|
11
|
+
include Codesake::Utils::Files
|
12
|
+
end
|
13
|
+
|
14
|
+
shared_examples_for Codesake::Utils::Files do
|
15
|
+
before(:all) do
|
16
|
+
@mock = Test.new
|
17
|
+
File.open("test_utils.txt", "w") do |f|
|
18
|
+
f.puts(dummy_text)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
after(:all) do
|
23
|
+
File.delete("test_utils.txt")
|
24
|
+
end
|
25
|
+
|
26
|
+
## Reading the file
|
27
|
+
|
28
|
+
it "has a read_file method" do
|
29
|
+
@mock.should respond_to(:read_file)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "complains if we request to read a non existing file" do
|
33
|
+
@mock.filename = "test"
|
34
|
+
@mock.read_file.should be_false
|
35
|
+
@mock.file_content.should be_empty
|
36
|
+
end
|
37
|
+
|
38
|
+
it "read an existing file" do
|
39
|
+
@mock.filename = "test_utils.txt"
|
40
|
+
@mock.read_file.should be_true
|
41
|
+
@mock.file_content.should_not be_empty
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
it "has a loc method" do
|
46
|
+
@mock.should respond_to(:loc)
|
47
|
+
end
|
48
|
+
it "has a lines method" do
|
49
|
+
@mock.should respond_to(:lines)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "has a lines_of_comment method" do
|
53
|
+
@mock.should respond_to(:lines_of_comment)
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
jsp_content =<<EOS
|
4
|
+
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
5
|
+
pageEncoding="ISO-8859-1"%>
|
6
|
+
<%@page import="com.codesake.test"%>
|
7
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
8
|
+
<html>
|
9
|
+
<head>
|
10
|
+
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
11
|
+
<link rel="stylesheet" type="text/CSS" href="<%=request.getContextPath()%>/css/style.css" />
|
12
|
+
<title>Hello World</title>
|
13
|
+
|
14
|
+
<script type="text/javascript">
|
15
|
+
function confirmSubmit(name) {
|
16
|
+
return alert("test here'"+ cacheName +"'");
|
17
|
+
}
|
18
|
+
|
19
|
+
</script>
|
20
|
+
|
21
|
+
</head>
|
22
|
+
<body>
|
23
|
+
|
24
|
+
<div id="header">
|
25
|
+
<h1>Hello World</h1>
|
26
|
+
|
27
|
+
<a href="<%=request.getContextPath()%>/jsp/link1.jsp">Link 1</a>
|
28
|
+
<a href="<%=request.getContextPath()%>/jsp/link2.jsp">Link 2</a>
|
29
|
+
<a href="<%=request.getContextPath()%>/jsp/link3.jsp">Link 3</a>
|
30
|
+
<a href="<%=request.getContextPath()%>/jsp/link4.jsp">Link 4</a>
|
31
|
+
<a href="<%=request.getContextPath()%>/servlet">servlet</a>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<%
|
35
|
+
String message = (String) request.getAttribute("message");
|
36
|
+
if(message != null)
|
37
|
+
{
|
38
|
+
%>
|
39
|
+
<h4 id="message"><%=message%></h4>
|
40
|
+
<% }
|
41
|
+
else
|
42
|
+
{
|
43
|
+
%>
|
44
|
+
<h4 id="message"></h4>
|
45
|
+
<% } %>
|
46
|
+
<div id="content">
|
47
|
+
<form action="<%=request.getContextPath()%>/postHandler" method="post">
|
48
|
+
<label for="message">message:</label>
|
49
|
+
<input type="text" name="message" id="message" size="40" value="<%=request.getLocalName()%>" />
|
50
|
+
<input type="submit" value="submit" onclick="javascript: return confirmSubmit('Clienti');" />
|
51
|
+
</form>
|
52
|
+
</div>
|
53
|
+
<%
|
54
|
+
Cookie c = new Cookie("name", "a_value")
|
55
|
+
Cookie cc = new Cookie("second", 12)
|
56
|
+
%>
|
57
|
+
</body>
|
58
|
+
EOS
|
59
|
+
|
60
|
+
describe Codesake::Engine::Jsp do
|
61
|
+
before(:all) do
|
62
|
+
File.open("test.jsp", "w") do |f|
|
63
|
+
f.write(jsp_content)
|
64
|
+
end
|
65
|
+
@jsp = Codesake::Engine::Jsp.new("test.jsp", {})
|
66
|
+
@jsp.analyse
|
67
|
+
end
|
68
|
+
|
69
|
+
after(:all) do
|
70
|
+
File.delete("test.jsp") if File.exists?("test.jsp")
|
71
|
+
end
|
72
|
+
|
73
|
+
it_behaves_like Codesake::Utils::Files
|
74
|
+
# it_behaves_like Codesake::Utils::Secrets
|
75
|
+
it_behaves_like Codesake::Engine::Core
|
76
|
+
|
77
|
+
it "takes a filename as input" do
|
78
|
+
@jsp.filename.should_not be_nil
|
79
|
+
@jsp.filename.should_not be_empty
|
80
|
+
end
|
81
|
+
|
82
|
+
it "analyses a jsp for imported packages" do
|
83
|
+
expected_result = [{:package=>"com.codesake.test", :line=>3}]
|
84
|
+
@jsp.imports.should == expected_result
|
85
|
+
end
|
86
|
+
|
87
|
+
it "analyses a jsp file for attack entrypoints" do
|
88
|
+
expected_result = [{:line=>32, :param=>"message", :var=>"message"}]
|
89
|
+
@jsp.attack_entrypoints.should == expected_result
|
90
|
+
end
|
91
|
+
it "analyses a jsp file for reflected variables" do
|
92
|
+
expected_result = [{:line=>8, :var=>"request.getContextPath()", :false_positive=>true},
|
93
|
+
{:line=>24, :var=>"request.getContextPath()", :false_positive=>true},
|
94
|
+
{:line=>25, :var=>"request.getContextPath()", :false_positive=>true},
|
95
|
+
{:line=>26, :var=>"request.getContextPath()", :false_positive=>true},
|
96
|
+
{:line=>27, :var=>"request.getContextPath()", :false_positive=>true},
|
97
|
+
{:line=>28, :var=>"request.getContextPath()", :false_positive=>true},
|
98
|
+
{:line=>36, :var=>"message", :false_positive=>false},
|
99
|
+
{:line=>44, :var=>"request.getContextPath()", :false_positive=>true},
|
100
|
+
{:line=>46, :var=>"request.getLocalName()", :false_positive=>true}
|
101
|
+
]
|
102
|
+
@jsp.reflected_xss.should == expected_result
|
103
|
+
end
|
104
|
+
|
105
|
+
it "analyses a jsp file for cookies" do
|
106
|
+
expected_result = [{:line=>51, :name=>"name", :value=>"a_value", :var=>"c"}, {:line=>52, :name=>"second", :value=>"12", :var=>"cc"}]
|
107
|
+
@jsp.cookies.should == expected_result
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
end
|
data/spec/kernel_spec.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Codesake::Kernel do
|
4
|
+
before(:all) do
|
5
|
+
@kernel = Codesake::Kernel.instance
|
6
|
+
end
|
7
|
+
|
8
|
+
it "has a choose_engine method" do
|
9
|
+
@kernel.should respond_to(:choose_engine)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has a detect method" do
|
13
|
+
@kernel.should respond_to(:detect)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "detects a text file from its extension" do
|
17
|
+
@kernel.detect("Gemfile").should == Codesake::Kernel::TEXT
|
18
|
+
@kernel.detect("foo.txt").should == Codesake::Kernel::TEXT
|
19
|
+
end
|
20
|
+
|
21
|
+
it "detects a jsp file from its extension" do
|
22
|
+
@kernel.detect("test.jsp").should == Codesake::Kernel::JSP
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
#
|
27
|
+
# TODO: I plan to add specialized engines for those languages before
|
28
|
+
# reaching 1.0 - 20121211
|
29
|
+
#
|
30
|
+
|
31
|
+
it "detects a java file from its extension"
|
32
|
+
it "detects a c file from its extension"
|
33
|
+
it "detects a shell script from its extension"
|
34
|
+
it "detects an html file from its extension"
|
35
|
+
it "detects an haml file from its extension"
|
36
|
+
it "detects a markdown file from its extension"
|
37
|
+
it "detects a ruby file from its extension"
|
38
|
+
it "detects a php file from its extension"
|
39
|
+
it "detects a js file from its extension"
|
40
|
+
it "detects a perl file from its extension"
|
41
|
+
|
42
|
+
# Engine choosing tests
|
43
|
+
|
44
|
+
it "chooses Codesake::Engine::Text for a text file" do
|
45
|
+
@kernel.choose_engine("a_text_file", {}).class.should == Codesake::Engine::Text
|
46
|
+
end
|
47
|
+
|
48
|
+
it "chooses Codesake::Engine::Jsp for a jsp file" do
|
49
|
+
@kernel.choose_engine("test.jsp", {}).class.should == Codesake::Engine::Jsp
|
50
|
+
end
|
51
|
+
|
52
|
+
it "chooses Codesake::Engine::Java for a java file"
|
53
|
+
it "chooses Codesake::Engine::Text for a c file"
|
54
|
+
it "chooses Codesake::Engine::Text for a shell script"
|
55
|
+
it "chooses Codesake::Engine::Text for a html file"
|
56
|
+
it "chooses Codesake::Engine::Text for a haml file"
|
57
|
+
it "chooses Codesake::Engine::Text for a markdown file"
|
58
|
+
it "chooses Codesake::Engine::Text for a ruby file"
|
59
|
+
it "chooses Codesake::Engine::Text for a php file"
|
60
|
+
it "chooses Codesake::Engine::Text for a js file"
|
61
|
+
it "chooses Codesake::Engine::Text for a perl file"
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
dummy_text = <<EOT
|
5
|
+
This is a text
|
6
|
+
This is a text
|
7
|
+
This is a text
|
8
|
+
This is a text
|
9
|
+
secret
|
10
|
+
This is a text
|
11
|
+
This is a text
|
12
|
+
This is a text
|
13
|
+
EOT
|
14
|
+
|
15
|
+
class Test
|
16
|
+
include Codesake::Utils::Files
|
17
|
+
include Codesake::Utils::Secrets
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
shared_examples_for Codesake::Utils::Secrets do
|
22
|
+
before(:all) do
|
23
|
+
@mock = Test.new
|
24
|
+
File.open("test_secrets.txt", "w") do |f|
|
25
|
+
f.puts(dummy_text)
|
26
|
+
end
|
27
|
+
|
28
|
+
@mock.filename="test_secrets.txt"
|
29
|
+
@mock.read_file
|
30
|
+
end
|
31
|
+
after(:all) do
|
32
|
+
File.delete("test_secrets.txt")
|
33
|
+
end
|
34
|
+
|
35
|
+
context "has a list of reserved words containing" do
|
36
|
+
it "password" do
|
37
|
+
@mock.reserved?("password").should be_true
|
38
|
+
end
|
39
|
+
it "username" do
|
40
|
+
@mock.reserved?("username").should be_true
|
41
|
+
end
|
42
|
+
it "login" do
|
43
|
+
@mock.reserved?("login").should be_true
|
44
|
+
end
|
45
|
+
it "fixme" do
|
46
|
+
@mock.reserved?("fixme").should be_true
|
47
|
+
end
|
48
|
+
it "xxx" do
|
49
|
+
@mock.reserved?("xxx").should be_true
|
50
|
+
end
|
51
|
+
it "fix" do
|
52
|
+
@mock.reserved?("fix").should be_true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "let user add a reserver word" do
|
57
|
+
@mock.reserved?("foo").should be_false
|
58
|
+
@mock.add("foo")
|
59
|
+
@mock.reserved?("foo").should be_true
|
60
|
+
|
61
|
+
end
|
62
|
+
context "has a find method" do
|
63
|
+
it "that is public" do
|
64
|
+
@mock.should respond_to(:find_reserved_keywords)
|
65
|
+
end
|
66
|
+
it "returns an empty array if 'secret' is not a reserved word in the example source" do
|
67
|
+
@mock.secrets=["noodle", "compain", "foo"]
|
68
|
+
@mock.find_reserved_keywords.should be_empty
|
69
|
+
end
|
70
|
+
it "returns true if 'secret' is a reserved word in the example source" do
|
71
|
+
@mock.secrets=["secret"]
|
72
|
+
@mock.find_reserved_keywords.should == [{:line=>5, :matcher=>"secret"}]
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
lorem_ipsum = <<EOS
|
4
|
+
Lorem ipsum dolor sit amet, secret consectetuer adipiscing elit, sed diam nonummy nibh
|
5
|
+
euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim
|
6
|
+
ad minim veniam, quis nostrud secret exerci tation ullamcorper suscipit lobortis nisl
|
7
|
+
ut aliquip ex ea commodo consequat. Duis splople autem vel eum iriure dolor in
|
8
|
+
hendrerit in vulputate velit esse secret molestie consequat, vel illum dolore eu
|
9
|
+
feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui
|
10
|
+
blandit praesent luptatum zzril password delenit augue duis dolore te feugait nulla
|
11
|
+
facilisi.
|
12
|
+
|
13
|
+
Pellentesque at dolor non lectus sagittis semper. Donec quis mi. Duis eget
|
14
|
+
pede. Phasellus arcu tellus, ultricies id, consequat id, lobortis nec, diam.
|
15
|
+
Suspendisse sed nunc. Pellentesque id magna. Morbi interdum quam at est.
|
16
|
+
Maecenas eleifend mi in urna. Praesent et lectus ac nibh luctus viverra. In vel
|
17
|
+
dolor sed nibh sollicitudin tincidunt. Ut consequat nisi sit amet nibh. Nunc mi
|
18
|
+
tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. Integer
|
19
|
+
vitae enim quis risus aliquet gravida. Curabitur vel lorem vel erat dapibus
|
20
|
+
lobortis. Donec dignissim tellus at arcu. Quisque molestie pulvinar sem.
|
21
|
+
|
22
|
+
Nulla magna neque, ullamcorper tempus, luctus eget, malesuada ut, velit. Morbi
|
23
|
+
felis. Praesent in purus at ipsum cursus posuere. Morbi bibendum facilisis
|
24
|
+
eros. Phasellus aliquam sapien in erat. Praesent venenatis diam dignissim dui.
|
25
|
+
Praesent risus erat, iaculis ac, dapibus sed, imperdiet ac, erat. Nullam sed
|
26
|
+
ipsum. Phasellus non dolor. Donec ut elit.
|
27
|
+
EOS
|
28
|
+
|
29
|
+
describe Codesake::Engine::Text do
|
30
|
+
before(:all) do
|
31
|
+
File.open("lorem.txt", "w") do |f|
|
32
|
+
f.write(lorem_ipsum)
|
33
|
+
end
|
34
|
+
@text = Codesake::Engine::Text.new("lorem.txt")
|
35
|
+
end
|
36
|
+
after(:all) do
|
37
|
+
File.delete("lorem.txt") if File.exists?("lorem.txt")
|
38
|
+
end
|
39
|
+
|
40
|
+
it_behaves_like Codesake::Utils::Files
|
41
|
+
it_behaves_like Codesake::Utils::Secrets
|
42
|
+
it_behaves_like Codesake::Engine::Core
|
43
|
+
|
44
|
+
it "takes a filename as input" do
|
45
|
+
@text.filename.should_not be_nil
|
46
|
+
@text.filename.should_not be_empty
|
47
|
+
end
|
48
|
+
|
49
|
+
context "has a is_txt? method" do
|
50
|
+
it "and this method is public" do
|
51
|
+
Codesake::Engine::Text.should respond_to(:is_txt?)
|
52
|
+
end
|
53
|
+
it "returns false if file extension is not .txt" do
|
54
|
+
Codesake::Engine::Text.is_txt?("text.jsp").should be_false
|
55
|
+
end
|
56
|
+
it "returns true if file extension is .txt" do
|
57
|
+
Codesake::Engine::Text.is_txt?("text.txt").should be_true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "analyse the file for reserved words" do
|
62
|
+
|
63
|
+
# secret @1, 3, 5
|
64
|
+
# password @7
|
65
|
+
expected_result = [{:line=>1, :matcher=>"secret"}, {:line=>3, :matcher=>"secret"}, {:line=>5, :matcher=>"secret"}, {:line=>7, :matcher=>"password"}]
|
66
|
+
@text.analyse.should_not be_nil
|
67
|
+
@text.reserved_keywords.size.should == 4
|
68
|
+
@text.reserved_keywords.should == expected_result
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|