blob: 9d3fdf5e0ff084af85eda1d1af09351c1c749c6d [file] [log] [blame]
sslobodrd6e07e72019-01-31 16:07:20 -05001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18package main
19
20import (
sslobodr1d1e50b2019-03-14 09:17:40 -040021{{if .HasFuncs}}
sslobodr13182842019-02-08 14:40:30 -050022 "fmt"
23 "time"
sslobodrd6e07e72019-01-31 16:07:20 -050024 "errors"
sslobodr13182842019-02-08 14:40:30 -050025 "context"
sslobodrd6e07e72019-01-31 16:07:20 -050026 "encoding/json"
sslobodr13182842019-02-08 14:40:30 -050027 //"golang.org/x/net/context"
sslobodrd9daabf2019-02-05 13:14:21 -050028 "google.golang.org/grpc/metadata"
Scott Bakerec6e61b2019-10-23 10:21:27 -070029 "github.com/opencord/voltha-lib-go/pkg/log"
sslobodr1d1e50b2019-03-14 09:17:40 -040030{{end}}
sslobodrd6e07e72019-01-31 16:07:20 -050031 {{range .Imports}}
sslobodr1d1e50b2019-03-14 09:17:40 -040032 {{if .Used}}
33 "{{.Package}}"
34 {{end}}
sslobodrd6e07e72019-01-31 16:07:20 -050035 {{end}}
36 {{range .ProtoImports}}
sslobodr1d1e50b2019-03-14 09:17:40 -040037 {{if .Used}}
sslobodrd6e07e72019-01-31 16:07:20 -050038 {{.Short}} "{{.Package}}"
39 {{end}}
sslobodr1d1e50b2019-03-14 09:17:40 -040040 {{end}}
sslobodrd6e07e72019-01-31 16:07:20 -050041)
42
sslobodr1d1e50b2019-03-14 09:17:40 -040043
44{{if .FileNum}}
45{{else}}
sslobodr13182842019-02-08 14:40:30 -050046var glCtx context.Context
47
sslobodrd9daabf2019-02-05 13:14:21 -050048func resetChannels() {
49 // Drain all channels of data
50 for _,v := range servers {
51 done := false
52 for {
53 select {
54 case _ = <-v.incmg:
55 case _ = <-v.replyData:
56 default:
57 done = true
58 }
59 if done == true {
60 break
61 }
62 }
63 }
64}
65
sslobodr1d1e50b2019-03-14 09:17:40 -040066type testData struct {
67 function func(int, string, string, []string,[]string,[]string,
68 map[string][]string,interface{}, interface{}) error
69 testNum int
70 testName string
71 sendClient string
72 srvrs []string
73 sendMeta []string
74 expectMeta []string // Send Meta
75 srvMeta map[string][]string
76 parm interface{}
77 ret interface{}
sslobodrd6e07e72019-01-31 16:07:20 -050078}
79
sslobodr1d1e50b2019-03-14 09:17:40 -040080func addTestSlot(stats * TestRun) {
81 tsIdx := len(stats.TestSuites) - 1
82 stats.TestSuites[tsIdx].TestCases =
83 append(stats.TestSuites[tsIdx].TestCases, TestCase{Info:[]string{}})
84}
85{{end}}
86
87{{if .FileNum}}
88func runTests{{.FileNum}}() {
89{{else}}
90func runTests() {
91{{end}}
92 tsIdx := len(stats.TestSuites) - 1
93 tests := []testData {
94 {{$ofs := .Offset}}
95 {{range $k,$v := .Tests}}
96 testData {
97 {{$v.Send.Method}}_test,
98 {{$k}} + {{$ofs}},
99 "{{$v.Name}}",
100 "{{$v.Send.Client}}",
101 []string{ {{range $sk,$sv := $v.Srvr}} "{{$sv.Name}}",{{end}} },
102 []string{ {{range $mk,$mv := $v.Send.MetaData}}"{{$mv.Key}}","{{$mv.Val}}",{{end}} },
103 []string{ {{range $mk,$mv := $v.Send.ExpectMeta}}"{{$mv.Key}}","{{$mv.Val}}",{{end}} },
104 map[string][]string {
105 {{range $sk,$sv := $v.Srvr}}
106 "{{$sv.Name}}":[]string {
107 {{range $mk, $mv := $sv.Meta}}
108 "{{$mv.Key}}","{{$mv.Val}}",
109 {{end}}
110 },
111 {{end}}
112 },
113 &{{$v.Send.ParamType}}{{$v.Send.Param}},
114 &{{$v.Send.ExpectType}}{{$v.Send.Expect}},
115 },
116 {{end}}
117 }
118
119 for _,v := range tests {
120 addTestSlot(stats)
121 stats.TestSuites[tsIdx].TestCases[v.testNum].Title = v.testName
122 if err := v.function(
123 v.testNum,
124 v.testName,
125 v.sendClient,
126 v.srvrs,
127 v.sendMeta,
128 v.expectMeta,
129 v.srvMeta,
130 v.parm,
131 v.ret); err != nil {
132 stats.TestSuites[tsIdx].TestCases[v.testNum].Result = false
133 } else {
134 stats.TestSuites[tsIdx].TestCases[v.testNum].Result = true
135 }
136 }
137 {{if .FileNum}}
138 {{else}}
139 {{range $k,$v := .RunTestsCallList}}
140 {{$v}}()
141 {{end}}
142 {{end}}
143 return
144 //resetChannels()
145}
146
147{{range $k,$v := .Funcs }}
148{{if $v.CodeGenerated}}
149{{else}}
150func {{$k}}_test(testNum int, testName string, sendClient string, srvrs []string,
151 sendMeta []string, expectMeta []string, srvrMeta map[string][]string,
152 parm interface{}, ret interface{}) error {
153
sslobodrd6e07e72019-01-31 16:07:20 -0500154 var rtrn error = nil
sslobodr13182842019-02-08 14:40:30 -0500155 var cancel context.CancelFunc
sslobodr1d1e50b2019-03-14 09:17:40 -0400156 var repl *reply
sslobodr13182842019-02-08 14:40:30 -0500157
sslobodr1d1e50b2019-03-14 09:17:40 -0400158 log.Debug("Running Test %d",testNum)
sslobodr13182842019-02-08 14:40:30 -0500159 glCtx, cancel = context.WithTimeout(context.Background(), 900*time.Millisecond)
160 defer cancel()
sslobodr1d1e50b2019-03-14 09:17:40 -0400161
162 cl := clients[sendClient]
sslobodrd6e07e72019-01-31 16:07:20 -0500163 // Create the server's reply data structure
sslobodr1d1e50b2019-03-14 09:17:40 -0400164 switch r := ret.(type) {
165 case *{{$v.ReturnType}}:
166 repl = &reply{repl:r}
167 default:
168 log.Errorf("Invalid type in call to {{$k}}_test expecting {{$v.ReturnType}} got %T", ret)
sslobodrd6e07e72019-01-31 16:07:20 -0500169 }
sslobodr1d1e50b2019-03-14 09:17:40 -0400170 // Send the reply data structure to each of the servers
171 for _,v := range srvrs {
172 if servers[v] == nil {
173 err := errors.New(fmt.Sprintf("Server %s is nil", v))
174 log.Error(err)
175 return err
sslobodr13182842019-02-08 14:40:30 -0500176 }
sslobodr1d1e50b2019-03-14 09:17:40 -0400177 // Start a go routine to send the the reply data to the
178 // server. The go routine blocks until the server picks
179 // up the data or the timeout is exceeded.
180 go func (ctx context.Context, srv string) {
181 select {
182 case servers[srv].replyData <- repl:
183 case <-ctx.Done():
184 rtrn := errors.New(fmt.Sprintf("Could not provide server %s with reply data",srv))
185 log.Error(rtrn)
186 stats.testLog("%s\n", rtrn.Error())
187 }
188 }(glCtx,v)
189 }
sslobodrd6e07e72019-01-31 16:07:20 -0500190
191 // Now call the RPC with the data provided
192 if expct,err := json.Marshal(repl.repl); err != nil {
sslobodr1d1e50b2019-03-14 09:17:40 -0400193 log.Errorf("Marshaling the reply for test %s: %v",testName, err)
sslobodrd6e07e72019-01-31 16:07:20 -0500194 } else {
sslobodrd9daabf2019-02-05 13:14:21 -0500195 // Create the context for the call
196 ctx := context.Background()
sslobodr1d1e50b2019-03-14 09:17:40 -0400197 for i:=0; i<len(sendMeta); i += 2 {
198 ctx = metadata.AppendToOutgoingContext(ctx, sendMeta[i], sendMeta[i+1])
199 }
sslobodrd9daabf2019-02-05 13:14:21 -0500200 var md map[string]string = make(map[string]string)
sslobodr1d1e50b2019-03-14 09:17:40 -0400201 for i:=0; i<len(expectMeta); i+=2 {
202 md[expectMeta[i]] = expectMeta[i+1]
203 }
sslobodrd9daabf2019-02-05 13:14:21 -0500204 expectMd := metadata.New(md)
sslobodr1d1e50b2019-03-14 09:17:40 -0400205 if err := cl.send("{{$k}}", ctx, parm, string(expct), expectMd); err != nil {
206 log.Errorf("Test case %s failed!: %v", testName, err)
207 rtrn = err
sslobodrd6e07e72019-01-31 16:07:20 -0500208 }
209 }
210
211 // Now read the servers' information to validate it
212 var s *serverCtl
213 var payload string
214 var i *incoming
sslobodr1d1e50b2019-03-14 09:17:40 -0400215 if pld, err := json.Marshal(parm); err != nil {
216 log.Errorf("Marshaling paramter for test %s: %v", testName, err)
sslobodrd6e07e72019-01-31 16:07:20 -0500217 } else {
218 payload = string(pld)
219 }
sslobodr1d1e50b2019-03-14 09:17:40 -0400220 for _,v := range srvrs {
221 s = servers[v]
222 // Oddly sometimes the data isn't in the channel yet when we come to read it.
223 select {
224 case i = <-s.incmg:
225 if i.payload != payload {
226 rtrn = errors.New(fmt.Sprintf("Mismatched payload expected '%s', got '%s'", payload, i.payload))
sslobodr13182842019-02-08 14:40:30 -0500227 log.Error(rtrn.Error())
sslobodr1d1e50b2019-03-14 09:17:40 -0400228 stats.testLog("%s\n", rtrn.Error())
sslobodrd9daabf2019-02-05 13:14:21 -0500229 }
sslobodr1d1e50b2019-03-14 09:17:40 -0400230 for j:=0; j<len(srvrMeta[v]); j+=2 {
231 if mv,ok := i.meta[srvrMeta[v][j]]; ok == true {
232 if srvrMeta[v][j+1] != mv[0] {
233 rtrn=errors.New(fmt.Sprintf("Mismatched metadata on server '%s' expected '%s', got '%s'", srvrMeta[v][j], srvrMeta[v][j+1], mv[0]))
234 log.Error(rtrn.Error())
235 stats.testLog("%s\n", rtrn.Error())
236 }
237 }
238 }
239 case <-glCtx.Done():
Kent Hagerman1b9c7062019-05-07 16:46:01 -0400240 rtrn = errors.New(fmt.Sprintf("Timeout: no response data available for server %s (%s)", v, testName))
sslobodr1d1e50b2019-03-14 09:17:40 -0400241 stats.testLog("%s\n", rtrn.Error())
242 log.Error(rtrn)
sslobodrd9daabf2019-02-05 13:14:21 -0500243 }
sslobodrd6e07e72019-01-31 16:07:20 -0500244 }
sslobodrd6e07e72019-01-31 16:07:20 -0500245
246 return rtrn
247}
248{{end}}
sslobodr1d1e50b2019-03-14 09:17:40 -0400249{{end}}