package sipcall import ( "bytes" "context" "fmt" "os" "strings" "testing" ) func TestNativePJSIPModuleReloadIsUsedAndConfirmed(t *testing.T) { c, path, base := stageFixture(t) fixture := configCLI(c, path) var reloads int cli := func(ctx context.Context, command string) ([]byte, error) { switch command { case "pjsip reload": return []byte("No such command 'pjsip reload' (type 'core show help pjsip reload' for other possible commands)\n"), nil case "module reload res_pjsip.so": reloads++ return []byte("Module 'res_pjsip.so' reloaded successfully.\n"), nil default: return fixture(ctx, command) } } restore, err := applyConfiguration(context.Background(), c, cli) if err != nil { t.Fatalf("supported native reload failed: %v", err) } if err := restore(); err != nil { t.Fatal(err) } if reloads != 2 { t.Fatalf("expected native module reload for apply and restore, got %d", reloads) } data, err := os.ReadFile(path) if err != nil || !bytes.Equal(data, base) { t.Fatal("original configuration not restored") } } func TestPJSIPReloadRejectsZeroExitWithoutModuleConfirmation(t *testing.T) { for _, output := range []string{ "No such command 'module reload res_pjsip.so'\n", "Module 'res_pjsip.so' could not be reloaded.\n", "Module 'res_other.so' reloaded successfully.\n", "", } { for _, phase := range []string{"apply", "restore"} { t.Run(fmt.Sprintf("%s/%q", phase, output), func(t *testing.T) { c, path, _ := stageFixture(t) fixture := configCLI(c, path) var reloads, runtimeReads int cli := func(ctx context.Context, command string) ([]byte, error) { if command == "module reload res_pjsip.so" { reloads++ if phase == "apply" || reloads == 2 { return []byte(output), nil } return []byte("Module 'res_pjsip.so' reloaded successfully.\n"), nil } if strings.HasPrefix(command, "pjsip show endpoint ") { runtimeReads++ } return fixture(ctx, command) } restore, err := applyConfiguration(context.Background(), c, cli) if phase == "apply" { if err == nil || !strings.Contains(err.Error(), "reload not confirmed") || runtimeReads != 0 { t.Fatalf("unconfirmed reload must fail before readback: error=%v reads=%d", err, runtimeReads) } return } if err != nil { t.Fatal(err) } if err = restore(); err == nil || !strings.Contains(err.Error(), "reload not confirmed") { t.Fatalf("unconfirmed restoration reload accepted: %v", err) } }) } } }