diff --git a/api/get_indexes.go b/api/get_indexes.go index 28a7b5a14..c46831e3b 100644 --- a/api/get_indexes.go +++ b/api/get_indexes.go @@ -5,6 +5,7 @@ import ( "github.com/deluan/gosonic/repositories" "github.com/deluan/gosonic/utils" "github.com/karlkfi/inject" + "github.com/deluan/gosonic/api/responses" ) type GetIndexesController struct { @@ -17,7 +18,16 @@ func (c *GetIndexesController) Prepare() { } func (c *GetIndexesController) Get() { - if c.repo == nil { - c.CustomAbort(500, "INJECTION NOT WORKING") + 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{} + res.Index = make([]responses.Index, len(indexes)) + for i, idx := range indexes { + res.Index[i].Name = idx.Id + } + + c.Ctx.Output.Body(responses.NewXML(res)) } diff --git a/api/get_indexes_test.go b/api/get_indexes_test.go index 11cb23888..7e0c01f92 100644 --- a/api/get_indexes_test.go +++ b/api/get_indexes_test.go @@ -3,18 +3,82 @@ package api_test import ( "testing" + "github.com/deluan/gosonic/utils" . "github.com/smartystreets/goconvey/convey" "github.com/deluan/gosonic/tests" + "github.com/deluan/gosonic/models" + "github.com/deluan/gosonic/repositories" + "encoding/xml" + "encoding/json" + "fmt" + "errors" + "github.com/deluan/gosonic/api/responses" ) func TestGetIndexes(t *testing.T) { tests.Init(t, false) - - _, w := Get(AddParams("/rest/getIndexes.view"), "TestGetIndexes") + mockRepo := &mockArtistIndex{} + utils.DefineSingleton(new(repositories.ArtistIndex), func() repositories.ArtistIndex { + return mockRepo + }) Convey("Subject: GetIndexes Endpoint", t, func() { - Convey("Status code should be 200", func() { - So(w.Code, ShouldEqual, 200) + Convey("Return fail on DB error", func() { + mockRepo.err = true + _, w := Get(AddParams("/rest/getIndexes.view"), "TestGetIndexes") + + v := responses.Subsonic{} + xml.Unmarshal(w.Body.Bytes(), &v) + So(v.Status, ShouldEqual, "fail") + }) + Convey("When the index is empty", func() { + _, w := Get(AddParams("/rest/getIndexes.view"), "TestGetIndexes") + + Convey("Status code should be 200", func() { + So(w.Code, ShouldEqual, 200) + }) + Convey("It should return valid XML", func() { + v := new(string) + err := xml.Unmarshal(w.Body.Bytes(), &v) + So(err, ShouldBeNil) + }) + Convey("Then it should return an empty collection", func() { + So(w.Body.String(), ShouldContainSubstring, "") + }) + }) + Convey("When the index is not empty", func() { + mockRepo.data = makeMockData(`[{"Id": "A","Artists": []}]`, 2) + _, w := Get(AddParams("/rest/getIndexes.view"), "TestGetIndexes") + + Convey("Then it should return the the items in the response", func() { + So(w.Body.String(), ShouldContainSubstring, ``) + }) + }) + Reset(func() { + mockRepo.data = make([]models.ArtistIndex, 0) + mockRepo.err = false }) }) } + +func makeMockData(j string, length int) []models.ArtistIndex { + data := make([]models.ArtistIndex, length) + err := json.Unmarshal([]byte(j), &data) + if err != nil { + fmt.Println("ERROR: ", err) + } + return data +} + +type mockArtistIndex struct { + repositories.ArtistIndexImpl + data []models.ArtistIndex + err bool +} + +func (m *mockArtistIndex) GetAll() ([]models.ArtistIndex, error) { + if m.err { + return nil, errors.New("Error!") + } + return m.data, nil +} \ No newline at end of file diff --git a/api/responses/error.go b/api/responses/error.go index 040238236..f048b1ec9 100644 --- a/api/responses/error.go +++ b/api/responses/error.go @@ -2,6 +2,7 @@ package responses import ( "encoding/xml" + "fmt" ) const ( @@ -37,13 +38,19 @@ type error struct { Message string `xml:"message,attr"` } -func NewError(errorCode int) []byte { +func NewError(errorCode int, message ...interface{}) []byte { response := NewEmpty() response.Status = "fail" if errors[errorCode] == "" { errorCode = ERROR_GENERIC } - xmlBody, _ := xml.Marshal(&error{Code: errorCode, Message: errors[errorCode]}) + var msg string + if (len(message) == 0) { + msg = errors[errorCode] + } else { + msg = fmt.Sprintf(message[0].(string), message[1:len(message)]...) + } + xmlBody, _ := xml.Marshal(&error{Code: errorCode, Message: msg}) response.Body = xmlBody xmlResponse, _ := xml.Marshal(response) return []byte(xml.Header + string(xmlResponse)) diff --git a/api/responses/indexes.go b/api/responses/indexes.go new file mode 100644 index 000000000..718cc9130 --- /dev/null +++ b/api/responses/indexes.go @@ -0,0 +1,14 @@ +package responses + +import "encoding/xml" + +type Index struct { + XMLName xml.Name `xml:"index"` + Name string `xml:"name,attr"` +} + +type ArtistIndex struct { + XMLName xml.Name `xml:"indexes"` + Index []Index `xml:"indexes"` +} + diff --git a/conf/inject_definitions.go b/conf/inject_definitions.go index b3a3804ab..eff8e885d 100644 --- a/conf/inject_definitions.go +++ b/conf/inject_definitions.go @@ -1,15 +1,10 @@ package conf import ( - "github.com/deluan/gosonic/repositories" "github.com/deluan/gosonic/utils" - "github.com/karlkfi/inject" + "github.com/deluan/gosonic/repositories" ) -func define(ptr interface{}, constructor interface{}, argPtrs ...interface{}) { - utils.Graph.Define(ptr, inject.NewProvider(constructor, argPtrs...)) -} - func init () { - define(new(repositories.ArtistIndex), repositories.NewArtistIndexRepository) + utils.DefineSingleton(new(repositories.ArtistIndex), repositories.NewArtistIndexRepository) } diff --git a/repositories/index_repository.go b/repositories/index_repository.go index 26e3fff01..ea378b479 100644 --- a/repositories/index_repository.go +++ b/repositories/index_repository.go @@ -11,30 +11,30 @@ type ArtistIndex interface { GetAll() ([]models.ArtistIndex, error) } -type artistIndex struct { +type ArtistIndexImpl struct { BaseRepository } func NewArtistIndexRepository() ArtistIndex { - r := &artistIndex{} + r := &ArtistIndexImpl{} r.init("index", &models.ArtistIndex{}) return r } -func (r *artistIndex) Put(m *models.ArtistIndex) error { +func (r *ArtistIndexImpl) Put(m *models.ArtistIndex) error { if m.Id == "" { return errors.New("Id is not set") } return r.saveOrUpdate(m.Id, m) } -func (r *artistIndex) Get(id string) (*models.ArtistIndex, error) { +func (r *ArtistIndexImpl) Get(id string) (*models.ArtistIndex, error) { var rec interface{} rec, err := r.readEntity(id) return rec.(*models.ArtistIndex), err } -func (r *artistIndex) GetAll() ([]models.ArtistIndex, error) { +func (r *ArtistIndexImpl) GetAll() ([]models.ArtistIndex, error) { var indices = make([]models.ArtistIndex, 0) err := r.loadAll(&indices) return indices, err diff --git a/utils/graph.go b/utils/graph.go index 0f1c08ae5..f37d6ee36 100644 --- a/utils/graph.go +++ b/utils/graph.go @@ -1,9 +1,27 @@ package utils -import "github.com/karlkfi/inject" +import ( + "github.com/karlkfi/inject" + "reflect" +) var Graph inject.Graph +var ( + definitions map[reflect.Type]interface{} +) + +func DefineSingleton(ptr interface{}, constructor interface{}, args ...interface{}) { + typ := reflect.TypeOf(ptr) + if definitions[typ] == nil { + Graph.Define(ptr, inject.NewProvider(constructor, args...)) + } else { + Graph.Define(definitions[typ], inject.NewProvider(constructor, args...)) + } + definitions[typ] = ptr +} + func init() { + definitions = make(map[reflect.Type]interface{}) Graph = inject.NewGraph() }