Skip to content

Commit 02b709a

Browse files
committed
A few (deactivated) tests added
1 parent ec5d486 commit 02b709a

29 files changed

Lines changed: 2168 additions & 60 deletions
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Attention
2+
3+
* Do **not** edit `generated_cgoPackage.go`. Change instead file `../testdata/cgoPackage.go` and execute `../updateTestData.sh` afterwards. This influences _all_ cgot packages tests.
4+
* For individual modifications use file `cgo_test.go` or create an additional file.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package cgot
2+
3+
import (
4+
"bytes"
5+
"io"
6+
"path"
7+
"testing"
8+
9+
"github.com/rokath/trice/internal/args"
10+
"github.com/spf13/afero"
11+
"github.com/tj/assert"
12+
)
13+
14+
func init() {
15+
triceLog = func(t *testing.T, fSys *afero.Afero, buffer string) string {
16+
var o bytes.Buffer
17+
f := args.Handler(io.Writer(&o), fSys,
18+
[]string{
19+
"trice", "log",
20+
"-i", path.Join(triceDir, "/demoTIL.json"),
21+
"-hs=off", "-prefix=off", "-li=off", "-color=off",
22+
"-p=BUFFER", "-args", buffer,
23+
"-ts0", "time: ",
24+
"-ts16", "time: %04x",
25+
"-ts32", "time:%08x",
26+
27+
"-pf=NONE",
28+
},
29+
)
30+
assert.Nil(t, f)
31+
return o.String()
32+
}
33+
targetMode = "deferredMode"
34+
}
Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
// Copyright 2020 Thomas.Hoehenleitner [at] seerose.net
2+
// Use of this source code is governed by a license that can be found in the LICENSE file.
3+
4+
// Package cgot is a helper for testing the target C-code.
5+
// Each C function gets a Go wrapper which is tested in appropriate test functions.
6+
// For some reason inside the trice_test.go an 'import "C"' is not possible.
7+
// The C-files referring to the trice sources this way avoiding code duplication.
8+
// The Go functions defined here are not exported. They are called by the Go test functions in this package.
9+
// This way the test functions are executing the trice C-code compiled with the triceConfig.h here.
10+
// Inside ./testdata this file is named cgoPackage.go where it is maintained.
11+
// The ../renewIDs_in_examples_and_test_folder.sh script copies this file under the name generated_cgoPackage.go into various
12+
// package folders, where it is used separately.
13+
package cgot
14+
15+
// #include <stdint.h>
16+
// void TriceCheck( int n );
17+
// void TriceTransfer( void );
18+
// unsigned TriceOutDepth( void );
19+
// void CgoSetTriceBuffer( uint8_t* buf );
20+
// void CgoClearTriceBuffer( void );
21+
// #cgo CFLAGS: -g -I../../src -Wshadow -Wno-format-security
22+
// #include "../../src/trice.c"
23+
// #include "../../src/trice8.c"
24+
// #include "../../src/trice16.c"
25+
// #include "../../src/trice32.c"
26+
// #include "../../src/trice64.c"
27+
// #include "../../src/triceUart.c"
28+
// #include "../../src/triceAuxiliary.c"
29+
// #include "../../src/triceDoubleBuffer.c"
30+
// #include "../../src/triceRingBuffer.c"
31+
// #include "../../src/triceStackBuffer.c"
32+
// #include "../../src/triceStaticBuffer.c"
33+
// #include "../../src/xtea.c"
34+
// #include "../../src/cobsDecode.c"
35+
// #include "../../src/cobsEncode.c"
36+
// #include "../../src/tcobsv1Decode.c"
37+
// #include "../../src/tcobsv1Encode.c"
38+
// #include "../testdata/triceCheck.c"
39+
// #include "../testdata/cgoTrice.c"
40+
import "C"
41+
42+
import (
43+
"bufio"
44+
"fmt"
45+
"path"
46+
"runtime"
47+
"strings"
48+
"testing"
49+
"unsafe"
50+
51+
"github.com/rokath/trice/internal/decoder"
52+
"github.com/rokath/trice/internal/trexDecoder"
53+
"github.com/rokath/trice/pkg/cipher"
54+
"github.com/rokath/trice/pkg/msg"
55+
"github.com/spf13/afero"
56+
"github.com/tj/assert"
57+
)
58+
59+
var (
60+
testLines = -1 // testLines is the common number of tested lines in triceCheck. The value -1 is for all lines, what takes time.
61+
triceDir string // triceDir holds the trice directory path.
62+
targetActivityC string // triceCheckC contains the target test code.
63+
targetMode string // targetMode is "directMode" OR "deferredMode" OR "combinedMode" (direct AND deferred mode) and must fit the triceConfig.h settings to adapt the tests.
64+
)
65+
66+
// https://stackoverflow.com/questions/23847003/golang-tests-and-working-directory
67+
func init() {
68+
_, filename, _, _ := runtime.Caller(0) // filename is the test executable inside the package dir like cgo_stackBuffer_noCycle_tcobs
69+
testDir := path.Dir(filename)
70+
triceDir = path.Join(testDir, "../../")
71+
targetActivityC = path.Join(triceDir, "./_test/testdata/triceCheck.c")
72+
C.TriceInit()
73+
}
74+
75+
// setTriceBuffer tells the underlying C code where to output the trice byte stream.
76+
func setTriceBuffer(o []byte) {
77+
Cout := (*C.uchar)(unsafe.Pointer(&o[0]))
78+
C.CgoSetTriceBuffer(Cout)
79+
}
80+
81+
// triceCheck performs triceCheck C-code sequence n.
82+
func triceCheck(n int) {
83+
C.TriceCheck(C.int(n))
84+
}
85+
86+
// triceTransfer performs the deferred trice output.
87+
func triceTransfer() {
88+
C.TriceTransfer()
89+
}
90+
91+
// triceOutDepth returns the actual out buffer depth.
92+
func triceOutDepth() int {
93+
return int(C.TriceOutDepth())
94+
}
95+
96+
// triceClearOutBuffer tells the trice kernel, that the data has been red.
97+
func triceClearOutBuffer() {
98+
C.CgoClearTriceBuffer()
99+
}
100+
101+
// linesInFile does get the lines in a file and stores them in a string slice.
102+
func linesInFile(fh afero.File) []string { // https://www.dotnetperls.com/lines-file-go
103+
// Create new Scanner.
104+
scanner := bufio.NewScanner(fh)
105+
result := []string{}
106+
// Use Scan.
107+
for scanner.Scan() {
108+
line := scanner.Text()
109+
// Append line to result.
110+
result = append(result, line)
111+
}
112+
return result
113+
}
114+
115+
// results contains the expected result string exps for line number line.
116+
type results struct {
117+
line int
118+
exps string
119+
}
120+
121+
func getExpectedResults(fSys *afero.Afero, filename string, maxTestlines int) (result []results) {
122+
// get all file lines into a []string
123+
f, e := fSys.Open(filename)
124+
msg.OnErr(e)
125+
lines := linesInFile(f)
126+
var testLinesCounter = 0
127+
for i, line := range lines {
128+
s := strings.Split(line, "//")
129+
if len(s) == 2 { // just one "//"
130+
lineEnd := s[1]
131+
index := strings.LastIndex(lineEnd, "exp: \"")
132+
if index == 0 { // pattern //exp: "
133+
var r results
134+
r.line = i + 1 // 1st line number is 1 and not 0
135+
// r.exps = strings.TrimSpace(lineEnd[index+len(subStr):])
136+
s := lineEnd[6 : len(lineEnd)-1]
137+
r.exps = strings.ReplaceAll(s, "\\n", "\n")
138+
result = append(result, r)
139+
testLinesCounter++
140+
if maxTestlines > 0 && testLinesCounter >= maxTestlines {
141+
break
142+
}
143+
}
144+
}
145+
}
146+
147+
skipAtStart := 0
148+
skipAtEnd := 0
149+
150+
from := skipAtStart
151+
if len(result) < skipAtStart {
152+
from = 0
153+
}
154+
155+
to := len(result) - skipAtEnd
156+
if len(result) < skipAtEnd {
157+
to = len(result)
158+
}
159+
return result[from:to]
160+
}
161+
162+
// logF is the log function type for executing the trice logging on binary log data in buffer as space separated numbers.
163+
// It uses the inside fSys specified til.json and returns the log output.
164+
type logF func(t *testing.T, fSys *afero.Afero, buffer string) string
165+
166+
// triceLogLineByLine creates a list of expected results from triceCheckC.
167+
// It loops over the result list and executes for each result the compiled C-code.
168+
// It passes the received binary data as buffer to the triceLog function of type logF.
169+
// This function is test package specific defined. The file cgoPackage.go is
170+
// copied into all specific test packages and compiled there together with the
171+
// triceConfig.h, which holds the test package specific target code configuration.
172+
// testLines is the count of executed test lines starting from the beginning. -1 ist for all.
173+
func triceLogLineByLine(t *testing.T, triceLog logF, testLines int, triceCheckC string) {
174+
osFSys := &afero.Afero{Fs: afero.NewOsFs()}
175+
// CopyFileIntoFSys(t, mmFSys, "til.json", osFSys, td+"./til.json") // needed for the trice log
176+
out := make([]byte, 32768)
177+
setTriceBuffer(out)
178+
result := getExpectedResults(osFSys, triceCheckC, testLines)
179+
for i, v := range result {
180+
triceCheck(v.line) // target activity
181+
triceTransfer() // This is only for deferred modes needed, but direct modes contain this as empty function.
182+
length := triceOutDepth()
183+
bin := out[:length] // bin contains the binary trice data of trice message i in r.line
184+
buf := fmt.Sprint(bin)
185+
buffer := buf[1 : len(buf)-1]
186+
act := triceLog(t, osFSys, buffer)
187+
triceClearOutBuffer()
188+
assert.Equal(t, v.exps, act, fmt.Sprintf("%d: line %d: len(exp)=%d, len(act)=%d", i, v.line, len(v.exps), len(act)))
189+
}
190+
}
191+
192+
// triceLogBulk creates a list of expected results from triceCheckC.
193+
// It loops over the result list and executes for each result the compiled C-code.
194+
// It passes the received binary data as buffer to the triceLog function of type logF.
195+
// This function is test package specific defined. The file cgoPackage.go is
196+
// copied into all specific test packages and compiled there together with the
197+
// triceConfig.h, which holds the test package specific target code configuration.
198+
// testLines is the count of executed test lines starting from the beginning. -1 ist for all.
199+
func triceLogBulk(t *testing.T, triceLog logF, testLines int, triceCheckC string) {
200+
osFSys := &afero.Afero{Fs: afero.NewOsFs()}
201+
// CopyFileIntoFSys(t, mmFSys, "til.json", osFSys, td+"./til.json") // needed for the trice log
202+
203+
// out is the binary trice data buffer until the next triceTransfer() call.
204+
// It must be able to hold binary Trice data for several Trice calls and should have at least the
205+
// configured target internal buffer size, here 65536 is a very safe value.
206+
out := make([]byte, 65536)
207+
setTriceBuffer(out)
208+
result := getExpectedResults(osFSys, triceCheckC, testLines)
209+
var bin []byte // bin collects the binary data.
210+
bulk := 5
211+
for i, r := range result {
212+
fmt.Print("i:", i, "\texecute triceCheck.c line:", r.line, "\texp:", r.exps)
213+
triceCheck(r.line) // target activity
214+
215+
// In case "#define TRICE_DEFERRED_TRANSFER_MODE TRICE_SINGLE_PACK_MODE" wee need to call triceTransfer
216+
// at least that often a trice was executed. Just in case a test line produces more than one trice message,
217+
// we do it 2*bulk times
218+
if i%bulk == 0 {
219+
for range 2 * bulk { // collect three trice messages before transfer}
220+
triceTransfer() // This is only for deferred modes needed, but direct modes contain this as empty function.
221+
length := triceOutDepth()
222+
bin = append(bin, out[:length]...)
223+
setTriceBuffer(out)
224+
}
225+
}
226+
}
227+
228+
// For safety do some more transfers to get the last messages.
229+
for range 2 * bulk { // collect three trice messages before transfer}
230+
triceTransfer() // This is only for deferred modes needed, but direct modes contain this as empty function.
231+
length := triceOutDepth()
232+
bin = append(bin, out[:length]...)
233+
setTriceBuffer(out)
234+
}
235+
236+
buf := fmt.Sprint(bin) // buf is the ASCII representation of bin.
237+
buffer := buf[1 : len(buf)-1] // buffer contains the bare data (without brackets).
238+
act := triceLog(t, osFSys, buffer) // act is the complete printed text.
239+
for i, v := range result {
240+
if len(act) >= len(v.exps) {
241+
a := act[:len(v.exps)] // get next part of actual data (usually a line).
242+
assert.Equal(t, v.exps, a, fmt.Sprintf("%d: line %d: len(exp)=%d, len(act)=%d", i, v.line, len(v.exps), len(a)))
243+
act = act[len(v.exps):]
244+
} else {
245+
fmt.Println(i, "of", len(result), "v.exps:", v.exps)
246+
fmt.Println(len(act), "act:", act)
247+
assert.Fail(t, fmt.Sprintf("%d: line %d: len(exp)=%d, len(act)=%d", i, v.line, len(v.exps), len(act)), "actual data too short")
248+
}
249+
}
250+
//assert.Fail(t, "forced fail")
251+
}
252+
253+
// triceLogDirectAndDeferred works like triceLogTest but additionally expects doubled output: direct and deferred.
254+
func triceLogDirectAndDeferred(t *testing.T, triceLog0, triceLog1 logF, testLines int, triceCheckC string) {
255+
g.getGlobalVarsDefaults() // read changed defaults
256+
osFSys := &afero.Afero{Fs: afero.NewOsFs()}
257+
// CopyFileIntoFSys(t, mmFSys, "til.json", osFSys, td+"./til.json") // needed for the trice log
258+
out := make([]byte, 32768)
259+
setTriceBuffer(out)
260+
result := getExpectedResults(osFSys, triceCheckC, testLines)
261+
262+
for i, v := range result {
263+
triceCheck(v.line) // target activity
264+
265+
{ // Check direct output line by line.
266+
length := triceOutDepth()
267+
bin := out[:length] // bin contains the binary trice data of trice message i
268+
buf := fmt.Sprint(bin)
269+
buffer := buf[1 : len(buf)-1]
270+
g.setGlobalVarsDefaults() // restore changed defaults
271+
act := triceLog0(t, osFSys, buffer)
272+
triceClearOutBuffer()
273+
assert.Equal(t, v.exps, act, fmt.Sprint(i, v))
274+
}
275+
{ // Check deferred output.
276+
if false {
277+
278+
} else { // liny by line (slow)
279+
triceTransfer()
280+
length := triceOutDepth()
281+
bin := out[:length] // bin contains the binary trice data of trice message i
282+
buf := fmt.Sprint(bin)
283+
buffer := buf[1 : len(buf)-1]
284+
g.setGlobalVarsDefaults() // restore changed defaults
285+
act := triceLog1(t, osFSys, buffer)
286+
triceClearOutBuffer()
287+
assert.Equal(t, v.exps, act, fmt.Sprint(i, v))
288+
}
289+
}
290+
}
291+
}
292+
293+
type globalDefaults struct {
294+
defaultPassword string
295+
defaultPackageFraming string
296+
defaultDoubled16BitID bool
297+
}
298+
299+
var (
300+
// g holds global vars default values
301+
g globalDefaults
302+
303+
// triceLog is the log function for executing the trice logging on binary log data in buffer as space separated numbers.
304+
// It uses the inside fSys specified til.json and returns the log output.
305+
triceLog func(t *testing.T, fSys *afero.Afero, buffer string) string
306+
triceLogDirect func(t *testing.T, fSys *afero.Afero, buffer string) string
307+
triceLogDeferred func(t *testing.T, fSys *afero.Afero, buffer string) string
308+
)
309+
310+
// Keep default values of global variables.
311+
func (p *globalDefaults) getGlobalVarsDefaults() {
312+
p.defaultPassword = cipher.Password
313+
p.defaultPackageFraming = decoder.PackageFraming
314+
p.defaultDoubled16BitID = trexDecoder.Doubled16BitID
315+
}
316+
317+
// setGlobalVarsDefaults sets all global variables in a definitive state.
318+
// In Go, each package generates an individual test binary and they are tested parallel.
319+
// All package tests are executed sequentially but use the same global variables.
320+
// Therefore we have to reset the global variables in each test function.
321+
func (p *globalDefaults) setGlobalVarsDefaults() {
322+
cipher.Password = p.defaultPassword
323+
decoder.PackageFraming = p.defaultPackageFraming
324+
trexDecoder.Doubled16BitID = p.defaultDoubled16BitID
325+
}

0 commit comments

Comments
 (0)