package config import ( "io" "os" "testing" "blitiri.com.ar/go/chasquid/internal/testlib" "blitiri.com.ar/go/log" "github.com/google/go-cmp/cmp" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" ) func mustCreateConfig(t *testing.T, contents string) (string, string) { tmpDir := testlib.MustTempDir(t) confStr := []byte(contents) err := os.WriteFile(tmpDir+"/chasquid.conf", confStr, 0600) if err != nil { t.Fatalf("Failed to write tmp config: %v", err) } return tmpDir, tmpDir + "/chasquid.conf" } func TestEmptyStruct(t *testing.T) { testLogConfig(&Config{}) } func TestEmptyConfig(t *testing.T) { tmpDir, path := mustCreateConfig(t, "") defer testlib.RemoveIfOk(t, tmpDir) c, err := Load(path, "") if err != nil { t.Fatalf("error loading empty config: %v", err) } // Test the default values are set. defaults := proto.Clone(defaultConfig).(*Config) hostname, _ := os.Hostname() defaults.Hostname = hostname diff := cmp.Diff(defaults, c, protocmp.Transform()) if diff != "" { t.Errorf("Load() mismatch (-want +got):\n%s", diff) } testLogConfig(c) } func TestFullConfig(t *testing.T) { confStr := ` hostname: "joust" smtp_address: ":1234" smtp_address: ":5678" submission_address: ":10001" submission_address: ":10002" monitoring_address: ":1111" max_data_size_mb: 26 suffix_separators: "" ` tmpDir, path := mustCreateConfig(t, confStr) defer testlib.RemoveIfOk(t, tmpDir) overrideStr := ` hostname: "proust" submission_address: ":999" dovecot_auth: true drop_characters: "" ` expected := &Config{ Hostname: "proust", MaxDataSizeMb: 26, SmtpAddress: []string{":1234", ":5678"}, SubmissionAddress: []string{":999"}, SubmissionOverTlsAddress: []string{"systemd"}, MonitoringAddress: ":1111", MailDeliveryAgentBin: "maildrop", MailDeliveryAgentArgs: []string{"-f", "%from%", "-d", "%to_user%"}, DataDir: "/var/lib/chasquid", SuffixSeparators: proto.String(""), DropCharacters: proto.String(""), MailLogPath: "", DovecotAuth: true, } c, err := Load(path, overrideStr) if err != nil { t.Fatalf("error loading non-existent config: %v", err) } diff := cmp.Diff(expected, c, protocmp.Transform()) if diff != "" { t.Errorf("Load() mismatch (-want +got):\n%s", diff) } testLogConfig(c) } func TestErrorLoading(t *testing.T) { c, err := Load("/does/not/exist", "") if err == nil { t.Fatalf("loaded a non-existent config: %v", c) } } func TestBrokenConfig(t *testing.T) { tmpDir, path := mustCreateConfig( t, " this is not a valid protobuf") defer testlib.RemoveIfOk(t, tmpDir) c, err := Load(path, "") if err == nil { t.Fatalf("loaded an invalid config: %v", c) } } func TestBrokenOverride(t *testing.T) { tmpDir, path := mustCreateConfig( t, `hostname: "test"`) defer testlib.RemoveIfOk(t, tmpDir) c, err := Load(path, "broken override") if err == nil { t.Fatalf("loaded an invalid config: %v", c) } } // Run LogConfig, overriding the default logger first. This exercises the // code, we don't yet validate the output, but it is an useful sanity check. func testLogConfig(c *Config) { l := log.New(nopWCloser{io.Discard}) log.Default = l LogConfig(c) } type nopWCloser struct { io.Writer } func (nopWCloser) Close() error { return nil }