package sipcall import ( "context" "os" "path/filepath" "strings" "testing" ) func TestNativeRunnerRejectsMissingAsteriskWithoutDialing(t *testing.T) { c := fixtureConfig(t) c.ConfigDir = t.TempDir() c.Binary = filepath.Join(t.TempDir(), "missing-asterisk") r, err := Run(context.Background(), c, "18601010101", false) if err == nil || r == nil || r.Status != "not_dialed" || r.CallID != "" || r.AnsweredAt != nil { t.Fatalf("invalid native host must never attempt a call: %+v %v", r, err) } if _, err = os.Stat(filepath.Join(r.Directory, "result.json")); err != nil { t.Fatal("native preflight failure needs detail") } if r, err = Run(context.Background(), c, "+123", false); err == nil || r != nil { t.Fatal("invalid input must fail before even opening host state") } } func TestNativeExclusiveLockAndIdleCheck(t *testing.T) { c := fixtureConfig(t) c.ConfigDir = t.TempDir() c.Binary = filepath.Join(t.TempDir(), "asterisk") if err := os.WriteFile(c.Binary, []byte("#!/bin/sh\necho '1 active channel'\n"), 0700); err != nil { t.Fatal(err) } first := &nativeHost{config: c} second := &nativeHost{config: c} if err := first.CheckIdle(context.Background()); err == nil || !strings.Contains(err.Error(), "active channels") { t.Fatalf("active call not rejected: %v", err) } if err := second.CheckIdle(context.Background()); err == nil || !strings.Contains(err.Error(), "owns") { t.Fatalf("simultaneous owner not rejected: %v", err) } if err := first.Close(); err != nil { t.Fatal(err) } if err := second.Close(); err != nil { t.Fatal(err) } third := &nativeHost{config: c} if err := third.CheckIdle(context.Background()); err == nil || strings.Contains(err.Error(), "owns") { t.Fatalf("lock was not released: %v", err) } if err := third.Close(); err != nil { t.Fatal(err) } } func TestNativeCLILeavesPrivateDiagnosticsAndDoesNotHideFailure(t *testing.T) { c := fixtureConfig(t) c.ConfigDir = t.TempDir() c.Binary = filepath.Join(t.TempDir(), "asterisk") if err := os.WriteFile(c.Binary, []byte("#!/bin/sh\necho 'diagnostic command failure' >&2\nexit 3\n"), 0700); err != nil { t.Fatal(err) } if _, err := asteriskCLI(context.Background(), c, "pjsip reload"); err == nil || !strings.Contains(err.Error(), "exit status 3") { t.Fatalf("command failure hidden: %v", err) } path := filepath.Join(c.resultDir, "asterisk-cli.log") data, err := os.ReadFile(path) if err != nil || !strings.Contains(string(data), "diagnostic command failure") { t.Fatalf("missing private root-cause output: %v", err) } info, err := os.Stat(path) if err != nil || info.Mode().Perm() != 0600 { t.Fatal("native diagnostics must be private") } }