Beispiel #1
0
// Fetch returns a group from the collection with the given path.
func (l *Library) Fetch(c index.Collection, path []string) (group, error) {
	if len(path) == 0 {
		return build(c, index.Key("Root")), nil
	}

	var g index.Group = c
	k := index.Key(path[0])
	g = c.Get(k)

	if g == nil {
		return group{}, fmt.Errorf("invalid path: near '%v'", path[0])
	}

	index.Sort(g.Tracks(), index.MultiSort(index.SortByInt("DiscNumber"), index.SortByInt("TrackNumber")))
	g = index.Transform(g, index.SplitList("Artist", "AlbumArtist", "Composer"))
	c = index.Collect(g, index.ByPrefix("Name"))
	g = index.SubTransform(c, index.TrimEnumPrefix)
	g = index.SumGroupIntAttr("TotalTime", g)
	commonFields := []attr.Interface{
		attr.String("Album"),
		attr.Strings("Artist"),
		attr.Strings("AlbumArtist"),
		attr.Strings("Composer"),
		attr.Int("Year"),
		attr.Int("BitRate"),
		attr.Int("DiscNumber"),
	}
	g = index.CommonGroupAttr(commonFields, g)
	g = index.RemoveEmptyCollections(g)

	for i, p := range path[1:] {
		var ok bool
		c, ok = g.(index.Collection)
		if !ok {
			return group{}, fmt.Errorf("retrieved Group is not a Collection")
		}

		k = index.Key(p)
		g = c.Get(k)
		if g == nil {
			return group{}, fmt.Errorf("invalid path near '%v'", path[1:][i])
		}

		if _, ok = g.(index.Collection); !ok {
			if i == len(path[1:])-1 {
				break
			}
			return group{}, fmt.Errorf("retrieved Group isn't a Collection: %v", p)
		}
	}
	if g == nil {
		return group{}, fmt.Errorf("could not find group")
	}
	g = index.FirstTrackAttr(attr.String("ID"), g)

	return build(g, k), nil
}
Beispiel #2
0
func TestByAttr(t *testing.T) {
	trackListing := []testTrack{
		{Name: "A", Album: "Album A"},
		{Name: "B", Album: "Album A"},
		{Name: "C", Album: "Album B"},
		{Name: "D", Album: "Album B"},
	}

	expected := map[string][]Track{
		"Album A": {trackListing[0], trackListing[1]},
		"Album B": {trackListing[2], trackListing[3]},
	}

	attrGroup := By(attr.String("Album")).Collect(testTracker(trackListing[:]))
	SortKeysByGroupName(attrGroup)

	nkm := nameKeyMap(attrGroup)
	for n, v := range expected {
		k, ok := nkm[n]
		if !ok {
			t.Errorf("%v is not a key of nkm", n)
		}

		gr := attrGroup.Get(Key(k))
		if gr == nil {
			t.Errorf("attrGroup.Get(%v) = nil, expected non-nil!", k)
		}

		got := gr.Tracks()
		if !reflect.DeepEqual(v, got) {
			t.Errorf("gr.Tracks() = %#v, expected: %#v", got, v)
		}
	}
}
Beispiel #3
0
func TestSubCollect(t *testing.T) {
	album1 := "Mahler Symphonies"
	album2 := "Shostakovich Symphonies"

	prefix1 := "Symphony No. 1 in D"
	prefix2 := "A B C Y"

	trackListing := []testTrack{
		{Name: prefix1 + ": I. Langsam, schleppend - Immer sehr gemächlich", Album: album1},
		{Name: prefix1 + ": II. Kräftig bewegt, doch nicht zu schnell - Recht gemächlich", Album: album1},
		{Name: prefix1 + ": III. Feierlich und gemessen, ohne zu schleppen", Album: album1},
		{Name: prefix2 + " 1", Album: album2},
		{Name: prefix2 + " 2", Album: album2},
		{Name: prefix2 + " 2", Album: album2},
	}
	expectedAlbums := []string{album1, album2}

	albums := By(attr.String("Album")).Collect(testTracker(trackListing[:]))
	SortKeysByGroupName(albums)
	albNames := names(albums)

	if !reflect.DeepEqual(albNames, expectedAlbums) {
		t.Errorf("albums.Names() = %v, expected %#v", names, expectedAlbums)
	}

	albPfx := SubCollect(albums, ByPrefix("Name"))
	albPfxNames := names(albPfx)

	if !reflect.DeepEqual(albPfxNames, expectedAlbums[:]) {
		t.Errorf("albPfx.Names() = %v, expected %#v", albPfxNames, expectedAlbums)
	}

	nkm := nameKeyMap(albPfx)
	prefixGroup := albPfx.Get(nkm[album1])
	pfxCol, ok := prefixGroup.(Collection)
	if !ok {
		t.Errorf("expected a Collection, but got %T", prefixGroup)
	}

	pfxColNames := names(pfxCol)
	expectedPrefixGroupNames := []string{prefix1}

	if !reflect.DeepEqual(pfxColNames, expectedPrefixGroupNames) {
		t.Errorf("prefixCollection.Names() = %#v, expected %#v", pfxColNames, expectedPrefixGroupNames)
	}
}
Beispiel #4
0
func buildRootCollection(l index.Library) index.Collection {
	root := index.Collect(l, index.By(attr.String("Album")))
	index.SortKeysByGroupName(root)
	return root
}
Beispiel #5
0
func TestFirstTrackAttr(t *testing.T) {
	table := []struct {
		in    Group
		field attr.Interface
		out   interface{}
	}{
		// One group with no tracks
		{
			in: group{
				name: "Group One",
			},
			field: attr.String("Name"),
			out:   nil,
		},

		{
			in: group{
				name: "Group One",
			},
			field: attr.Strings("Artist"),
			out:   nil,
		},

		// One group with one track
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
				},
			},
			field: attr.String("Name"),
			out:   "Track One",
		},

		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Artist: "Track One",
					},
				},
			},
			field: attr.Strings("Artist"),
			out:   []string{"Track One"},
		},

		// One group with two tracks, empty first field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{},
					testTrack{
						Name:   "Track Two",
						Artist: "Artist One",
					},
				},
			},
			field: attr.String("Artist"),
			out:   nil,
		},

		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{},
					testTrack{
						Name:   "Track Two",
						Artist: "Artist One",
					},
				},
			},
			field: attr.Strings("Artist"),
			out:   nil,
		},

		// One collection, one group, one track
		{
			in: testCol{
				name: "Group One (collection)",
				keys: []Key{"Group-One-One"},
				grps: map[Key]Group{
					"Group-One-One": group{
						name: "Group One (One)",
						tracks: []Track{
							testTrack{
								Name: "Track One",
							},
						},
					},
				},
			},
			field: attr.String("Name"),
			out:   "Track One",
		},

		// One group with one track
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Duration: 1234,
					},
				},
			},
			field: attr.Int("Duration"),
			out:   1234,
		},

		// One group with two tracks, empty first field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{},
					testTrack{
						Duration: 1234,
						Artist:   "Artist One",
					},
				},
			},
			field: attr.Int("Duration"),
			out:   nil,
		},

		// One collection, one group, one track
		{
			in: testCol{
				name: "Group One (collection)",
				keys: []Key{"Group-One-One"},
				grps: map[Key]Group{
					"Group-One-One": group{
						name: "Group One (One)",
						tracks: []Track{
							testTrack{
								Duration: 1234,
							},
						},
					},
				},
			},
			field: attr.Int("Duration"),
			out:   1234,
		},
	}

	for ii, tt := range table {
		g := FirstTrackAttr(tt.field, tt.in)
		got := g.Field(tt.field.Name())

		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected %#v", ii, got, tt.out)
		}
	}
}
Beispiel #6
0
func TestCommonGroupAttr(t *testing.T) {
	table := []struct {
		in     Group
		fields []attr.Interface
		out    []interface{}
	}{
		// One group with one track, unset common field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
				},
			},
			fields: []attr.Interface{attr.String("Artist")},
			out:    []interface{}{nil},
		},

		// One group with one track, unset common int field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Empty common field",
					},
				},
			},
			fields: []attr.Interface{attr.Int("Year")},
			out:    []interface{}{nil},
		},

		// One group with one track, unset common (string) and (int) fields
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
				},
			},
			fields: []attr.Interface{attr.String("Artist"), attr.Int("Year")},
			out:    []interface{}{nil, nil},
		},

		// One group with one track, set strings field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						stringsMap: map[string][]string{
							"Artist": []string{"First Artist", "Second Artist"},
						},
					},
				},
			},
			fields: []attr.Interface{attr.Strings("Artist")},
			out:    []interface{}{[]string{"First Artist", "Second Artist"}},
		},

		// One group with two tracks, check intersection of artists list
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						stringsMap: map[string][]string{
							"Artist": []string{"First Artist", "Second Artist"},
						},
					},
					testTrack{
						stringsMap: map[string][]string{
							"Artist": []string{"First Artist"},
						},
					},
				},
			},
			fields: []attr.Interface{attr.Strings("Artist")},
			out:    []interface{}{[]string{"First Artist"}},
		},

		// One group with two tracks, empty first string & int fields
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
					testTrack{
						Name:   "Track Two",
						Artist: "Artist One",
						Year:   1984,
					},
				},
			},
			fields: []attr.Interface{attr.String("Artist"), attr.Int("Year")},
			out:    []interface{}{nil, nil},
		},

		// One group with two tracks, empty first field
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name: "Track One",
					},
					testTrack{
						Name: "Track Two",
						Year: 1985,
					},
				},
			},
			fields: []attr.Interface{attr.Int("Year")},
			out:    []interface{}{nil},
		},

		// One group with one track, common string/int fields
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Artist:   "Artist One",
						Composer: "Composer One",
						Year:     1984,
					},
				},
			},
			fields: []attr.Interface{attr.String("Artist"), attr.Int("Year")},
			out:    []interface{}{"Artist One", 1984},
		},

		// One group with one track, common string fields for Artist and Composer
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Artist:   "Artist One",
						Composer: "Composer One",
					},
				},
			},
			fields: []attr.Interface{attr.String("Artist"), attr.String("Composer")},
			out:    []interface{}{"Artist One", "Composer One"},
		},

		// One group with two tracks, common fields across pairs
		{
			in: group{
				name: "Group One",
				tracks: []Track{
					testTrack{
						Name:     "Track One",
						Artist:   "Artist One",
						Composer: "Composer One",
					},
					testTrack{
						Name:     "Track Two",
						Artist:   "Artist Two",
						Composer: "Composer One",
					},
				},
			},
			fields: []attr.Interface{attr.String("Artist"), attr.String("Composer")},
			out:    []interface{}{nil, "Composer One"},
		},

		// One collection, one group, one track
		{
			in: testCol{
				name: "Group Three (collection)",
				keys: []Key{"Group-Three-One"},
				grps: map[Key]Group{
					"Group-Three-One": group{
						name: "Group One (Three)",
						tracks: []Track{
							testTrack{
								Name:   "Track One",
								Artist: "Artist One",
							},
						},
					},
				},
			},
			fields: []attr.Interface{attr.String("Artist"), attr.String("Composer")},
			out:    []interface{}{"Artist One", nil},
		},

		// One collection, three groups, many tracks!
		{
			in: testCol{
				name: "Root",
				keys: []Key{"Group-One", "Group-Two", "Group-Three"},
				grps: map[Key]Group{
					"Group-One": group{
						name: "Group One",
						tracks: []Track{
							testTrack{
								Name:   "Track One",
								Artist: "Artist One",
								Year:   1984,
							},
						},
					},
					"Group-Two": group{
						name: "Group Two",
						tracks: []Track{
							testTrack{
								Name:   "Track One",
								Artist: "Artist One",
								Year:   1984,
							},
							testTrack{
								Name:   "Track Two",
								Artist: "Artist One",
								Year:   1984,
							},
						},
					},
					"Group-Three": testCol{
						name: "Group Three (collection)",
						keys: []Key{"Group-Three-One"},
						grps: map[Key]Group{
							"Group-Three-One": group{
								name: "Group One (Three)",
								tracks: []Track{
									testTrack{
										Name:   "Track One",
										Artist: "Artist One",
										Year:   1984,
									},
									testTrack{
										Name:   "Track Two",
										Artist: "Artist One",
										Year:   2000,
									},
									testTrack{
										Name:   "Track One",
										Artist: "Artist One",
										Year:   1984,
									},
								},
							},
						},
					},
				},
			},
			fields: []attr.Interface{attr.String("Artist"), attr.Int("Year")},
			out:    []interface{}{"Artist One", nil},
		},
	}

	for ii, tt := range table {
		g := CommonGroupAttr(tt.fields, tt.in)
		got := make([]interface{}, len(tt.out))
		for i, f := range tt.fields {
			got[i] = g.Field(f.Name())
		}

		if !reflect.DeepEqual(got, tt.out) {
			t.Errorf("[%d] got %#v, expected %#v", ii, got, tt.out)
		}
	}
}