-
Notifications
You must be signed in to change notification settings - Fork 9
/
Spec.hs
195 lines (157 loc) · 6.79 KB
/
Spec.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
import qualified Control.Exception as E
import qualified Data.ByteString.Lazy as BSL
import Data.String.QQ
import System.Directory
import System.FilePath
import System.IO.Temp
import Test.Tasty
import Test.Tasty.Hspec
import CC.ShellCheck.ShellScript
import Data.Shebang
import CC.ShellCheck.FingerprintSpec (fingerprintSpecs)
--------------------------------------------------------------------------------
main :: IO ()
main = do
sbSpecs <- testSpec "Shebang Specs" shebangSpecs
ssSpecs <- testSpec "ShellScript Specs" shellscriptSpecs
fpSpecs <- testSpec "Fingerprint Specs" fingerprintSpecs
defaultMain (tests $ testGroup "All specs" [ sbSpecs, ssSpecs, fpSpecs ])
tests :: TestTree -> TestTree
tests specs = testGroup "Engine Tests" [ specs ]
--------------------------------------------------------------------------------
shebang :: BSL.ByteString
shebang = "#!/bin/sh"
shScript :: BSL.ByteString
shScript = [s|#!/bin/sh
echo "hello world"|]
rbScript :: BSL.ByteString
rbScript = [s|#!/bin/env ruby
puts "hello world"|]
--------------------------------------------------------------------------------
shebangSpecs :: Spec
shebangSpecs = describe "Shebang parsing" $ do
describe "decode" $ do
it "should parse a valid shebang without optional args" $ do
let subject = shScript
let result = decode subject
result `shouldBe` Just (Shebang (Interpretter "/bin/sh") Nothing)
it "should parse a valid shebang with optional args" $ do
let subject = rbScript
let result = decode subject
result `shouldBe` Just (Shebang (Interpretter "/bin/env") (Just (Argument "ruby")))
describe "decodeEither" $ do
it "should parse a valid shebang without optional args" $ do
let subject = shScript
let result = decodeEither subject
result `shouldBe` Right (Shebang (Interpretter "/bin/sh") Nothing)
describe "hasShebang" $ do
it "should be able to detect a valid shebang" $ do
let subject = shebang
let result = hasShebang subject
result `shouldBe` True
it "should be able to detect when shebang is missing" $ do
let subject = BSL.empty
let result = hasShebang subject
result `shouldBe` False
describe "readFirstLine" $ do
it "should only read the first line" $ do
let contents = shScript
withinTempDir $ do
let subject = "example.sh"
createFile subject contents
result <- readFirstLine subject
result `shouldBe` shebang
--------------------------------------------------------------------------------
shellscriptSpecs :: Spec
shellscriptSpecs = describe "Shellscript validation and retrieval" $ do
describe "isShellScript" $ do
it "should be valid if file has .sh extension" $ do
withinTempDir $ do
let subject = "example.sh"
createFile subject BSL.empty
result <- isShellScript subject
result `shouldBe` True
it "should be valid if file has no extension but a valid shebang" $ do
withinTempDir $ do
let subject = "example"
createFile subject shScript
result <- isShellScript subject
result `shouldBe` True
it "should not be valid if file has no extension and an invalid shebang" $ do
withinTempDir $ do
let subject = "example"
createFile subject rbScript
result <- isShellScript subject
result `shouldBe` False
describe "hasShellExtension" $ do
it "should be valid if file has .sh extension" $ do
let subject = "example.sh"
let result = hasShellExtension subject
result `shouldBe` True
it "should be valid if file has .ash extension" $ do
let subject = "example.ash"
let result = hasShellExtension subject
result `shouldBe` True
it "should be valid if file has .dash extension" $ do
let subject = "example.dash"
let result = hasShellExtension subject
result `shouldBe` True
it "should be valid if file has .bash extension" $ do
let subject = "example.bash"
let result = hasShellExtension subject
result `shouldBe` True
it "should be valid if file has .ksh extension" $ do
let subject = "example.ksh"
let result = hasShellExtension subject
result `shouldBe` True
it "should not be valid if file has no extension" $ do
let subject = "example"
let result = hasShellExtension subject
result `shouldBe` False
describe "hasValidInterpretter" $ do
it "should be valid if sh is interpretter" $ do
let subject = Shebang (Interpretter "/bin/sh") Nothing
let result = hasValidInterpretter subject
result `shouldBe` True
let subject' = Shebang (Interpretter "/bin/env") (Just (Argument "sh"))
let result' = hasValidInterpretter subject'
result' `shouldBe` True
it "should be valid if bash is interpretter" $ do
let subject = Shebang (Interpretter "/bin/bash") Nothing
let result = hasValidInterpretter subject
result `shouldBe` True
let subject' = Shebang (Interpretter "/bin/env") (Just (Argument "bash"))
let result' = hasValidInterpretter subject'
result' `shouldBe` True
it "should be not be valid if ruby is interpretter" $ do
let subject = Shebang (Interpretter "/bin/ruby") Nothing
let result = hasValidInterpretter subject
result `shouldBe` False
let subject' = Shebang (Interpretter "/bin/env") (Just (Argument "ruby"))
let result' = hasValidInterpretter subject'
result' `shouldBe` False
describe "findShellScripts" $ do
describe "when i specify a list of files" $ do
it "should filter out scripts that aren't shell scripts" $ do
let subject = [ "test/fixtures/example"
, "test/fixtures/example.sh"
, "test/fixtures/example.rb"
]
result <- findShellScripts subject
result `shouldBe` [ "test/fixtures/example", "test/fixtures/example.sh" ]
describe "when i specify a list of directories" $ do
it "should give me all shell script files, regardless of extension" $ do
let subject = [ "test/fixtures/" ]
result <- findShellScripts subject
result `shouldBe` [ "test/fixtures/example", "test/fixtures/example.sh" ]
--------------------------------------------------------------------------------
withinTempDir :: IO a -> IO a
withinTempDir act = withSystemTempDirectory "cc-hlint" $ \tmp -> do
E.bracket getCurrentDirectory setCurrentDirectory $ \_ ->
setCurrentDirectory tmp >> act
createFile :: FilePath -> BSL.ByteString -> IO ()
createFile path content = do
createDirectoryIfMissing True $ takeDirectory path
BSL.writeFile path content