diff --git a/api/api_test.go b/api/api_test.go index d6f8cf67c..04acdfa97 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -6,6 +6,7 @@ import ( "net/http" "net/http/httptest" _ "github.com/deluan/gosonic/conf" + "strings" ) const ( @@ -15,8 +16,12 @@ const ( testVersion = "1.0.0" ) -func AddParams(url string) string { - return fmt.Sprintf("%s?u=%s&p=%s&c=%s&v=%s", url, testUser, testPassword, testClient, testVersion) +func AddParams(endpoint string, params ...string) string { + url := fmt.Sprintf("%s?u=%s&p=%s&c=%s&v=%s", endpoint, testUser, testPassword, testClient, testVersion) + if len(params) > 0 { + url = url + "&" + strings.Join(params, "&") + } + return url } func Get(url string, testCase string) (*http.Request, *httptest.ResponseRecorder) { diff --git a/api/get_indexes.go b/api/get_indexes.go index 39bb1d39c..5e3d34384 100644 --- a/api/get_indexes.go +++ b/api/get_indexes.go @@ -7,11 +7,12 @@ import ( "github.com/karlkfi/inject" "github.com/deluan/gosonic/api/responses" "github.com/deluan/gosonic/consts" + "strconv" ) type GetIndexesController struct { beego.Controller - repo repositories.ArtistIndex + repo repositories.ArtistIndex properties repositories.Property } @@ -21,28 +22,42 @@ func (c *GetIndexesController) Prepare() { } func (c *GetIndexesController) Get() { - indexes, err := c.repo.GetAll() - if err != nil { - beego.Error("Error retrieving Indexes:", err) - c.CustomAbort(200, string(responses.NewError(responses.ERROR_GENERIC, "Internal Error"))) - } - res := &responses.ArtistIndex{} + var err error - res.LastModified, err = c.properties.Get(consts.LastScan) + ifModifiedSince := c.Input().Get("ifModifiedSince") + if ifModifiedSince == "" { + ifModifiedSince = "0" + } + + res := &responses.ArtistIndex{} + res.IgnoredArticles = beego.AppConfig.String("ignoredArticles") + + res.LastModified, err = c.properties.DefaultGet(consts.LastScan, "-1") if err != nil { beego.Error("Error retrieving LastScan property:", err) c.CustomAbort(200, string(responses.NewError(responses.ERROR_GENERIC, "Internal Error"))) } - res.IgnoredArticles = beego.AppConfig.String("ignoredArticles") - res.Index = make([]responses.IdxIndex, len(indexes)) - for i, idx := range indexes { - res.Index[i].Name = idx.Id - res.Index[i].Artists = make([]responses.IdxArtist, len(idx.Artists)) - for j, a := range idx.Artists { - res.Index[i].Artists[j].Id = a.ArtistId - res.Index[i].Artists[j].Name = a.Artist + i, _ := strconv.Atoi(ifModifiedSince) + l, _ := strconv.Atoi(res.LastModified) + + if (l > i) { + indexes, err := c.repo.GetAll() + if err != nil { + beego.Error("Error retrieving Indexes:", err) + c.CustomAbort(200, string(responses.NewError(responses.ERROR_GENERIC, "Internal Error"))) } + + res.Index = make([]responses.IdxIndex, len(indexes)) + for i, idx := range indexes { + res.Index[i].Name = idx.Id + res.Index[i].Artists = make([]responses.IdxArtist, len(idx.Artists)) + for j, a := range idx.Artists { + res.Index[i].Artists[j].Id = a.ArtistId + res.Index[i].Artists[j].Name = a.Artist + } + } + } c.Ctx.Output.Body(responses.NewXML(res)) diff --git a/api/get_indexes_test.go b/api/get_indexes_test.go index e391366f4..044c934ba 100644 --- a/api/get_indexes_test.go +++ b/api/get_indexes_test.go @@ -28,10 +28,15 @@ func TestGetIndexes(t *testing.T) { return propRepo }) + mockRepo.SetData("[]", 0) + mockRepo.SetError(false) + propRepo.Put(consts.LastScan, "1") + propRepo.SetError(false) + Convey("Subject: GetIndexes Endpoint", t, func() { Convey("Return fail on Index Table error", func() { mockRepo.SetError(true) - _, w := Get(AddParams("/rest/getIndexes.view"), "TestGetIndexes") + _, w := Get(AddParams("/rest/getIndexes.view", "ifModifiedSince=0"), "TestGetIndexes") v := responses.Subsonic{} xml.Unmarshal(w.Body.Bytes(), &v) @@ -72,6 +77,26 @@ func TestGetIndexes(t *testing.T) { ``) }) }) + Convey("And it should return empty if 'ifModifiedSince' is more recent than the index", func() { + mockRepo.SetData(`[{"Id": "A","Artists": [ + {"ArtistId": "21", "Artist": "Afrolicious"} + ]}]`, 2) + propRepo.Put(consts.LastScan, "1") + + _, w := Get(AddParams("/rest/getIndexes.view", "ifModifiedSince=2"), "TestGetIndexes") + + So(w.Body.String(), ShouldContainSubstring, emptyResponse) + }) + Convey("And it should return empty if 'ifModifiedSince' is the asme as tie index last update", func() { + mockRepo.SetData(`[{"Id": "A","Artists": [ + {"ArtistId": "21", "Artist": "Afrolicious"} + ]}]`, 2) + propRepo.Put(consts.LastScan, "1") + + _, w := Get(AddParams("/rest/getIndexes.view", "ifModifiedSince=1"), "TestGetIndexes") + + So(w.Body.String(), ShouldContainSubstring, emptyResponse) + }) Reset(func() { mockRepo.SetData("[]", 0) mockRepo.SetError(false) diff --git a/repositories/property_repository.go b/repositories/property_repository.go index 85d6235b3..7578afa35 100644 --- a/repositories/property_repository.go +++ b/repositories/property_repository.go @@ -8,6 +8,7 @@ import ( type Property interface { Put(id string, value string) error Get(id string) (string, error) + DefaultGet(id string, defaultValue string) (string, error) } type PropertyImpl struct { @@ -33,3 +34,13 @@ func (r *PropertyImpl) Get(id string) (string, error) { rec, err := r.readEntity(id) return rec.(*models.Property).Value, err } + +func (r* PropertyImpl) DefaultGet(id string, defaultValue string) (string, error) { + v, err := r.Get(id) + + if v == "" { + v = defaultValue + } + + return v, err +} diff --git a/tests/mocks/mock_property_repo_tests.go b/tests/mocks/mock_property_repo_tests.go index 5946a3528..72fadb101 100644 --- a/tests/mocks/mock_property_repo_tests.go +++ b/tests/mocks/mock_property_repo_tests.go @@ -20,7 +20,7 @@ func (m *MockProperty) SetError(err bool) { } func (m *MockProperty) Put(id string, value string) error { - if (m.err) { + if m.err { return errors.New("Error!") } m.data[id] = value @@ -28,9 +28,19 @@ func (m *MockProperty) Put(id string, value string) error { } func (m *MockProperty) Get(id string) (string, error) { - if (m.err) { + if m.err { return "", errors.New("Error!") } else { return m.data[id], nil } -} \ No newline at end of file +} + +func (m *MockProperty) DefaultGet(id string, defaultValue string) (string, error) { + v, err := m.Get(id) + + if v == "" { + v = defaultValue + } + + return v, err +}