Skip to content

Commit dc8ec6b

Browse files
committed
Add tests and CI setups
1 parent 7955216 commit dc8ec6b

File tree

2 files changed

+221
-0
lines changed

2 files changed

+221
-0
lines changed

.github/workflows/build.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: build
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
schedule:
11+
- cron: "0 0 * * *"
12+
13+
jobs:
14+
test:
15+
name: ${{ matrix.os }}
16+
runs-on: ${{ matrix.os }}
17+
strategy:
18+
matrix:
19+
os: [ubuntu-latest, windows-latest]
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v2
23+
- name: Set up Go
24+
uses: actions/setup-go@v1
25+
with:
26+
go-version: 1.14
27+
- name: Run test
28+
run: go test ./...

tflint/client_test.go

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package tflint
2+
3+
import (
4+
"encoding/gob"
5+
"errors"
6+
"net"
7+
"net/rpc"
8+
"testing"
9+
10+
"github.com/google/go-cmp/cmp"
11+
"github.com/google/go-cmp/cmp/cmpopts"
12+
hcl "github.com/hashicorp/hcl/v2"
13+
"github.com/hashicorp/hcl/v2/hclsyntax"
14+
"github.com/zclconf/go-cty/cty"
15+
)
16+
17+
type mockServer struct {
18+
Listener *net.TCPListener
19+
}
20+
21+
func (*mockServer) Attributes(req *AttributesRequest, resp *AttributesResponse) error {
22+
expr, diags := hclsyntax.ParseExpression([]byte("1"), "example.tf", hcl.Pos{Line: 1, Column: 1})
23+
if diags.HasErrors() {
24+
*resp = AttributesResponse{Attributes: []*hcl.Attribute{}, Err: diags}
25+
return nil
26+
}
27+
28+
*resp = AttributesResponse{Attributes: []*hcl.Attribute{
29+
{
30+
Name: req.AttributeName,
31+
Expr: expr,
32+
Range: hcl.Range{
33+
Start: hcl.Pos{Line: 1, Column: 1},
34+
End: hcl.Pos{Line: 2, Column: 2},
35+
},
36+
},
37+
}, Err: nil}
38+
return nil
39+
}
40+
41+
func (*mockServer) EvalExpr(req *EvalExprRequest, resp *EvalExprResponse) error {
42+
*resp = EvalExprResponse{Val: cty.StringVal("1"), Err: nil}
43+
return nil
44+
}
45+
46+
func (s *mockServer) EmitIssue(req *EmitIssueRequest, resp *interface{}) error {
47+
return nil
48+
}
49+
50+
func startMockServer(t *testing.T) (*Client, *mockServer) {
51+
gob.Register(&hclsyntax.LiteralValueExpr{})
52+
53+
addy, err := net.ResolveTCPAddr("tcp", "0.0.0.0:42586")
54+
if err != nil {
55+
t.Fatal(err)
56+
}
57+
inbound, err := net.ListenTCP("tcp", addy)
58+
if err != nil {
59+
t.Fatal(err)
60+
}
61+
62+
server := &mockServer{Listener: inbound}
63+
rpc.RegisterName("Plugin", server)
64+
go rpc.Accept(inbound)
65+
66+
conn, err := net.Dial("tcp", "0.0.0.0:42586")
67+
if err != nil {
68+
t.Fatal(err)
69+
}
70+
return NewClient(conn), server
71+
}
72+
73+
func Test_WalkResourceAttributes(t *testing.T) {
74+
client, server := startMockServer(t)
75+
defer server.Listener.Close()
76+
77+
walked := []*hcl.Attribute{}
78+
walker := func(attribute *hcl.Attribute) error {
79+
walked = append(walked, attribute)
80+
return nil
81+
}
82+
83+
if err := client.WalkResourceAttributes("foo", "bar", walker); err != nil {
84+
t.Fatal(err)
85+
}
86+
87+
expr, diags := hclsyntax.ParseExpression([]byte("1"), "example.tf", hcl.Pos{Line: 1, Column: 1})
88+
if diags.HasErrors() {
89+
t.Fatal(diags)
90+
}
91+
expected := []*hcl.Attribute{
92+
{
93+
Name: "bar",
94+
Expr: expr,
95+
Range: hcl.Range{
96+
Start: hcl.Pos{Line: 1, Column: 1},
97+
End: hcl.Pos{Line: 2, Column: 2},
98+
},
99+
},
100+
}
101+
102+
opt := cmpopts.IgnoreFields(hclsyntax.LiteralValueExpr{}, "Val")
103+
if !cmp.Equal(expected, walked, opt) {
104+
t.Fatalf("Diff: %s", cmp.Diff(expected, walked, opt))
105+
}
106+
}
107+
108+
func Test_EvaluateExpr(t *testing.T) {
109+
client, server := startMockServer(t)
110+
defer server.Listener.Close()
111+
112+
expr, diags := hclsyntax.ParseExpression([]byte("1"), "example.tf", hcl.Pos{Line: 1, Column: 1})
113+
if diags.HasErrors() {
114+
t.Fatal(diags)
115+
}
116+
117+
var ret string
118+
if err := client.EvaluateExpr(expr, &ret); err != nil {
119+
t.Fatal(err)
120+
}
121+
122+
if ret != "1" {
123+
t.Fatalf("Expected: 1, but got %s", ret)
124+
}
125+
}
126+
127+
type testRule struct{}
128+
129+
func (*testRule) Name() string { return "test" }
130+
func (*testRule) Enabled() bool { return true }
131+
func (*testRule) Severity() string { return "Error" }
132+
func (*testRule) Link() string { return "" }
133+
func (*testRule) Check(Runner) error { return nil }
134+
135+
func Test_EmitIssue(t *testing.T) {
136+
client, server := startMockServer(t)
137+
defer server.Listener.Close()
138+
139+
if err := client.EmitIssue(&testRule{}, "test", hcl.Range{}, Metadata{}); err != nil {
140+
t.Fatal(err)
141+
}
142+
}
143+
144+
func Test_EnsureNoError(t *testing.T) {
145+
cases := []struct {
146+
Name string
147+
Error error
148+
ErrorText string
149+
}{
150+
{
151+
Name: "no error",
152+
Error: nil,
153+
ErrorText: "function called",
154+
},
155+
{
156+
Name: "native error",
157+
Error: errors.New("Error occurred"),
158+
ErrorText: "Error occurred",
159+
},
160+
{
161+
Name: "warning error",
162+
Error: Error{
163+
Code: UnknownValueError,
164+
Level: WarningLevel,
165+
Message: "Warning error",
166+
},
167+
},
168+
{
169+
Name: "app error",
170+
Error: Error{
171+
Code: TypeMismatchError,
172+
Level: ErrorLevel,
173+
Message: "App error",
174+
},
175+
ErrorText: "App error",
176+
},
177+
}
178+
179+
client, _ := startMockServer(t)
180+
181+
for _, tc := range cases {
182+
err := client.EnsureNoError(tc.Error, func() error {
183+
return errors.New("function called")
184+
})
185+
if err == nil {
186+
if tc.ErrorText != "" {
187+
t.Fatalf("Failed `%s` test: expected error is not occurred `%s`", tc.Name, tc.ErrorText)
188+
}
189+
} else if err.Error() != tc.ErrorText {
190+
t.Fatalf("Failed `%s` test: expected error is %s, but get %s", tc.Name, tc.ErrorText, err)
191+
}
192+
}
193+
}

0 commit comments

Comments
 (0)