added integration test and github workflow action

This commit is contained in:
swdee
2025-04-20 19:05:52 +12:00
parent 18bc88f956
commit ba035c4847
3 changed files with 188 additions and 23 deletions

View File

@@ -8,19 +8,67 @@ on:
jobs:
lint:
name: Lint & fmt
runs-on: ubuntu-latest
name: Lint and gofmt
runs-on: [ self-hosted, rk3588, npu ]
container:
image: swdee/go-rknnlite:latest
# pass in NPU
options: >-
--device /dev/dri:/dev/dri
-v /usr/include/rknn_api.h:/usr/include/rknn_api.h
-v /usr/lib/librknnrt.so:/usr/lib/librknnrt.so
steps:
- uses: actions/checkout@v3
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v4
with:
version: v1.58.2
- name: Check gofmt
- name: Checkout code
uses: actions/checkout@v3
- name: Fetch Go modules
run: go mod download
- name: Install nodejs for golangci
run: |
if diff -u <(echo -n) <(gofmt -d .); then
echo "All files are gofmted"
else
echo "Please run gofmt -s -w ."
exit 1
fi
apt-get update
apt-get install -y nodejs
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v7
with:
version: v2.1.2
args: -v --config .golangci.yml
integration-test:
name: Integration on RK3588
runs-on: [ self-hosted, rk3588, npu ]
container:
image: swdee/go-rknnlite:latest
# pass in NPU
options: >-
--device /dev/dri:/dev/dri
-v /usr/include/rknn_api.h:/usr/include/rknn_api.h
-v /usr/lib/librknnrt.so:/usr/lib/librknnrt.so
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Fetch Go modules
run: go mod download
- name: Download model & image for integration test
run: |
mkdir -p example/data
curl -L \
https://raw.githubusercontent.com/swdee/go-rknnlite-data/master/mobilenet_v1-rk3588.rknn \
-o example/data/mobilenet_v1-rk3588.rknn
curl -L \
https://raw.githubusercontent.com/swdee/go-rknnlite-data/master/cat_224x224.jpg \
-o example/data/cat_224x224.jpg
- name: Run integration tests
run: |
export RKNN_MODEL=example/data/mobilenet_v1-rk3588.rknn
export RKNN_IMAGE=example/data/cat_224x224.jpg
go test -timeout 5m -tags=integration ./...

View File

@@ -1,14 +1,20 @@
version: "2"
run:
timeout: 5m # give linters up to 5m to complete
tests: true # also run linters on *_test.go
issues:
exclude-rules:
- linters:
- typecheck
path: ^example/ppocr/.*\.go$
text: "main redeclared in this block" # ignore multiple main() declaractions in ppocr directory
linters:
default: none
enable:
- govet
- unused
linters-settings:
errcheck:
ignore: '' # workaround to bug #4743, fix to upgrade to v1.62.0+
formatters:
enable:
- gofmt
issues:
max-issues-per-linter: 0
max-same-issues: 0

View File

@@ -0,0 +1,111 @@
//go:build integration
// +build integration
package rknnlite
import (
"gocv.io/x/gocv"
"image"
"os"
"testing"
)
func TestMobileNetTop5(t *testing.T) {
modelFile := os.Getenv("RKNN_MODEL")
if modelFile == "" {
t.Fatalf("No Model file provided in RKNN_MODEL")
}
imgFile := os.Getenv("RKNN_IMAGE")
if imgFile == "" {
t.Fatalf("No Image file provided in RKNN_IMAGE")
}
// Initialize runtime
rt, err := NewRuntime(modelFile, NPUCoreAuto)
if err != nil {
t.Fatalf("NewRuntime failed: %v", err)
}
defer rt.Close()
// load image
img := gocv.IMRead(imgFile, gocv.IMReadColor)
if img.Empty() {
t.Fatalf("Error reading image from: %s", imgFile)
}
// convert colorspace and resize image
rgbImg := gocv.NewMat()
gocv.CvtColor(img, &rgbImg, gocv.ColorBGRToRGB)
cropImg := rgbImg.Clone()
scaleSize := image.Pt(int(rt.InputAttrs()[0].Dims[1]), int(rt.InputAttrs()[0].Dims[2]))
gocv.Resize(rgbImg, &cropImg, scaleSize, 0, 0, gocv.InterpolationArea)
defer img.Close()
defer rgbImg.Close()
defer cropImg.Close()
// run inference
outputs, err := rt.Inference([]gocv.Mat{cropImg})
if err != nil {
t.Fatalf("Inference error: %v", err)
}
defer func() {
if err := outputs.Free(); err != nil {
t.Errorf("Free Outputs: %v", err)
}
}()
// Extract Top5
top5 := GetTop5(outputs.Output)
if len(top5) != 5 {
t.Fatalf("expected 5 results, got %d", len(top5))
}
// Probabilities must be in [0,1] and descending
for i, p := range top5 {
if p.Probability < 0 || p.Probability > 1 {
t.Errorf("entry %d: probability %v out of [0,1]", i, p.Probability)
}
if i > 0 && p.Probability > top5[i-1].Probability {
t.Errorf("probabilities not descending: index %d has %v > previous %v",
i, p.Probability, top5[i-1].Probability)
}
}
// Label indices must be in range [0, numClasses)
numClasses := int(rt.OutputAttrs()[0].Dims[1])
for i, p := range top5 {
if int(p.LabelIndex) < 0 || int(p.LabelIndex) >= numClasses {
t.Errorf("entry %d: label index %d out of range [0,%d)", i, p.LabelIndex, numClasses)
}
}
// Sanity check: at least one probability above a tiny epsilon
const eps = 1e-3
var found bool
for _, p := range top5 {
if p.Probability > eps {
found = true
break
}
}
if !found {
t.Errorf("all probabilities ≤ %v, something's wrong", eps)
}
}