package files import ( "fmt" "os" "testing" "time" "codeberg.org/danjones000/my-log/config" "codeberg.org/danjones000/my-log/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestAppend(tt *testing.T) { tt.Run("success", func(t *testing.T) { t.Run("single", appendTestSingle) t.Run("two", appendTestTwoEntries) t.Run("new_line", appendTestAddNewLine) t.Run("no-new-line", appendTestDontAddNewLine) t.Run("dot-folder", appendTestDotFolder) t.Run("no-dot-folder", appendTestDotFolderNo) t.Run("no-ext", appendTestNoExt) }) tt.Run("failure", func(t *testing.T) { t.Run("badEntry", appendTestBadEntry) t.Run("load-err", appendTestConfLoadErr) t.Run("mkdir-err", appendTestMkdirErr) t.Run("append-log-err", appendTestOpenErr) }) } func setupAppendTest(t *testing.T) string { t.Helper() dir := t.ArtifactDir() config.Overrides["input.path"] = dir config.Overrides["input.ext"] = "log" t.Cleanup(func() { delete(config.Overrides, "input.path") delete(config.Overrides, "input.ext") }) return dir } func appendTestSingle(t *testing.T) { dir := setupAppendTest(t) when := time.Now().Local() e := models.Entry{ Title: "Jimmy", Date: when, Fields: []models.Meta{ {"foo", 42}, {"bar", true}, }, } l := models.Log{ Name: "test", Entries: []models.Entry{e}, } err := Append(l) require.NoError(t, err) require.FileExists(t, dir+"/test.log") by, err := os.ReadFile(dir + "/test.log") st := string(by) require.NoError(t, err) assert.Contains(t, st, "Jimmy\n") assert.Contains(t, st, "\n@foo 42") assert.Contains(t, st, "\n@bar true") } func appendTestTwoEntries(t *testing.T) { dir := setupAppendTest(t) when := time.Now().Local() whens := when.Format(models.DateFormat) e := []models.Entry{ {Title: "one", Date: when}, {Title: "two", Date: when}, } l := models.Log{ Name: "test", Entries: e, } err := Append(l) assert.NoError(t, err) require.FileExists(t, dir+"/test.log") by, _ := os.ReadFile(dir + "/test.log") st := string(by) assert.Contains(t, st, fmt.Sprintf("@begin %s - one", whens)) assert.Contains(t, st, fmt.Sprintf("@begin %s - two", whens)) } func appendTestAddNewLine(t *testing.T) { dir := setupAppendTest(t) os.WriteFile(dir+"/test.log", []byte("foo"), 0644) when := time.Now().Local() whens := when.Format(models.DateFormat) e := []models.Entry{ {Title: "one", Date: when, Fields: models.Metas{{"id", "jimmy"}}}, } l := models.Log{ Name: "test", Entries: e, } err := Append(l) assert.NoError(t, err) require.FileExists(t, dir+"/test.log") by, _ := os.ReadFile(dir + "/test.log") exp := fmt.Sprintf("foo\n@begin %s - one\n@id jimmy @end\n", whens) assert.Equal(t, exp, string(by)) } func appendTestDontAddNewLine(t *testing.T) { dir := setupAppendTest(t) os.WriteFile(dir+"/test.log", []byte("foo\n"), 0644) when := time.Now().Local() whens := when.Format(models.DateFormat) e := []models.Entry{ {Title: "one", Date: when, Fields: models.Metas{{"id", "jimmy"}}}, } l := models.Log{ Name: "test", Entries: e, } err := Append(l) assert.NoError(t, err) require.FileExists(t, dir+"/test.log") by, _ := os.ReadFile(dir + "/test.log") exp := fmt.Sprintf("foo\n@begin %s - one\n@id jimmy @end\n", whens) assert.Equal(t, exp, string(by)) } func appendTestBadEntry(t *testing.T) { dir := setupAppendTest(t) e := models.Entry{ Title: "Jimmy", } l := models.Log{ Name: "test", Entries: []models.Entry{e}, } err := Append(l) assert.NoError(t, err) require.FileExists(t, dir+"/test.log") by, _ := os.ReadFile(dir + "/test.log") assert.Equal(t, []byte{}, by) } func appendTestDotFolder(t *testing.T) { config.Overrides["input.dotFolder"] = "true" t.Cleanup(func() { delete(config.Overrides, "input.dotFolder") }) dir := setupAppendTest(t) e := models.Entry{ Title: "something", Date: time.Now(), } l := models.Log{ Name: "sub.test", Entries: []models.Entry{e}, } err := Append(l) require.NoError(t, err) require.FileExists(t, dir+"/sub/test.log") by, err := os.ReadFile(dir + "/sub/test.log") st := string(by) require.NoError(t, err) assert.Contains(t, st, fmt.Sprintf("@begin %s - %s", e.Date.Format(models.DateFormat), e.Title)) } func appendTestDotFolderNo(t *testing.T) { config.Overrides["input.dotFolder"] = "false" t.Cleanup(func() { delete(config.Overrides, "input.dotFolder") }) dir := setupAppendTest(t) e := models.Entry{ Title: "another", Date: time.Now(), } l := models.Log{ Name: "sub.test", Entries: []models.Entry{e}, } err := Append(l) require.NoError(t, err) require.FileExists(t, dir+"/sub.test.log") by, err := os.ReadFile(dir + "/sub.test.log") st := string(by) require.NoError(t, err) assert.Contains(t, st, fmt.Sprintf("@begin %s - %s", e.Date.Format(models.DateFormat), e.Title)) } func appendTestNoExt(t *testing.T) { dir := setupAppendTest(t) config.Overrides["input.ext"] = "" t.Cleanup(func() { config.Overrides["input.ext"] = "log" }) e := models.Entry{ Title: "baz", Date: time.Now(), } l := models.Log{ Name: "foobar", Entries: []models.Entry{e}, } err := Append(l) require.NoError(t, err) require.FileExists(t, dir+"/foobar") by, err := os.ReadFile(dir + "/foobar") st := string(by) require.NoError(t, err) assert.Contains(t, st, fmt.Sprintf("@begin %s - %s", e.Date.Format(models.DateFormat), e.Title)) } func appendTestConfLoadErr(t *testing.T) { dir := t.ArtifactDir() currConf := config.ConfigPath tmp, _ := os.CreateTemp(dir, "app-conf-*.toml") fname := tmp.Name() t.Cleanup(func() { tmp.Close() }) t.Cleanup(func() { os.Remove(fname) }) fmt.Fprintln(tmp, `{"not":"toml"}`) config.ConfigPath = fname t.Cleanup(func() { config.ConfigPath = currConf }) err := Append(models.Log{}) assert.ErrorContains(t, err, "toml") } func appendTestMkdirErr(t *testing.T) { // Don't run this test as root config.Overrides["input.path"] = "/var/my-logs-test" t.Cleanup(func() { delete(config.Overrides, "input.path") }) err := Append(models.Log{}) assert.ErrorContains(t, err, "permission denied") } func appendTestOpenErr(t *testing.T) { dir := setupAppendTest(t) l := models.Log{ Name: "test-open-err", } fname := dir + "/test-open-err.log" os.MkdirAll(dir, 0750) f, _ := os.Create(fname) f.Close() os.Chmod(fname, 0400) err := Append(l) assert.ErrorContains(t, err, "permission denied") }