From 24513a60a41e0bf7dbb0751f2176895acfd0121d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= <hugo@beauzee.fr>
Date: Mon, 11 Jul 2022 16:41:41 +0200
Subject: [PATCH] tests: Add a subscription importer tool

---
 test/meson.build                        |   1 +
 test/subscriptions_importer/main.cpp    | 168 ++++++++++++++++++++++++
 test/subscriptions_importer/meson.build |   6 +
 3 files changed, 175 insertions(+)
 create mode 100644 test/subscriptions_importer/main.cpp
 create mode 100644 test/subscriptions_importer/meson.build

diff --git a/test/meson.build b/test/meson.build
index 7264f5613..185002854 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -10,4 +10,5 @@ else
   subdir('sqlite_load')
   subdir('fast_teardown')
   subdir('fast_discover_cancel')
+  subdir('subscriptions_importer')
 endif
diff --git a/test/subscriptions_importer/main.cpp b/test/subscriptions_importer/main.cpp
new file mode 100644
index 000000000..78802bb87
--- /dev/null
+++ b/test/subscriptions_importer/main.cpp
@@ -0,0 +1,168 @@
+/*****************************************************************************
+ * Media Library
+ *****************************************************************************
+ * Copyright (C) 2022 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
+ *
+ * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "medialibrary/IMediaLibrary.h"
+#include "test/common/NoopCallback.h"
+#include "test/common/util.h"
+
+#include "compat/ConditionVariable.h"
+#include "compat/Mutex.h"
+
+#include <iostream>
+#include <unistd.h>
+#include <cassert>
+
+class TestCb : public mock::NoopCallback
+{
+public:
+    TestCb()
+        : m_isParsingCompleted( false )
+    {
+    }
+
+    bool waitForCompletion()
+    {
+        std::unique_lock<compat::Mutex> lock( m_mutex );
+        m_cond.wait( lock, [this](){
+            return m_isParsingCompleted == true;
+        });
+        return true;
+    }
+
+    void prepareWaitForCache()
+    {
+        std::lock_guard<compat::Mutex> lock{ m_mutex };
+        m_cacheUpdated = false;
+        m_cacheWorkerIdle = false;
+    }
+
+    void waitForCacheUpdated()
+    {
+        std::unique_lock<compat::Mutex> lock{ m_mutex };
+        m_cond.wait( lock, [this]() {
+            return m_cacheWorkerIdle == true && m_cacheUpdated == true;
+        });
+    }
+
+private:
+    virtual void onParsingStatsUpdated( uint32_t done, uint32_t scheduled ) override
+    {
+        {
+            std::lock_guard<compat::Mutex> lock( m_mutex );
+            m_isParsingCompleted = (done == scheduled);
+        }
+        m_cond.notify_all();
+    }
+
+    virtual void onCacheIdleChanged( bool idle ) override
+    {
+        std::lock_guard<compat::Mutex> lock( m_mutex );
+        m_cacheWorkerIdle = idle;
+        m_cond.notify_all();
+    }
+
+    virtual void onSubscriptionCacheUpdated( int64_t ) override
+    {
+        std::lock_guard<compat::Mutex> lock( m_mutex );
+        assert( m_cacheWorkerIdle == false );
+        m_cacheUpdated = true;
+    }
+
+private:
+    compat::ConditionVariable m_cond;
+    compat::Mutex m_mutex;
+    bool m_isParsingCompleted;
+    bool m_cacheUpdated;
+    bool m_cacheWorkerIdle;
+};
+
+static void usage( const char* const* argv )
+{
+    std::cerr << "usage: " << argv[0] << "[-q] [-c] <RSS_MRL>\n"
+                 "-q: Use Error log level. Default is Debug\n"
+                 "-c: Automatically cache this subscription\n"
+              << std::endl;
+}
+
+int main( int argc, char** argv )
+{
+    if ( argc < 2 )
+    {
+        usage(argv);
+        exit(1);
+    }
+
+    auto quiet = false;
+    auto cache = false;
+    int opt;
+    while ( ( opt = getopt( argc, argv, "qc" ) ) != -1 )
+    {
+        switch ( opt )
+        {
+        case 'q':
+            quiet = true;
+            break;
+        case 'c':
+            cache = true;
+            break;
+        default:
+            usage( argv );
+            exit( 1 );
+        }
+    }
+    if ( optind >= argc )
+    {
+        std::cerr << "Missing subscription RSS MRL" << std::endl;
+        usage(argv);
+        exit(2);
+    }
+    auto subMrl = argv[optind];
+
+    auto mlDir = getTempPath( "subscriptions_importer" );
+    auto dbPath = mlDir + "/test.db";
+    unlink( dbPath.c_str() );
+
+    auto testCb = std::make_unique<TestCb>();
+    std::unique_ptr<medialibrary::IMediaLibrary> ml{
+        NewMediaLibrary( dbPath.c_str(), mlDir.c_str(), false, nullptr )
+    };
+
+    ml->setVerbosity( quiet == true ? medialibrary::LogLevel::Error :
+                                      medialibrary::LogLevel::Debug );
+    auto initRes = ml->initialize( testCb.get() );
+    assert( initRes == InitializeResult::Success );
+    ml->setDiscoverNetworkEnabled( true );
+
+    ml->addSubscription( Service::Podcast, subMrl );
+
+    testCb->waitForCompletion();
+    if ( cache == true )
+    {
+        testCb->prepareWaitForCache();
+        ml->cacheNewSubscriptionMedia();
+        testCb->waitForCacheUpdated();
+    }
+}
diff --git a/test/subscriptions_importer/meson.build b/test/subscriptions_importer/meson.build
new file mode 100644
index 000000000..8d8f9df3d
--- /dev/null
+++ b/test/subscriptions_importer/meson.build
@@ -0,0 +1,6 @@
+executable('subscriptions_importer', 'main.cpp',
+    link_with: [medialib],
+    include_directories: [includes, test_include_dir],
+    dependencies: [sqlite_dep],
+    build_by_default: true
+)
-- 
GitLab