Files
neko/server/internal/config/capture_test.go
T
Abdellatif Anaflous 73b9d71b0d fix(capture): accept a bare pipeline string in video pipelines entries (#701)
* fix(capture): accept a bare pipeline string in video pipelines entries

NEKO_CAPTURE_VIDEO_PIPELINES expects every entry to be a full pipeline config
object, but the singular capture.video.pipeline option trains people to write
the whole pipeline as a plain string, so a dict like {"high": "ximagesrc ...
! appsink"} failed to unmarshal, the error got reduced to a warn and neko fell
back to the default vp8 pipeline silently, also overriding a directly set
video codec

the json string hook decodes the env value into a generic map, so the shorthand
is restored in the mapstructure chain: a string value for an entry now becomes
VideoConfig{GstPipeline: ...}, the same shape the single pipeline option
produces, object entries are untouched

the new config test drives the production env flow (Init + Set) and fails on
master with the same two warnings the reporter saw

Fixes #689

* feat(capture): add shorthand support for pipeline entries as plain strings.

---------

Co-authored-by: Miroslav Šedivý <sedivy.miro@gmail.com>
2026-09-10 13:45:30 +02:00

59 lines
1.5 KiB
Go

package config
import (
"strings"
"testing"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// loadCaptureFromEnv mirrors the production config flow: env prefix setup,
// flag registration via Init, then value population via Set.
func loadCaptureFromEnv(t *testing.T, pipelines string) *Capture {
t.Helper()
viper.Reset()
viper.SetEnvPrefix("NEKO")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
t.Setenv("NEKO_CAPTURE_VIDEO_PIPELINES", pipelines)
c := &Capture{}
cmd := &cobra.Command{}
if err := c.Init(cmd); err != nil {
t.Fatal(err)
}
c.Set()
return c
}
func TestVideoPipelinesEnv(t *testing.T) {
const pipeline = "ximagesrc display-name={display} show-pointer=false ! appsink name=appsink"
t.Run("object entries with gst_pipeline keep working", func(t *testing.T) {
c := loadCaptureFromEnv(t, `{"high":{"gst_pipeline":"`+pipeline+`"}}`)
cfg, ok := c.VideoPipelines["high"]
if !ok {
t.Fatalf("pipeline entry missing, got %v", c.VideoPipelines)
}
if cfg.GstPipeline != pipeline {
t.Errorf("expected pipeline %q, got %q", pipeline, cfg.GstPipeline)
}
})
t.Run("bare pipeline string entries are accepted", func(t *testing.T) {
c := loadCaptureFromEnv(t, `{"high":"`+pipeline+`"}`)
cfg, ok := c.VideoPipelines["high"]
if !ok {
t.Fatalf("bare pipeline string entry was dropped and neko fell back to the default vp8 pipeline, got %v", c.VideoPipelines)
}
if cfg.GstPipeline != pipeline {
t.Errorf("expected pipeline %q, got %q", pipeline, cfg.GstPipeline)
}
})
}