Skip to content

Commit cc9339b

Browse files
qmuntaldagood
andauthored
Add tests for internal/mkcgo (#270)
* add tests for internal/mkcgo * Apply suggestions from code review Co-authored-by: Davis Goodin <[email protected]> * pr feedback --------- Co-authored-by: Davis Goodin <[email protected]>
1 parent 7d39d27 commit cc9339b

File tree

7 files changed

+780
-285
lines changed

7 files changed

+780
-285
lines changed

cmd/checkheader/main.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,16 @@ func gccRun(program string) error {
100100
}
101101

102102
func generate(header string) (string, error) {
103-
src, err := mkcgo.Parse(header)
103+
r, err := os.Open(header)
104104
if err != nil {
105105
return "", err
106106
}
107+
defer r.Close()
108+
109+
var src mkcgo.Source
110+
if err := src.Parse(r); err != nil {
111+
return "", err
112+
}
107113
w := &strings.Builder{}
108114

109115
for _, c := range src.Comments {
@@ -131,7 +137,7 @@ func generate(header string) (string, error) {
131137
}
132138
var i int
133139
for _, fn := range src.Funcs {
134-
if fn.VariadicInst {
140+
if fn.VariadicTarget != "" {
135141
// Variadic instantiations are not real OpenSSL functions,
136142
// skip them.
137143
continue
@@ -141,7 +147,7 @@ func generate(header string) (string, error) {
141147
tags = []mkcgo.TagAttr{{}}
142148
}
143149
for _, tag := range tags {
144-
importName := fn.ImportName
150+
importName := fn.ImportName()
145151
if tag.Name != "" {
146152
importName = tag.Name
147153
}
@@ -169,7 +175,7 @@ func generate(header string) (string, error) {
169175
for _, p := range fn.Params {
170176
sparams = append(sparams, p.Type)
171177
}
172-
fmt.Fprintf(w, "%s (*__check_%d)(%s) = %s;\n", fn.Ret.Type, i, strings.Join(sparams, ", "), importName)
178+
fmt.Fprintf(w, "%s (*__check_%d)(%s) = %s;\n", fn.Ret, i, strings.Join(sparams, ", "), importName)
173179
for range conds {
174180
fmt.Fprintf(w, "#endif\n")
175181
}

cmd/mkcgo/generate.go

+28-27
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func generateGoAliases(funcs []*mkcgo.Func, w io.Writer) {
125125
}
126126
handleType(p.Type)
127127
}
128-
handleType(fn.Ret.Type)
128+
handleType(fn.Ret)
129129
}
130130
types := make([]string, 0, len(ctypes))
131131
for typ := range ctypes {
@@ -199,9 +199,9 @@ func generateCHeader(src *mkcgo.Source, w io.Writer) {
199199
continue
200200
}
201201
if fnNeedErrWrapper(fn) {
202-
fmt.Fprintf(w, "%s %s(%s);\n", fn.Ret.Type, fnCName(fn), fnCErrWrapperParams(fn, false))
202+
fmt.Fprintf(w, "%s %s(%s);\n", fn.Ret, fnCName(fn), fnCErrWrapperParams(fn, false))
203203
} else {
204-
fmt.Fprintf(w, "%s %s(%s);\n", fn.Ret.Type, fnCName(fn), fnToCArgs(fn, true, false))
204+
fmt.Fprintf(w, "%s %s(%s);\n", fn.Ret, fnCName(fn), fnToCArgs(fn, true, false))
205205
}
206206
}
207207
fmt.Fprintf(w, "\n")
@@ -233,10 +233,10 @@ func generateC(src *mkcgo.Source, w io.Writer) {
233233

234234
// Function pointer declarations.
235235
for _, fn := range src.Funcs {
236-
if fn.VariadicInst {
236+
if fn.VariadicTarget != "" {
237237
continue
238238
}
239-
fmt.Fprintf(w, "%s (*_g_%s)(%s);\n", fn.Ret.Type, fn.ImportName, fnToCArgs(fn, true, false))
239+
fmt.Fprintf(w, "%s (*_g_%s)(%s);\n", fn.Ret, fn.ImportName(), fnToCArgs(fn, true, false))
240240
}
241241
fmt.Fprintf(w, "\n")
242242

@@ -253,7 +253,7 @@ func generateC(src *mkcgo.Source, w io.Writer) {
253253
for _, tag := range src.Tags() {
254254
fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle) {\n", tag)
255255
for _, fn := range src.Funcs {
256-
if fn.VariadicInst {
256+
if fn.VariadicTarget != "" {
257257
continue
258258
}
259259
tags := fn.Tags
@@ -264,11 +264,11 @@ func generateC(src *mkcgo.Source, w io.Writer) {
264264
if tagAttr.Tag == tag {
265265
if tagAttr.Name != "" {
266266
// TODO: if necessary, support optional functions in here too.
267-
fmt.Fprintf(w, "\t__mkcgo__dlsym2(%s, %s)\n", fn.ImportName, tagAttr.Name)
267+
fmt.Fprintf(w, "\t__mkcgo__dlsym2(%s, %s)\n", fn.ImportName(), tagAttr.Name)
268268
} else if fn.Optional {
269-
fmt.Fprintf(w, "\t__mkcgo__dlsym_nocheck(%s, %s)\n", fn.ImportName, fn.ImportName)
269+
fmt.Fprintf(w, "\t__mkcgo__dlsym_nocheck(%s, %s)\n", fn.ImportName(), fn.ImportName())
270270
} else {
271-
fmt.Fprintf(w, "\t__mkcgo__dlsym(%s)\n", fn.ImportName)
271+
fmt.Fprintf(w, "\t__mkcgo__dlsym(%s)\n", fn.ImportName())
272272
}
273273
break
274274
}
@@ -278,7 +278,7 @@ func generateC(src *mkcgo.Source, w io.Writer) {
278278

279279
fmt.Fprintf(w, "void __mkcgo_unload_%s() {\n", tag)
280280
for _, fn := range src.Funcs {
281-
if fn.VariadicInst {
281+
if fn.VariadicTarget != "" {
282282
continue
283283
}
284284
tags := fn.Tags
@@ -287,7 +287,7 @@ func generateC(src *mkcgo.Source, w io.Writer) {
287287
}
288288
for _, tagAttr := range tags {
289289
if tagAttr.Tag == tag {
290-
fmt.Fprintf(w, "\t_g_%s = NULL;\n", fn.ImportName)
290+
fmt.Fprintf(w, "\t_g_%s = NULL;\n", fn.ImportName())
291291
break
292292
}
293293
}
@@ -308,7 +308,7 @@ func generateC(src *mkcgo.Source, w io.Writer) {
308308
if fn.Optional {
309309
// Generate a function that returns true if the function is available.
310310
fmt.Fprintf(w, "int %s() {\n", fnCNameAvailable(fn))
311-
fmt.Fprintf(w, "\treturn _g_%s != NULL;\n", fn.ImportName)
311+
fmt.Fprintf(w, "\treturn _g_%s != NULL;\n", fn.ImportName())
312312
fmt.Fprintf(w, "}\n\n")
313313
}
314314
generateCFn(typedefs, fn, w)
@@ -320,15 +320,15 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) {
320320
fnCall := fmt.Sprintf("C.%s(%s)", fnCName(fn), fnToGoArgs(fn))
321321
// Function definition
322322
fmt.Fprintf(w, "func %s(%s)", goSymName(fn.Name), fnToGoParams(fn))
323-
if retIsVoid(fn.Ret) {
323+
if isVoid(fn.Ret) {
324324
// Easy path, just call the C function. No need to write the return types,
325325
// nor do error handling, nor cast the return value.
326326
fmt.Fprintf(w, "{\n")
327327
fmt.Fprintf(w, "\t%s\n", fnCall)
328328
fmt.Fprintf(w, "}\n\n")
329329
return
330330
}
331-
goType, needCast := cTypeToGo(fn.Ret.Type, false)
331+
goType, needCast := cTypeToGo(fn.Ret, false)
332332
if fn.NoError {
333333
fmt.Fprintf(w, " %s ", goType)
334334
} else {
@@ -381,24 +381,24 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) {
381381

382382
func generateCFn(typedefs map[string]string, fn *mkcgo.Func, w io.Writer) {
383383
if !fnNeedErrWrapper(fn) {
384-
fmt.Fprintf(w, "%s %s(%s) {\n\t", fn.Ret.Type, fnCName(fn), fnToCArgs(fn, true, true))
385-
if !retIsVoid(fn.Ret) {
384+
fmt.Fprintf(w, "%s %s(%s) {\n\t", fn.Ret, fnCName(fn), fnToCArgs(fn, true, true))
385+
if !isVoid(fn.Ret) {
386386
fmt.Fprintf(w, "return ")
387387
}
388-
fmt.Fprintf(w, "_g_%s(%s);\n", fn.ImportName, fnToCArgs(fn, false, true))
388+
fmt.Fprintf(w, "_g_%s(%s);\n", fn.ImportName(), fnToCArgs(fn, false, true))
389389
fmt.Fprintf(w, "}\n\n")
390390
return
391391
}
392392

393-
fmt.Fprintf(w, "%s %s(%s) {\n", fn.Ret.Type, fnCName(fn), fnCErrWrapperParams(fn, true))
393+
fmt.Fprintf(w, "%s %s(%s) {\n", fn.Ret, fnCName(fn), fnCErrWrapperParams(fn, true))
394394
fmt.Fprintf(w, "\tmkcgo_err_clear();\n") // clear any previous error
395-
fmt.Fprintf(w, "\t%s _ret = _g_%s(%s);\n", fn.Ret.Type, fn.ImportName, fnToCArgs(fn, false, true))
395+
fmt.Fprintf(w, "\t%s _ret = _g_%s(%s);\n", fn.Ret, fn.ImportName(), fnToCArgs(fn, false, true))
396396
errCond := "<= 0"
397397
if fn.ErrCond != "" {
398398
errCond = fn.ErrCond
399-
} else if strings.Contains(fn.Ret.Type, "*") {
399+
} else if strings.Contains(fn.Ret, "*") {
400400
errCond = "== NULL"
401-
} else if typ, ok := typedefs[fn.Ret.Type]; ok && typ == "void*" {
401+
} else if typ, ok := typedefs[fn.Ret]; ok && typ == "void*" {
402402
errCond = "== NULL"
403403
}
404404
fmt.Fprintf(w, "\tif (_ret %s) *_err_state = mkcgo_err_retrieve();\n", errCond)
@@ -470,7 +470,7 @@ var cstdTypesToCgo = map[string]string{
470470
// the type needs to be casted to goType or not.
471471
func cTypeToGo(t string, cgo bool) (string, bool) {
472472
t, _ = strings.CutPrefix(t, "const ")
473-
if t == "void" {
473+
if isVoid(t) {
474474
return "", true
475475
}
476476
if strings.HasPrefix(t, "void*") {
@@ -515,7 +515,7 @@ func paramToC(i int, p *mkcgo.Param, addType, addName bool) string {
515515
if addType {
516516
s += p.Type
517517
}
518-
if addName && p.Type != "void" {
518+
if addName && !isVoid(p.Type) {
519519
if len(s) > 0 {
520520
s += " "
521521
}
@@ -524,8 +524,9 @@ func paramToC(i int, p *mkcgo.Param, addType, addName bool) string {
524524
return s
525525
}
526526

527-
func retIsVoid(r *mkcgo.Return) bool {
528-
return r.Type == "void"
527+
// isVoid reports whether typ is a void type.
528+
func isVoid(typ string) bool {
529+
return typ == "void"
529530
}
530531

531532
// fnToGoParams returns source code for function f parameters.
@@ -580,7 +581,7 @@ func fnCErrWrapperParams(fn *mkcgo.Func, addName bool) string {
580581
args := fnToCArgs(fn, true, addName)
581582
if len(args) == 0 {
582583
args = errArg
583-
} else if args == "void" {
584+
} else if isVoid(args) {
584585
args = errArg
585586
} else {
586587
args += ", " + errArg
@@ -605,7 +606,7 @@ func fnCNameAvailable(fn *mkcgo.Func) string {
605606

606607
// fnNeedErrWrapper reports whether function fn needs an error wrapper.
607608
func fnNeedErrWrapper(fn *mkcgo.Func) bool {
608-
return !fn.NoError && !retIsVoid(fn.Ret)
609+
return !fn.NoError && !isVoid(fn.Ret)
609610
}
610611

611612
// fnCalledFromGo reports whether function fn is called from Go code.

cmd/mkcgo/main.go

+23-7
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package main
22

33
import (
44
"bytes"
5+
"cmp"
56
"flag"
67
"fmt"
78
"go/format"
89
"log"
910
"os"
11+
"slices"
1012
"strings"
1113

1214
"github.com/golang-fips/openssl/v2/internal/mkcgo"
@@ -35,17 +37,31 @@ func main() {
3537
usage()
3638
}
3739

40+
var src mkcgo.Source
3841
// Parse source files.
39-
src, err := mkcgo.Parse(flag.Args()...)
40-
if err != nil {
41-
log.Fatal(err)
42+
for _, arg := range flag.Args() {
43+
file, err := os.Open(arg)
44+
if err != nil {
45+
log.Fatal(err)
46+
}
47+
err = src.Parse(file)
48+
file.Close()
49+
if err != nil {
50+
log.Fatal(err)
51+
}
4252
}
4353

54+
// Sort functions by name to get deterministic output
55+
// even when the order of the functions in the source file changes.
56+
slices.SortFunc(src.Funcs, func(a, b *mkcgo.Func) int {
57+
return cmp.Compare(a.Name, b.Name)
58+
})
59+
4460
var gobuf, go124buf, hbuf, cbuf bytes.Buffer
45-
generateGo(src, &gobuf)
46-
generateGo124(src, &go124buf)
47-
generateCHeader(src, &hbuf)
48-
generateC(src, &cbuf)
61+
generateGo(&src, &gobuf)
62+
generateGo124(&src, &go124buf)
63+
generateCHeader(&src, &hbuf)
64+
generateC(&src, &cbuf)
4965

5066
// Format the generated Go source code.
5167
godata := goformat(gobuf.Bytes())

hash_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,28 @@ func TestCgo(t *testing.T) {
360360
openssl.SHA256(d.Data[:])
361361
}
362362

363+
func TestHashAllocations(t *testing.T) {
364+
if Asan() {
365+
t.Skip("skipping allocations test with sanitizers")
366+
}
367+
msg := []byte("testing")
368+
n := int(testing.AllocsPerRun(10, func() {
369+
sink ^= openssl.SHA1(msg)[0]
370+
sink ^= openssl.SHA224(msg)[0]
371+
sink ^= openssl.SHA256(msg)[0]
372+
sink ^= openssl.SHA512(msg)[0]
373+
}))
374+
want := 4
375+
if compareCurrentVersion("go1.24") >= 0 {
376+
// The go1.24 compiler is able to optimize the allocation away.
377+
// See cgo_go124.go for more information.
378+
want = 0
379+
}
380+
if n > want {
381+
t.Errorf("allocs = %d, want %d", n, want)
382+
}
383+
}
384+
363385
func BenchmarkSHA256(b *testing.B) {
364386
b.StopTimer()
365387
h := openssl.NewSHA256()

0 commit comments

Comments
 (0)