package media_test import ( "context" "fmt" "net" "os" "path/filepath" "testing" "time" "git.ilapage.cn/ila/yovision/Sense/server/app/sense/media" ) func freeAddress(t *testing.T) string { t.Helper() listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } address := listener.Addr().String() if err = listener.Close(); err != nil { t.Fatal(err) } return address } func TestRealMediaMTXControlLifecycle(t *testing.T) { binary := os.Getenv("SENSE_MEDIAMTX_TEST_BINARY") if binary == "" { t.Skip("set SENSE_MEDIAMTX_TEST_BINARY to run the real MediaMTX integration") } apiAddress, rtspAddress := freeAddress(t), freeAddress(t) configPath := filepath.Join(t.TempDir(), "mediamtx.yml") config := fmt.Sprintf("logLevel: warn\napi: true\napiAddress: %s\nrtspAddress: %s\nrtmp: false\nhls: false\nwebrtc: false\nsrt: false\nplayback: false\npaths: {}\n", apiAddress, rtspAddress) if err := os.WriteFile(configPath, []byte(config), 0o600); err != nil { t.Fatal(err) } controller, err := media.NewHTTPController("http://" + apiAddress) if err != nil { t.Fatal(err) } supervisor := media.NewSupervisor(binary, configPath) if err = supervisor.Start(context.Background()); err != nil { t.Fatal(err) } t.Cleanup(func() { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() _ = supervisor.Stop(ctx) }) deadline := time.Now().Add(8 * time.Second) for { err = controller.Health(context.Background()) if err == nil { break } if time.Now().After(deadline) { t.Fatalf("MediaMTX did not become ready: %v", err) } time.Sleep(100 * time.Millisecond) } source := media.Source{Path: "sense_integration", URI: "rtsp://127.0.0.1:65530/test", Username: "synthetic-user", Password: "synthetic-password"} if err = controller.Apply(context.Background(), source); err != nil { t.Fatal(err) } if err = controller.Apply(context.Background(), source); err != nil { t.Fatalf("replace must be idempotent: %v", err) } if err = controller.Delete(context.Background(), source.Path); err != nil { t.Fatal(err) } }