unity-lens-music-6.9.0+13.10.20131011/ 0000755 0000157 0000170 00000000000 12225714132 017272 5 ustar pbuser pbgroup 0000000 0000000 unity-lens-music-6.9.0+13.10.20131011/po/ 0000755 0000157 0000170 00000000000 12225714132 017710 5 ustar pbuser pbgroup 0000000 0000000 unity-lens-music-6.9.0+13.10.20131011/po/LINGUAS 0000644 0000157 0000170 00000000002 12225713654 020735 0 ustar pbuser pbgroup 0000000 0000000
unity-lens-music-6.9.0+13.10.20131011/po/POTFILES.skip 0000644 0000157 0000170 00000000267 12225713654 022042 0 ustar pbuser pbgroup 0000000 0000000 src/main.c
src/daemon.c
src/utils.c
src/simple-scope.c
src/banshee-scope.c
src/rhythmbox-scope.c
src/musicstore-scope.c
src/ubuntuone-webservices.c
tests/unit/ubuntuone-webservices.c
unity-lens-music-6.9.0+13.10.20131011/po/POTFILES.in 0000644 0000157 0000170 00000000413 12225713654 021473 0 ustar pbuser pbgroup 0000000 0000000 [encoding: UTF-8]
src/daemon.vala
src/main.vala
src/banshee-scope.vala
src/rhythmbox-scope.vala
src/simple-scope.vala
src/musicstore-scope.vala
[type: gettext/ini]banshee.scope.in.in
[type: gettext/ini]rhythmbox.scope.in.in
[type: gettext/ini]musicstore.scope.in.in
unity-lens-music-6.9.0+13.10.20131011/README 0000644 0000157 0000170 00000000000 12225713654 020150 0 ustar pbuser pbgroup 0000000 0000000 unity-lens-music-6.9.0+13.10.20131011/configure.ac 0000644 0000157 0000170 00000013012 12225713654 021565 0 ustar pbuser pbgroup 0000000 0000000 AC_INIT(unity-lens-music, 6.9.0, https://launchpad.net/unity-lens-music)
AC_COPYRIGHT([Copyright 2011-2012 Canonical])
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
#####################################################
# Silent build rules
#####################################################
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_PREREQ(2.59)
AC_CONFIG_HEADERS([config.h])
#####################################################
# Init the other things we depend on
#####################################################
AM_MAINTAINER_MODE
AM_PROG_VALAC([0.18.0])
AS_IF([test -z "$VALAC"], [AC_MSG_ERROR(["No valac compiler found."])])
AC_PROG_CC
AM_PROG_CC_C_O
AC_HEADER_STDC
LT_INIT
AC_CONFIG_MACRO_DIR([m4])
#############################################
# Gettext
#############################################
GETTEXT_PACKAGE="$PACKAGE"
AC_SUBST(GETTEXT_PACKAGE)
AC_SUBST([CONFIG_STATUS_DEPENDENCIES],['$(top_srcdir)/po/LINGUAS'])
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [gettext domain])
AM_GLIB_GNU_GETTEXT
# AM_GNOME_GETTEXT above substs $DATADIRNAME
# this is the directory where the *.{mo,gmo} files are installed
localedir='${prefix}/${DATADIRNAME}/locale'
AC_SUBST(localedir)
IT_PROG_INTLTOOL([0.40.0])
AC_DEFINE_UNQUOTED(LOCALE_DIR, "${PREFIX}/${DATADIRNAME}/locale",[Locale directory])
AC_DEFINE_UNQUOTED(DATADIR, "${PREFIX}/${DATADIRNAME}",[Data directory])
AC_DEFINE_UNQUOTED(PREFIXDIR, "${PREFIX}",[Prefix directory])
######################################################
# intltool rule for generating translated .lens file
######################################################
INTLTOOL_SCOPE_RULE='%.scope: %.scope.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
AC_SUBST(INTLTOOL_SCOPE_RULE)
###########################
# gcov coverage reporting
###########################
m4_include([m4/gcov.m4])
AC_TDD_GCOV
AM_CONDITIONAL([HAVE_GCOV], [test "x$ac_cv_check_gcov" = xyes])
AM_CONDITIONAL([HAVE_LCOV], [test "x$ac_cv_check_lcov" = xyes])
AM_CONDITIONAL([HAVE_GCOVR], [test "x$ac_cv_check_gcovr" = xyes])
AC_SUBST(COVERAGE_CFLAGS)
AC_SUBST(COVERAGE_LDFLAGS)
#####################################################
# Check for module and library dependancies
#####################################################
GLIB_REQUIRED=2.32
PKG_CHECK_MODULES(SCOPE_DAEMON,
glib-2.0 >= $GLIB_REQUIRED
gobject-2.0 >= $GLIB_REQUIRED
gio-2.0 >= $GLIB_REQUIRED
gio-unix-2.0 >= $GLIB_REQUIRED
dee-1.0 >= 1.2.5
sqlite3 >= 3.7.7
gee-1.0
json-glib-1.0
libnotify
libsoup-2.4
oauth
unity >= 7.1.0
unity-extras >= 7.0.0
tdb >= 1.2.6)
PKG_CHECK_MODULES(PREVIEW_PLAYER,
glib-2.0 >= $GLIB_REQUIRED
gobject-2.0 >= $GLIB_REQUIRED
gio-2.0 >= $GLIB_REQUIRED
gstreamer-1.0
gstreamer-pbutils-1.0
)
AC_SUBST(SCOPE_DAEMON_CFLAGS)
AC_SUBST(SCOPE_DAEMON_LIBS)
AC_SUBST(PREVIEW_PLAYER_CFLAGS)
AC_SUBST(PREVIEW_PLAYER_LIBS)
#####################################################
# local install for distcheck and stand-alone running
#####################################################
with_localinstall="no"
AC_ARG_ENABLE(localinstall,
AS_HELP_STRING([--enable-localinstall],
[Install all of the files locally instead of in system directories (for distcheck)]),
with_localinstall=$enableval,
with_localinstall=no)
AM_CONDITIONAL([HAVE_LOCALINSTALL], [test "x$with_localinstall" = "xyes"])
#####################################################
# Expand variables needed for config.vala
#####################################################
AS_AC_EXPAND(PREFIX, $prefix)
AC_SUBST(PREFIX)
AS_AC_EXPAND(DATADIR, $datarootdir)
AC_SUBST(DATADIR)
AS_AC_EXPAND(LIBEXECDIR, $libexecdir)
AC_SUBST(LIBEXECDIR)
#####################################################
# Look for dbus service dir
#####################################################
if test "x$with_localinstall" = "xyes"; then
DBUSSERVICEDIR="${datadir}/dbus-1/services/"
else
DBUSSERVICEDIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`
fi
AC_SUBST(DBUSSERVICEDIR)
#####################################################
# Look for correct Scopes dir
#####################################################
if test "x$with_localinstall" = "xyes"; then
SCOPESDIR="${datadir}/unity/scopes"
else
SCOPESDIR=`$PKG_CONFIG --variable=scopesdir unity`
fi
AC_SUBST(SCOPESDIR)
#####################################################
# Create the Makefiles
#####################################################
AC_CONFIG_FILES([
Makefile
banshee.scope.in
rhythmbox.scope.in
musicstore.scope.in
data/Makefile
src/Makefile
src/config.vala
po/Makefile.in
tests/Makefile
tests/unit/Makefile
])
AC_OUTPUT
#####################################################
# Output the results
#####################################################
AC_MSG_NOTICE([
Unity Music Lens Daemon $VERSION
-------------------------------
Prefix : ${prefix}
Local install : ${with_localinstall}
Extra CFlags : ${CPPFLAGS} $MAINTAINER_CFLAGS
Extra ValaFlags : ${CPPFLAGS} $MAINTAINER_VALAFLAGS
Scopes Directory: ${SCOPESDIR}
Testing
Coverage reporting : ${use_gcov}
])
unity-lens-music-6.9.0+13.10.20131011/rhythmbox.scope.in.in 0000644 0000157 0000170 00000001036 12225713654 023373 0 ustar pbuser pbgroup 0000000 0000000 [Scope]
DBusName=com.canonical.Unity.Scope.Music
DBusPath=/com/canonical/unity/scope/rhythmbox
Icon=@prefix@/share/unity/icons/lens-nav-music.svg
QueryBinary=rhythmbox
_Name=Rhythmbox
_Description=This is an Ubuntu search plugin that enables information from Rhythmbox to be searched and displayed in the Dash underneath the Music header. If you do not wish to search this content source, you can disable this search plugin.
_SearchHint=Search music collection
Shortcut=m
Type=music
[Desktop Entry]
X-Ubuntu-Gettext-Domain=unity-lens-music
unity-lens-music-6.9.0+13.10.20131011/tests/ 0000755 0000157 0000170 00000000000 12225714132 020434 5 ustar pbuser pbgroup 0000000 0000000 unity-lens-music-6.9.0+13.10.20131011/tests/unit/ 0000755 0000157 0000170 00000000000 12225714132 021413 5 ustar pbuser pbgroup 0000000 0000000 unity-lens-music-6.9.0+13.10.20131011/tests/unit/assertions.vapi 0000644 0000157 0000170 00000001334 12225713654 024477 0 ustar pbuser pbgroup 0000000 0000000 [CCode (cprefix = "G", lower_case_cprefix = "g_", cheader_filename = "glib.h")]
namespace Assertions {
public enum OperatorType {
[CCode (cname = "==")]
EQUAL,
[CCode (cname = "!=")]
NOT_EQUAL,
[CCode (cname = "<")]
LESS_THAN,
[CCode (cname = ">")]
GREATER_THAN,
[CCode (cname = "<=")]
LESS_OR_EQUAL,
[CCode (cname = ">=")]
GREATER_OR_EQUAL
}
public void assert_cmpstr (string? s1, OperatorType op, string? s2);
public void assert_cmpint (int n1, OperatorType op, int n2);
public void assert_cmpuint (uint n1, OperatorType op, uint n2);
public void assert_cmphex (uint n1, OperatorType op, uint n2);
public void assert_cmpfloat (float n1, OperatorType op, float n2);
}
unity-lens-music-6.9.0+13.10.20131011/tests/unit/test-ubuntuone-purchases.vala 0000644 0000157 0000170 00000054526 12225713654 027300 0 ustar pbuser pbgroup 0000000 0000000 /*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by Alejandro J. Cura
*
*/
using Assertions;
using Gee;
using GLib;
using Ubuntuone.Webservice;
const string FAKE_URL = "http://fake/url";
const string FAKE_PASSWORD = "PezEspada";
const string FAKE_SKU = "7digital:fake_album:id";
const string FAKE_TOKEN = "a fake token";
const string BROKEN_JSON = """
{
"a": "b",
$!@$# BROKEN!
""";
const string FAKE_JSON_ACCOUNT = """
{
"username": "mrbean",
"nickname": "Mr. Bean",
"email": "mr@be.an"
}
""";
const string FAKE_JSON_PAYMENT_METHOD = """
{
"open_url": "",
"user_email": "mr@be.an",
"selected_payment_method": "Visa 1234"
}
""";
const string FAKE_JSON_PAYMENT_METHOD_ERROR = """
{
"open_url": "http://somewhere/else",
"error_message": "No default payment method selected."
}
""";
const string FAKE_JSON_AUTHENTICATION = """
{
"consumer_secret": "fake_secret",
"token": "fake_token",
"consumer_key": "fake_consumer_key",
"name": "FAKE_TOKEN_NAME",
"token_secret": "fake_token_secret"
}
""";
const string FAKE_JSON_PURCHASE = """
{
"order_id": "1111",
"order_status": "OK"
}
""";
const string FAKE_JSON_PURCHASE_FAILURE = """
{
"order_id": "1111",
"order_status": "PAYMENT_FAILURE",
"order_detail": "TBD",
"open_url": "http://slashdot.org/"
}
""";
public class Main
{
public static int main (string[] args)
{
int result = run_tests (args);
// irl_test ();
return result;
}
static int run_tests (string[] args)
{
Test.init (ref args);
Test.add_data_func ("/Unit/PurchaseChecker/ParseAccount", test_parse_account);
Test.add_data_func ("/Unit/PurchaseChecker/ParseBrokenAccount", test_parse_broken_account);
Test.add_data_func ("/Unit/PurchaseChecker/ParsePaymentMethod", test_parse_payment_method);
Test.add_data_func ("/Unit/PurchaseChecker/ParsePaymentMethodError", test_parse_payment_method_error);
Test.add_data_func ("/Unit/PurchaseChecker/ParseAuthentication", test_parse_authentication);
Test.add_data_func ("/Unit/PurchaseChecker/ReadyToPurchase", test_ready_to_purchase);
Test.add_data_func ("/Unit/PurchaseChecker/FetchAccountInfo", test_fetch_account_info);
Test.add_data_func ("/Unit/PurchaseChecker/FetchPaymentInfo", test_fetch_payment_info);
Test.add_data_func ("/Unit/PurchaseChecker/FetchCredentials", test_fetch_credentials);
Test.add_data_func ("/Unit/PurchaseChecker/FetchCredentialsFails", test_fetch_credentials_fails);
Test.add_data_func ("/Unit/PurchaseChecker/FetchCredentialsFailsExtra", test_fetch_credentials_fails_extra);
Test.add_data_func ("/Unit/PurchaseChecker/FetchAccount", test_fetch_account);
Test.add_data_func ("/Unit/PurchaseChecker/FetchAccountFails", test_fetch_account_http_failure);
Test.add_data_func ("/Unit/PurchaseChecker/FetchAccountBrokenJson", test_fetch_account_wrong_json);
Test.add_data_func ("/Unit/PurchaseChecker/FetchPayment", test_fetch_payment);
Test.add_data_func ("/Unit/PurchaseChecker/FetchPaymentFails", test_fetch_payment_http_failure);
Test.add_data_func ("/Unit/PurchaseChecker/FetchPaymentBrokenJson", test_fetch_payment_wrong_json);
Test.add_data_func ("/Unit/PurchaseChecker/Purchase", test_purchase);
Test.add_data_func ("/Unit/PurchaseChecker/GetPurchaseToken", test_get_purchase_token);
Test.add_data_func ("/Unit/PurchaseChecker/GetPurchaseTokenBrokenJson", test_get_purchase_token_broken_json);
Test.add_data_func ("/Unit/PurchaseChecker/SsoWebcall", test_authenticated_sso_webcall);
Test.add_data_func ("/Unit/PurchaseChecker/SsoWebcallFails", test_authenticated_sso_webcall_fails);
Test.add_data_func ("/Unit/PurchaseChecker/SsoWebcallWrongPassword", test_authenticated_sso_webcall_wrong_password);
Test.add_data_func ("/Unit/PurchaseChecker/PurchaseDefaultPayment", test_purchase_with_default_payment);
Test.add_data_func ("/Unit/PurchaseChecker/PurchaseDefaultPaymentBroken", test_purchase_with_default_payment_broken_json);
Test.add_data_func ("/Unit/PurchaseChecker/PurchaseConnectionFails", test_purchase_with_default_payment_connection_fails);
Test.add_data_func ("/Unit/PurchaseChecker/PurchaseDefaultPaymentFails", test_purchase_with_default_payment_fails);
return Test.run ();
}
public static bool run_with_timeout (MainLoop ml, uint timeout_ms)
{
bool timeout_reached = false;
var t_id = Timeout.add (timeout_ms, () => {
timeout_reached = true;
debug ("Timeout reached");
ml.quit ();
return false;
});
ml.run ();
if (!timeout_reached) Source.remove (t_id);
return !timeout_reached;
}
async void irl_test_async ()
{
var purchase_service = new PurchaseService();
var purchase_sku = "7digital:album:1347423:WORLD";
try {
yield purchase_service.fetch_account_info ();
purchase_service.fetch_payment_info (purchase_sku);
debug ("data was available: %s %s %s", purchase_service.nickname, purchase_service.email, purchase_service.selected_payment_method);
var real_user_password = FAKE_PASSWORD;
purchase_service.purchase (purchase_sku, real_user_password);
debug ("purchase completed.");
} catch (PurchaseError e) {
debug ("got purchase error: %s", e.message);
}
}
static void irl_test ()
{
var loop = new GLib.MainLoop ();
var m = new Main();
Idle.add (() => {
m.irl_test_async.begin ((obj, res) => {
m.irl_test_async.end (res);
loop.quit ();
});
return false;
});
assert (run_with_timeout (loop, 60000));
}
class FakeCredentialsManagement : GLib.Object, CredentialsManagement
{
private HashTable fake_credentials;
construct
{
fake_credentials = new HashTable (str_hash, str_equal);
fake_credentials["token"] = "fake_token";
}
public void find_credentials () throws IOError
{
Idle.add (() => {
credentials_found (fake_credentials);
return false;
});
}
}
class FailingCredentialsManagement : GLib.Object, CredentialsManagement
{
private HashTable fake_error_info;
construct
{
fake_error_info = new HashTable (str_hash, str_equal);
fake_error_info["error"] = "fake_error";
}
public void find_credentials () throws IOError
{
Idle.add (() => {
credentials_error (fake_error_info);
return false;
});
}
}
class ExtraFailingCredentialsManagement : GLib.Object, CredentialsManagement
{
public void find_credentials () throws IOError
{
throw new IOError.INVALID_DATA ("Miscellanea Errora");
}
}
class BaseTestPurchaseService : PurchaseService
{
internal override CredentialsManagement build_credentials_management ()
{
return new FakeCredentialsManagement ();
}
}
class FailingCredentialsPurchaseService : PurchaseService
{
internal override CredentialsManagement build_credentials_management ()
{
return new FailingCredentialsManagement ();
}
}
class ExtraFailingCredentialsPurchaseService : PurchaseService
{
internal override CredentialsManagement build_credentials_management ()
{
return new ExtraFailingCredentialsManagement ();
}
}
private static void test_parse_account ()
{
var purchase_service = new BaseTestPurchaseService ();
try {
purchase_service.parse_account_json (FAKE_JSON_ACCOUNT);
} catch (GLib.Error e)
{
assert_not_reached ();
}
assert_cmpstr (purchase_service.nickname, OperatorType.EQUAL, "Mr. Bean");
assert_cmpstr (purchase_service.email, OperatorType.EQUAL, "mr@be.an");
}
private static void test_parse_broken_account ()
{
var purchase_service = new BaseTestPurchaseService ();
try
{
purchase_service.parse_account_json (BROKEN_JSON);
assert_not_reached ();
} catch (GLib.Error e)
{
// This is *just* the error we are expecting, so do nothing!
}
}
private static void test_parse_payment_method ()
{
var purchase_service = new BaseTestPurchaseService ();
try
{
purchase_service.parse_payment_method_json (FAKE_JSON_PAYMENT_METHOD);
} catch (GLib.Error e)
{
assert_not_reached ();
}
assert_cmpstr (purchase_service.selected_payment_method, OperatorType.EQUAL, "Visa 1234");
}
private static void test_parse_payment_method_error ()
{
var purchase_service = new BaseTestPurchaseService ();
try
{
purchase_service.parse_payment_method_json (FAKE_JSON_PAYMENT_METHOD_ERROR);
assert_not_reached ();
} catch (PurchaseError e)
{
assert_cmpstr (purchase_service.open_url, OperatorType.EQUAL, "http://somewhere/else");
}
}
private static void test_parse_authentication ()
{
var purchase_service = new BaseTestPurchaseService ();
try
{
purchase_service.parse_authentication_json (FAKE_JSON_AUTHENTICATION);
} catch (GLib.Error e)
{
assert_not_reached ();
}
assert_cmpstr (purchase_service.consumer_key, OperatorType.EQUAL, "fake_consumer_key");
assert_cmpstr (purchase_service.token, OperatorType.EQUAL, "fake_token");
}
private static void test_ready_to_purchase ()
{
var purchase_service = new BaseTestPurchaseService ();
assert (purchase_service.ready_to_purchase == false);
purchase_service.selected_payment_method = "visa 1234";
assert (purchase_service.ready_to_purchase == true);
}
class TestRefetchPurchaseService : BaseTestPurchaseService {
internal bool credentials_fetched = false;
internal bool account_fetched = false;
internal bool payment_method_fetched = false;
internal override async void fetch_credentials ()
{
Idle.add (() => {
credentials_fetched = true;
fetch_credentials.callback ();
return false;
});
yield;
}
internal override async void fetch_account ()
{
Idle.add (() => {
account_fetched = true;
fetch_account.callback ();
return false;
});
yield;
}
internal override void fetch_payment_method (string purchase_sku)
{
payment_method_fetched = true;
}
}
private static void test_fetch_account_info ()
{
var purchase_service = new TestRefetchPurchaseService ();
MainLoop mainloop = new MainLoop ();
purchase_service.fetch_account_info.begin((obj, res) => {
mainloop.quit ();
try {
purchase_service.fetch_account_info.end (res);
} catch (PurchaseError e) {
error ("Can't fetch payment info: %s", e.message);
}
});
assert (run_with_timeout (mainloop, 1000));
assert (purchase_service.credentials_fetched);
assert (purchase_service.account_fetched);
}
private static void test_fetch_payment_info ()
{
var purchase_service = new TestRefetchPurchaseService ();
try {
purchase_service.fetch_payment_info("fake_sku");
} catch (PurchaseError e) {
error ("Can't fetch payment info: %s", e.message);
}
assert (purchase_service.payment_method_fetched);
}
private static void test_fetch_credentials ()
{
var purchase_service = new BaseTestPurchaseService ();
MainLoop mainloop = new MainLoop ();
purchase_service.fetch_credentials.begin((obj, res) => {
mainloop.quit ();
try {
purchase_service.fetch_credentials.end (res);
} catch (PurchaseError e) {
error ("Can't fetch credentials: %s", e.message);
}
});
assert (run_with_timeout (mainloop, 1000));
assert (purchase_service._ubuntuone_credentials != null);
}
private static void test_fetch_credentials_fails ()
{
PurchaseError failure = null;
var purchase_service = new FailingCredentialsPurchaseService ();
MainLoop mainloop = new MainLoop ();
purchase_service.fetch_credentials.begin((obj, res) => {
mainloop.quit ();
try {
purchase_service.fetch_credentials.end (res);
} catch (PurchaseError e) {
failure = e;
}
});
assert (run_with_timeout (mainloop, 1000));
assert (failure is PurchaseError.MISSING_CREDENTIALS_ERROR);
}
private static void test_fetch_credentials_fails_extra ()
{
PurchaseError failure = null;
var purchase_service = new ExtraFailingCredentialsPurchaseService ();
MainLoop mainloop = new MainLoop ();
purchase_service.fetch_credentials.begin((obj, res) => {
mainloop.quit ();
try {
purchase_service.fetch_credentials.end (res);
} catch (PurchaseError e) {
failure = e;
}
});
assert (run_with_timeout (mainloop, 1000));
assert (failure is PurchaseError.MISSING_CREDENTIALS_ERROR);
}
class FakeWebcallPurchaseService : BaseTestPurchaseService
{
internal string used_uri = null;
internal int status_code;
internal string found_json;
internal FakeWebcallPurchaseService (int _status_code, string _found_json) {
status_code = _status_code;
found_json = _found_json;
}
internal override async PurchaseError call_api (string method, string uri, out string response)
{
PurchaseError error = null;
Idle.add (() => {
call_api.callback ();
return false;
});
yield;
response = found_json;
if (status_code != Soup.KnownStatusCode.OK) {
error = new PurchaseError.PURCHASE_ERROR ("fake error");
}
return error;
}
internal override void _do_sso_webcall (Soup.Message message, string password)
{
message.response_body.append (Soup.MemoryUse.STATIC, found_json.data);
message.status_code = status_code;
}
internal override Soup.Message send_signed_webservice_call (string method, string uri)
{
var message = new Soup.Message (method, uri);
message.response_body.append (Soup.MemoryUse.STATIC, found_json.data);
message.status_code = status_code;
return message;
}
}
private static FakeWebcallPurchaseService _test_fetch_account (int _status_code, string _found_json) throws PurchaseError
{
var purchase_service = new FakeWebcallPurchaseService (_status_code, _found_json);
purchase_service._ubuntuone_credentials = new HashTable (str_hash, str_equal);
PurchaseError error = null;
MainLoop mainloop = new MainLoop ();
purchase_service.fetch_account.begin((obj, res) => {
mainloop.quit ();
try {
purchase_service.fetch_account.end (res);
} catch (PurchaseError e) {
error = e;
}
});
assert (run_with_timeout (mainloop, 1000));
if (error != null) {
throw error;
}
return purchase_service;
}
private static void test_fetch_account ()
{
try {
var purchase_service = _test_fetch_account (Soup.KnownStatusCode.OK, FAKE_JSON_ACCOUNT);
assert_cmpstr (purchase_service.nickname, OperatorType.EQUAL, "Mr. Bean");
assert_cmpstr (purchase_service.email, OperatorType.EQUAL, "mr@be.an");
} catch (PurchaseError e) {
assert_not_reached ();
}
}
private static void test_fetch_account_http_failure ()
{
try {
_test_fetch_account (Soup.KnownStatusCode.INTERNAL_SERVER_ERROR, FAKE_JSON_ACCOUNT);
assert_not_reached ();
} catch (PurchaseError e) {
// Expected error
}
}
private static void test_fetch_account_wrong_json ()
{
try {
_test_fetch_account (Soup.KnownStatusCode.OK, BROKEN_JSON);
assert_not_reached ();
} catch (PurchaseError e) {
// Expected error
}
}
private static FakeWebcallPurchaseService _test_fetch_payment (int _status_code, string _found_json) throws PurchaseError
{
var purchase_service = new FakeWebcallPurchaseService (_status_code, _found_json);
purchase_service._ubuntuone_credentials = new HashTable (str_hash, str_equal);
purchase_service.fetch_payment_method("fake_sku");
return purchase_service;
}
private static void test_fetch_payment ()
{
try {
var purchase_service = _test_fetch_payment (Soup.KnownStatusCode.OK, FAKE_JSON_PAYMENT_METHOD);
assert_cmpstr (purchase_service.selected_payment_method, OperatorType.EQUAL, "Visa 1234");
} catch (PurchaseError e) {
assert_not_reached ();
}
}
private static void test_fetch_payment_http_failure ()
{
try {
_test_fetch_payment (Soup.KnownStatusCode.INTERNAL_SERVER_ERROR, FAKE_JSON_PAYMENT_METHOD);
assert_not_reached ();
} catch (PurchaseError e) {
// Expected error
}
}
private static void test_fetch_payment_wrong_json ()
{
try {
_test_fetch_payment (Soup.KnownStatusCode.OK, BROKEN_JSON);
assert_not_reached ();
} catch (PurchaseError e) {
// Expected error
}
}
class TestPurchaseService : BaseTestPurchaseService
{
internal string password;
internal string album_id;
internal string purchase_token;
internal override string get_purchase_token (string password)
{
this.password = password;
return FAKE_TOKEN;
}
internal override void purchase_with_default_payment (string album_id, string purchase_token)
{
this.album_id = album_id;
this.purchase_token = purchase_token;
}
}
private static void test_purchase ()
{
try {
var purchase_service = new TestPurchaseService ();
purchase_service.purchase (FAKE_SKU, FAKE_PASSWORD);
assert_cmpstr (purchase_service.password, OperatorType.EQUAL, FAKE_PASSWORD);
assert_cmpstr (purchase_service.album_id, OperatorType.EQUAL, FAKE_SKU);
assert_cmpstr (purchase_service.purchase_token, OperatorType.EQUAL, FAKE_TOKEN);
} catch (Error e) {
assert_not_reached ();
}
}
class FakePurchaseTokenService : BaseTestPurchaseService
{
string found_json;
internal FakePurchaseTokenService (string _found_json)
{
found_json = _found_json;
}
internal override string authenticated_sso_webcall (string method, string uri, string operation, string password)
throws PurchaseError
{
return found_json;
}
}
private static void test_get_purchase_token ()
{
var purchase_service = new FakePurchaseTokenService (FAKE_JSON_AUTHENTICATION);
var expected = "fake_consumer_key:fake_token";
try {
var result = purchase_service.get_purchase_token (FAKE_PASSWORD);
assert_cmpstr (expected, OperatorType.EQUAL, result);
} catch (PurchaseError e) {
assert_not_reached ();
}
}
private static void test_get_purchase_token_broken_json ()
{
var purchase_service = new FakePurchaseTokenService (BROKEN_JSON);
try {
purchase_service.get_purchase_token (FAKE_PASSWORD);
assert_not_reached ();
} catch (PurchaseError e) {
assert (e is PurchaseError.PURCHASE_ERROR);
}
}
private static void test_authenticated_sso_webcall ()
{
var purchase_service = new FakeWebcallPurchaseService (Soup.KnownStatusCode.OK, FAKE_JSON_AUTHENTICATION);
try {
var result = purchase_service.authenticated_sso_webcall ("FAKE", "http://some/where", "operation=wolf", FAKE_PASSWORD);
assert_cmpstr (FAKE_JSON_AUTHENTICATION, OperatorType.EQUAL, result);
} catch (PurchaseError e) {
assert_not_reached ();
}
}
private static void test_authenticated_sso_webcall_fails ()
{
var purchase_service = new FakeWebcallPurchaseService (Soup.KnownStatusCode.INTERNAL_SERVER_ERROR, FAKE_JSON_AUTHENTICATION);
try {
purchase_service.authenticated_sso_webcall ("FAKE", "http://some/where", "operation=wolf", FAKE_PASSWORD);
assert_not_reached ();
} catch (Error e) {
assert (e is PurchaseError.PURCHASE_ERROR);
}
}
private static void test_authenticated_sso_webcall_wrong_password ()
{
var purchase_service = new FakeWebcallPurchaseService (Soup.KnownStatusCode.UNAUTHORIZED, FAKE_JSON_AUTHENTICATION);
try {
purchase_service.authenticated_sso_webcall ("FAKE", "http://some/where", "operation=wolf", FAKE_PASSWORD);
assert_not_reached ();
} catch (Error e) {
assert (e is PurchaseError.WRONG_PASSWORD_ERROR);
}
}
private static void test_purchase_with_default_payment ()
{
var purchase_service = new FakeWebcallPurchaseService (Soup.KnownStatusCode.OK, FAKE_JSON_PURCHASE);
try {
purchase_service.purchase_with_default_payment (FAKE_SKU, FAKE_TOKEN);
} catch (PurchaseError e) {
warning (e.message);
assert_not_reached ();
}
}
private static void test_purchase_with_default_payment_broken_json ()
{
var purchase_service = new FakeWebcallPurchaseService (Soup.KnownStatusCode.OK, BROKEN_JSON);
try {
purchase_service.purchase_with_default_payment (FAKE_SKU, FAKE_TOKEN);
assert_not_reached ();
} catch (PurchaseError e) {
assert (e is PurchaseError.PURCHASE_ERROR);
}
}
private static void test_purchase_with_default_payment_fails ()
{
var purchase_service = new FakeWebcallPurchaseService (Soup.KnownStatusCode.OK, FAKE_JSON_PURCHASE_FAILURE);
try {
purchase_service.purchase_with_default_payment (FAKE_SKU, FAKE_TOKEN);
assert_not_reached ();
} catch (PurchaseError e) {
assert (e is PurchaseError.PURCHASE_ERROR);
}
}
private static void test_purchase_with_default_payment_connection_fails ()
{
var purchase_service = new FakeWebcallPurchaseService (Soup.KnownStatusCode.INTERNAL_SERVER_ERROR, FAKE_JSON_PURCHASE_FAILURE);
try {
purchase_service.purchase_with_default_payment (FAKE_SKU, FAKE_TOKEN);
assert_not_reached ();
} catch (PurchaseError e) {
assert (e is PurchaseError.PURCHASE_ERROR);
}
}
}
unity-lens-music-6.9.0+13.10.20131011/tests/unit/Makefile.am 0000644 0000157 0000170 00000004124 12225713654 023460 0 ustar pbuser pbgroup 0000000 0000000 check_PROGRAMS = test-rhythmbox-parser test-ubuntuone-purchases
TESTS = $(check_PROGRAMS)
AM_CPPFLAGS = \
-w \
$(SCOPE_DAEMON_CFLAGS) \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
-I$(top_srcdir)/src \
$(COVERAGE_CFLAGS) \
$(NULL)
AM_LDFLAGS = $(COVERAGE_LDFLAGS)
AM_VALAFLAGS = \
-C \
--pkg dee-1.0 \
--pkg gee-1.0 \
--pkg gio-2.0 \
--pkg gio-unix-2.0 \
--pkg glib-2.0 \
--pkg json-glib-1.0 \
--pkg oauth \
--pkg libsoup-2.4 \
--vapidir $(top_srcdir)/src \
--pkg tdb \
--pkg unity \
$(srcdir)/assertions.vapi \
$(MAINTAINER_VALAFLAGS)
$(NULL)
test_libs = \
$(SCOPE_DAEMON_LIBS) \
$(NULL)
test_rhythmbox_parser_LDADD = $(test_libs)
# Files starting from track.vala are not used in this test,
# but they are listed here so they show up in coverage
# measurements. When new tests are written for these features,
# move these files to them.
#
# All main scope vala files are missing because they would
# not compile and really need their own test binaries.
test_rhythmbox_parser_SOURCES = \
test-rhythmbox-parser.vala \
$(top_srcdir)/src/album.vala \
$(top_srcdir)/src/categories.vala \
$(top_srcdir)/src/config.vala \
$(top_srcdir)/src/filter-parser.vala \
$(top_srcdir)/src/filter-parser-decade.vala \
$(top_srcdir)/src/filter-parser-genre.vala \
$(top_srcdir)/src/genre.vala \
$(top_srcdir)/src/rhythmbox-collection.vala \
$(top_srcdir)/src/track.vala \
$(top_srcdir)/src/banshee-filter-parser-decade.vala \
$(top_srcdir)/src/banshee-filter-parser-genre.vala \
$(top_srcdir)/src/banshee-filter-parser.vala \
$(top_srcdir)/src/dash-proxy.vala \
$(top_srcdir)/src/musicstore-collection.vala \
$(top_srcdir)/src/musicstore-filter-parser-decade.vala \
$(top_srcdir)/src/musicstore-filter-parser-genre.vala \
$(top_srcdir)/src/musicstore-filter-parser.vala \
$(NULL)
test_ubuntuone_purchases_LDADD = $(test_libs)
test_ubuntuone_purchases_SOURCES = \
test-ubuntuone-purchases.vala \
$(top_srcdir)/src/ubuntuone-constants.vala \
$(top_srcdir)/src/ubuntuone-webservices.vala \
$(NULL)
EXTRA_DIST = assertions.vapi
CLEANFILES = *.stamp
unity-lens-music-6.9.0+13.10.20131011/tests/unit/test-rhythmbox-parser.vala 0000644 0000157 0000170 00000013404 12225713654 026565 0 ustar pbuser pbgroup 0000000 0000000 /*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by Didier Roche
*
*/
using Unity.MusicLens;
using Assertions;
public class Main
{
public static int main (string[] args)
{
Test.init (ref args);
Test.add_data_func ("/Unit/ParserChecker/Radios", test_radios);
Test.add_data_func ("/Unit/ParserChecker/Songs", test_songs);
Test.add_data_func ("/Unit/ParserChecker/LazyLoad", test_lazy_load);
Test.add_data_func ("/Unit/ParserChecker/InvalidTag", test_invalid_tag);
Test.run ();
return 0;
}
/* FIXME: this test is broken - it passes if iradio tag is not parsed
* because all checks are done in a callback that's never called in such case.
*/
private static void test_radios ()
{
var parser = new RhythmboxCollection.XmlParser ();
string collection_to_parse = """
Absolute Radio 80s (Modem)
80's
http://network.absoluteradio.co.uk/core/audio/ogg/live.pls?service=a8
6
1339693331
32
0
application/octet-stream
""";
parser.track_info_ready.connect ((track) =>
{
assert_cmpstr (track.title, OperatorType.EQUAL, "Absolute Radio 80s (Modem)");
assert_cmpstr (track.genre, OperatorType.EQUAL, "other");
assert_cmpstr (track.artist, OperatorType.EQUAL, "");
assert_cmpstr (track.album, OperatorType.EQUAL, "");
assert_cmpstr (track.uri, OperatorType.EQUAL, "http://network.absoluteradio.co.uk/core/audio/ogg/live.pls?service=a8");
assert_cmpint (track.year, OperatorType.EQUAL, 0);
assert (track.type_track == TrackType.RADIO);
});
parser.parse(collection_to_parse, collection_to_parse.length);
}
private static void test_songs ()
{
var parser = new RhythmboxCollection.XmlParser ();
string collection_to_parse = """
LA PASSION
Dance
GIGI D'AGOSTINO
Loulou 007
228
3661842
file:///home/moi/Gigi%20d'agostino%20Passion.mp3
1338273042
1338536342
1340378542
128
730142
audio/mpeg
http://www.danceparadise.ca.tc
""";
parser.track_info_ready.connect ((track) =>
{
assert_cmpstr (track.title, OperatorType.EQUAL, "LA PASSION");
assert_cmpstr (track.genre, OperatorType.EQUAL, "techno");
assert_cmpstr (track.artist, OperatorType.EQUAL, "GIGI D'AGOSTINO");
assert_cmpstr (track.album, OperatorType.EQUAL, "Loulou 007");
assert_cmpstr (track.uri, OperatorType.EQUAL, "file:///home/moi/Gigi%20d'agostino%20Passion.mp3");
assert_cmpint (track.year, OperatorType.EQUAL, 2000);
assert_cmpstr (track.mime_type, OperatorType.EQUAL, "audio/mpeg");
assert (track.type_track == TrackType.SONG);
});
parser.parse(collection_to_parse, collection_to_parse.length);
}
private static void test_lazy_load ()
{
var parser = new RhythmboxCollection.XmlParser ();
string collection_to_parse_chunk = """
LA PASSION
Dance
GIGI D'AGOSTINO
""";
parser.parse(collection_to_parse_chunk, collection_to_parse_chunk.length);
collection_to_parse_chunk = """
Loulou 007
228
3661842
file:///home/moi/Gigi%20d'agostino%20Passion.mp3
1338273042
1338536342
1340378542
128
730142
audio/mpeg
http://www.danceparadise.ca.tc
""";
parser.track_info_ready.connect ((track) =>
{
assert_cmpstr (track.title, OperatorType.EQUAL, "LA PASSION");
assert_cmpstr (track.album, OperatorType.EQUAL, "Loulou 007");
assert (track.type_track == TrackType.SONG);
});
parser.parse(collection_to_parse_chunk, collection_to_parse_chunk.length);
}
private static void test_invalid_tag ()
{
var parser = new RhythmboxCollection.XmlParser ();
string collection_to_parse_chunk = """
LA PASSION
Dance
le poisson
Dance
""";
parser.track_info_ready.connect ((track) =>
{
assert_cmpstr (track.title, OperatorType.EQUAL, "le poisson");
assert (track.type_track == TrackType.SONG);
});
parser.parse(collection_to_parse_chunk, collection_to_parse_chunk.length);
}
}
unity-lens-music-6.9.0+13.10.20131011/tests/Makefile.am 0000644 0000157 0000170 00000000017 12225713654 022476 0 ustar pbuser pbgroup 0000000 0000000 SUBDIRS = unit
unity-lens-music-6.9.0+13.10.20131011/tests/test-no-results.sh 0000755 0000157 0000170 00000000344 12225713654 024074 0 ustar pbuser pbgroup 0000000 0000000 #!/bin/sh
# Check that a non-sensical search string returns reply with "no-results-hint"
# set.
unity-tool -n com.canonical.Unity.Lens.Music -p /com/canonical/unity/lens/music -s asdfqwer | grep -q "no-results-hint" || exit 1
unity-lens-music-6.9.0+13.10.20131011/tests/test-common.sh 0000755 0000157 0000170 00000000213 12225713654 023244 0 ustar pbuser pbgroup 0000000 0000000 #!/bin/sh
# Common tests for emitting finished signal
unity-tool -n com.canonical.Unity.Lens.Music -p /com/canonical/unity/lens/music -c
unity-lens-music-6.9.0+13.10.20131011/tests/manual/ 0000755 0000157 0000170 00000000000 12225714132 021711 5 ustar pbuser pbgroup 0000000 0000000 unity-lens-music-6.9.0+13.10.20131011/tests/manual/categorization.txt 0000644 0000157 0000170 00000000432 12225713654 025503 0 ustar pbuser pbgroup 0000000 0000000 Categorization
==============
Tests that the categorization of results is correct.
#. Open the Dash and switch to the music lens.
#. Make sure that the search string is empty.
Outcome
The "Albums" category should list only album titles, if you see a song title the test failed.
unity-lens-music-6.9.0+13.10.20131011/tests/manual/previews-rhythmbox.txt 0000644 0000157 0000170 00000017114 12225713654 026354 0 ustar pbuser pbgroup 0000000 0000000 Preview of local album
----------------------------------------------------
Test that the local album preview are displayed correctly in the Dash.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open the Dash and switch to the music lens.
2. Make sure some local albums are displayed.
3. Right-click an album.
Expected Result:
Album preview should be displayed. It should display album cover, album title, album artist and year (as subtitle)
a list of tracks and 'Show in Folder' and 'Play' buttons.
Album preview - 'Show in Folder' action.
----------------------------------------------------
Test 'Show in Folder' action opens proper folder.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local album.
2. Click 'Show in Folder' button.
Expected Result:
Nautilus is launched, showing the parent folder of selected album.
Album preview - 'Play' action.
---------------------------------------------------
Test that 'Play' action enqueues album in Rhythmbox.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local album.
2. Click 'Play' button.
Expected Result:
The album is enqueued in Rhythmbox and playback starts.
Preview - codec installation
----------------------------------------------------
Test that missing mp3 codec is installed when required by preview.
Setup:
Rhythmbox installed and rhythmbox database exists, some mp3 files are available in ~/Music and are indexed by Rhythmbox. MP3 codec
(such as fluendo or gstreamer-bad/ugly package) is not installed.
Actions:
1. Open the Dash and switch to the music lens.
2. Make sure some local albums are displayed.
3. Right-click an album that contains mp3s.
4. Hover mouse over track number to reveal play button, click it.
Expected Result:
Album preview should be displayed. A standard GNOME popup box is displayed prompting the user for
codec installation and dash gets closed. After providing a password the codec gets installed (verify with 'dpkg -l|grep fluendo') and user is no longer
prompted for it when previewing mp3s.
Album preview - built-in playback for album tracks
----------------------------------------------------
Test that built-in playback via music-preview-player supports play/pause and resume.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local album.
2. Click small play button next to a track.
3. As the track is played, hit pause / play a few times.
Expected Result:
Selected track is played by music-preview-player. Playback progress is reported in the Dash. Playback is paused/resumed
when hitting pause/play button.
Album preview - end of playback with build-in playback
----------------------------------------------------
Test progress and playback state are reported correctly on end-of-playback when built-in playback is used.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local album.
2. Click small play button next to a track.
3. Wait for the playback to finish.
Expected Result:
Selected track is played by music-preview-player. Playback progress is reported in the Dash. When playback finishes,
the progress is reset.
Album preview - song change with built-in playback
----------------------------------------------------
Test that song can be changed with built-in playback functionality and progress/state are reported accordingly.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local album.
2. Click small play button next to a track.
3. As the track is played, click small play button for another track.
Expected Result:
Selected track is played by music-preview-player. When another track is activated for playback then playback progress
is updated accrodingly to show play state and progress for only one track.
Album preview - closing the preview during playback
----------------------------------------------------
Test that built-in playback stops when preview is closed.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local album.
2. Click small play button next to a track.
3. As the track is played, close the preview.
Expected Result:
Selected track is played by music-preview-player. Playback stops when the preview is closed. Preview player process
quits (verify with 'ps uax|grep music-preview-player').
Album preview - switching to a different preview during playback
----------------------------------------------------
Test that built-in playback stops when switching to a different preview.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local album.
2. Click small play button next to a track.
3. As the track is played, switch to a different preview by clicking left/right arrows.
Expected Result:
Selected track is played by music-preview-player. Playback stops when preview of different album is displayed.
Single track preview display in the dash.
----------------------------------------------------
Test that the single track preview for local album is displayed correctly in the Dash.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open the Dash and switch to the music lens.
2. Make sure some local songs are displayed.
3. Right-click a song.
Expected Result:
Song preview should be displayed. It should display album cover, song title, album artist and year (as subtitle).
Only a single track should be displayed in the player area. Two buttons should be present: 'Show in Folder' and 'Play'.
Single track preview - 'Show in Folder' action.
----------------------------------------------------
Test 'Show in Folder' action opens proper folder.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local song.
2. Click 'Show in Folder' button.
Expected Result:
Nautilus is launched, showing the parent folder of selected song (i.e. its album folder).
Single track preview - 'Play' action.
----------------------------------------------------
Test that 'Play' action enqueues song in Rhythmbox.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local song.
2. Click 'Play' button.
Expected Result:
The song is enqueued in Rhythmbox and playback starts.
Test built-in playback for single track.
----------------------------------------------------
Test that built-in playback via music-preview-player supports play/pause and resume.
Setup:
Rhythmbox installed and rhythmbox database exists, some music files are available in ~/Music and are indexed by Rhythmbox.
Actions:
1. Open a preview of local song.
2. Click small play button next to a track.
3. As the track is played, hit pause / play a few times.
Expected Result:
The track is played by music-preview-player. Playback progress is reported in the Dash. Playback is paused/resumed
when hitting pause/play button.
unity-lens-music-6.9.0+13.10.20131011/tests/manual/activation-remote-scope.txt 0000644 0000157 0000170 00000000702 12225713654 027222 0 ustar pbuser pbgroup 0000000 0000000 'Disable' Music store Search
----------------------------------------------------
Disabling the music store scope should not show any remote fetched result.
Setup:
Internet connectivity.
Actions:
1. Disable the online/commercial search in gnome-control-center or directly in gsettings
(com.canonical.Unity.Lenses "remote-content-search" to none)
2 Perfom a search in the music lens
Expected Results:
No "More suggestions" category should appear.
unity-lens-music-6.9.0+13.10.20131011/tests/manual/previews-musicstore.txt 0000644 0000157 0000170 00000012043 12225713654 026521 0 ustar pbuser pbgroup 0000000 0000000 Preview of U1 musicstore album
----------------------------------------------------
Test that the u1ms album preview is displayed correctly in the Dash.
Setup:
Network connectivity.
Actions:
1. Open the Dash and switch to the music lens.
2. Make sure some albums for purchase are displayed.
3. Right-click an album.
4. Repeat 1-2, but use Left-click in (3).
Expected Result:
Album preview should be displayed. It should display album cover, album title, album artist and year (as subtitle)
a list of tracks and 'Download' button. 'Download' button should display price and currency.
Preview of U1ms album - 'Download' action.
----------------------------------------------------
Test that 'Download' actions brings U1 music store.
Setup:
Network connectivity.
Actions:
1. Open a preview of u1ms album.
2. Click 'Download' button.
Expected Result:
U1 music store website is opened, with selected album displayed.
U1ms album preview - built-in playback
----------------------------------------------------
Test that built-in playback via music-preview-player supports play/pause and resume for u1ms album tracks.
Setup:
Network connectivity.
Actions:
1. Open a preview of u1ms album.
2. Click small play button next to a track.
3. As the track is played, hit pause / play a few times.
Expected Result:
Selected track is played by music-preview-player. Playback progress is reported in the Dash. Playback is paused/resumed
when hitting pause/play button.
U1ms album preview - end of playback with built-in playback
----------------------------------------------------
Test progress and playback state are reported correctly on end-of-playback when built-in playback is used.
Setup:
Network connectivity.
Actions:
1. Open a preview of u1ms album.
2. Click small play button next to a track.
3. Wait for the playback to finish.
Expected Result:
Selected track is played by music-preview-player. Playback progress is reported in the Dash. When playback finishes,
the progress is reset.
U1ms album preview - song change with built-in playback
----------------------------------------------------
Test that song can be changed with built-in playback functionality and progress/state are reported accordingly.
Actions:
1. Open a preview of u1ms album.
2. Click small play button next to a track.
3. As the track is played, click small play button for another track.
Expected Result:
Selected track is played by music-preview-player. When another track is activated for playback then playback progress
is updated accrodingly to show play state and progress for only one track.
U1ms album preview - closing the preview during playback
----------------------------------------------------
Test that built-in playback stops when preview is closed.
Setup:
Network connectivity.
Actions:
1. Open a preview of u1ms album.
2. Click small play button next to a track.
3. As the track is played, close the preview.
Expected Result:
Selected track is played by music-preview-player. Playback stops when the preview is closed.
Preview player process quits (verify with 'ps uax|grep music-preview-player').
U1ms album preview - switching to a different preview during playback
----------------------------------------------------
Test that built-in playback stops when switching to a different preview.
Setup:
Network connectivity.
Actions:
1. Open a preview of u1ms album.
2. Click small play button next to a track.
3. As the track is played, switch to a different preview by clicking left/right arrows.
Expected Result:
Selected track is played by music-preview-player. Playback stops when preview of different album is displayed.
U1ms single track preview
----------------------------------------------------
Test that single track preview for u1ms track is displayed correctly in the Dash.
Setup:
Network connectivity.
1. Open the Dash and switch to the music lens.
2. Make sure some u1ms songs are displayed.
3. Right-click a song.
Expected Result:
Song preview should be displayed. It should display album cover, song title, album artist and year (as subtitle).
Only a single track should be displayed in the player area. 'Download' button should be displayed.
U1ms single track preview - 'Download' action
----------------------------------------------------
Test that 'Download' action for single track preview brings U1 music store.
Setup:
Network connectivity.
Actions:
1. Open a preview of u1ms song.
2. Click 'Download' button.
Expected Result:
U1 music store website is opened, with selected song displayed.
U1ms album preview - playback stops on network error
----------------------------------------------------
Test playback state is set back to stop when network is not available.
Setup:
Network connectivity.
Actions:
1. Open a preview of u1ms album.
2. Login via ssh or switch to a VT and block outgoing network traffic, e.g.
`sudo iptables -A OUTPUT -p tcp --dport 80 -j DROP`.
3. Click small play button next to a track.
Expected Result:
Music doesn't play; the small play button next to a track indicates playing state.
After approximately 10 seconds the state is reset back to the default (not playing).
unity-lens-music-6.9.0+13.10.20131011/src/ 0000755 0000157 0000170 00000000000 12225714132 020061 5 ustar pbuser pbgroup 0000000 0000000 unity-lens-music-6.9.0+13.10.20131011/src/banshee-collection.vala 0000644 0000157 0000170 00000031505 12225713654 024500 0 ustar pbuser pbgroup 0000000 0000000 /*
* Copyright (C) 2011 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Authored by Alex Launi
*
*/
using Gee;
using GLib;
using Sqlite;
namespace Unity.MusicLens {
public errordomain DatabaseError {
FAILED_TO_OPEN
}
/**
* Abstracts talking to the banshee collection database
*/
public class BansheeCollection : Object
{
private const int MAX_RESULTS = 100;
private Database db;
public BansheeCollection () throws DatabaseError
{
int rc = Database.open ("%s/banshee-1/banshee.db".printf (Environment.get_user_config_dir ()), out db);
if (rc != Sqlite.OK) {
printerr ("failed to open db, %d, %s\n", rc, db.errmsg ());
throw new DatabaseError.FAILED_TO_OPEN ("Failed to open banshee database");
}
}
/**
* Performs a search on the banshee db
*/
public void search (DeprecatedScopeSearch search,
SearchType search_type,
GLib.List? filters = null,
int max_results = -1,
int category_override = -1)
{
const int TRACK_TITLE = 0;
const int TRACK_URI = 1;
const int TRACK_MIMETYPE = 2;
const int ALBUM_TITLE = 3;
const int ALBUM_ARTWORKID = 4;
const int ARTIST_NAME = 5;
int rc = 0;
Statement stmt;
var results_model = search.results_model;
var helper_model = results_model;
var empty_asv = new Variant.array (VariantType.VARDICT.element (), {});
if (category_override >= 0)
{
helper_model = new Dee.SequenceModel ();
helper_model.set_schema_full (results_model.get_schema ());
}
// use a tree set to ensure we don't duplicate albums
TreeSet albums = new TreeSet ();
string filters_sql = build_sql_from_filters (filters);
// BUILD SQL STATEMENT
string sql = """SELECT CoreTracks.Title, CoreTracks.Uri, CoreTracks.MimeType, CoreAlbums.Title, CoreAlbums.ArtworkID, CoreArtists.Name FROM CoreTracks
CROSS JOIN CoreArtists, CoreAlbums
WHERE CoreArtists.ArtistID = CoreTracks.ArtistID
AND CoreAlbums.AlbumID = CoreTracks.AlbumID
AND CoreTracks.PrimarySourceID = 1
AND ((CoreArtists.NameLowered LIKE '%%%s%%' ESCAPE '\'
AND CoreArtists.NameLowered IS NOT NULL)
OR (CoreAlbums.TitleLowered LIKE '%%%s%%' ESCAPE '\'
AND CoreAlbums.TitleLowered IS NOT NULL)
OR (CoreTracks.TitleLowered LIKE '%%%s%%' ESCAPE '\'
AND CoreTracks.TitleLowered IS NOT NULL)
)
%s
ORDER BY CoreTracks.Score DESC
LIMIT 0, %d;""".printf (search.search_string,
search.search_string,
search.search_string,
filters_sql,
max_results == -1 ? MAX_RESULTS : max_results);
rc = execute_sql (sql, out stmt);
if (stmt == null)
return;
do {
rc = stmt.step ();
switch (rc) {
case Sqlite.DONE:
break;
case Sqlite.ROW:
string artwork_path = get_album_artwork_path (stmt.column_text (ALBUM_ARTWORKID));
if (artwork_path == null || artwork_path == "" || !FileUtils.test(artwork_path, FileTest.EXISTS))
artwork_path = ALBUM_MISSING_ICON_PATH;
Track track = new Track ();
track.title = stmt.column_text (TRACK_TITLE);
track.artist = stmt.column_text (ARTIST_NAME);
track.uri = stmt.column_text (TRACK_URI);
track.mime_type = stmt.column_text (TRACK_MIMETYPE);
track.artwork_path = artwork_path;
Album album = new Album ();
album.title = stmt.column_text (ALBUM_TITLE);
album.artist = stmt.column_text (ARTIST_NAME);
album.uri = "album://%s/%s".printf (album.artist, album.title);
album.artwork_path = artwork_path;
uint category_id = Category.SONGS;
if (category_override >= 0)
category_id = category_override;
helper_model.append (track.uri, artwork_path, category_id,
Unity.ResultType.PERSONAL,
track.mime_type, track.title, track.artist,
track.uri, empty_asv);
if (albums.add (album.artist + album.title)) {
StringBuilder uri_list_builder = new StringBuilder ();
foreach (string uri in get_track_uris (album)) {
uri_list_builder.append ("'");
uri_list_builder.append (uri);
uri_list_builder.append ("' ");
}
category_id = Category.ALBUMS;
if (category_override >= 0)
category_id = category_override;
results_model.append (album.uri, album.artwork_path, category_id,
Unity.ResultType.PERSONAL,
"audio/mp3", album.title, album.artist,
uri_list_builder.str, empty_asv);
}
break;
default:
break;
}
} while (rc == Sqlite.ROW);
if (helper_model == results_model) return;
// we need to do this because the dash doesn't care about position
// of a newly added row in the model - it just appends it
var iter = helper_model.get_first_iter ();
var last = helper_model.get_last_iter ();
while (iter != last)
{
var row = helper_model.get_row (iter);
results_model.append_row (row);
iter = helper_model.next (iter);
}
}
/**
* Computes path for album artwork.
*/
private string get_album_artwork_path (string artwork_id)
{
string album_art_dir = "%s/media-art/".printf (Environment.get_user_cache_dir ());
string artwork_path = "%s/%s.jpg".printf (album_art_dir, artwork_id);
return artwork_path;
}
/**
* Creates Track object out of single row of Statement result data.
*/
private Track get_track (Statement stmt)
{
const int TRACK_URI = 0;
const int TRACK_TITLE = 1;
const int ARTIST_NAME = 2;
const int ALBUM_TITLE = 3;
const int ALBUM_ARTWORKID = 4;
const int TRACK_MIMETYPE = 5;
const int TRACK_GENRE = 6;
const int TRACK_NUMBER = 7;
const int TRACK_YEAR = 8;
const int TRACK_PLAYCOUNT = 9;
const int TRACK_DURATION = 10;
Track track = new Track();
track.uri = stmt.column_text (TRACK_URI);
track.title = stmt.column_text (TRACK_TITLE);
track.artist = stmt.column_text (ARTIST_NAME);
track.album = stmt.column_text (ALBUM_TITLE);
track.artwork_path = get_album_artwork_path (stmt.column_text (ALBUM_ARTWORKID));
track.mime_type = stmt.column_text (TRACK_MIMETYPE);
track.genre = stmt.column_text (TRACK_GENRE);
track.track_number = stmt.column_int (TRACK_NUMBER);
track.year = stmt.column_int (TRACK_YEAR);
track.play_count = stmt.column_int (TRACK_PLAYCOUNT);
track.duration = stmt.column_int (TRACK_DURATION);
return track;
}
/**
* Returns single track.
*/
public Track? get_album_track (string uri)
{
string sql = "SELECT
CoreTracks.Uri,
CoreTracks.Title,
CoreArtists.Name,
CoreAlbums.Title,
CoreAlbums.ArtworkID,
CoreTracks.MimeType,
CoreTracks.Genre,
CoreTracks.TrackNumber,
CoreTracks.Year,
CoreTracks.PlayCount,
CoreTracks.Duration
FROM CoreTracks
CROSS JOIN CoreAlbums, CoreArtists
WHERE CoreTracks.URI IS ?
AND CoreArtists.ArtistID = CoreTracks.ArtistID
AND CoreAlbums.AlbumID = CoreTracks.AlbumID";
Statement stmt;
int rc = execute_sql (sql, out stmt);
stmt.bind_text (1, uri);
rc = stmt.step ();
if (rc == Sqlite.ROW)
{
return get_track (stmt);
}
return null;
}
/**
* Returns all tracks of an album.
*/
public SList