Folders.cpp 8.2 KB
Newer Older
1 2 3 4 5 6
#include "gtest/gtest.h"

#include "IFile.h"
#include "IFolder.h"
#include "IMediaLibrary.h"

7 8
#include "filesystem/IDirectory.h"
#include "filesystem/IFile.h"
9 10 11 12
#include "Utils.h"

#include <memory>
#include <unordered_map>
13 14 15 16

namespace mock
{

17 18 19
class File : public fs::IFile
{
public:
20 21 22 23 24
    File( const std::string& filePath )
        : m_name( utils::file::fileName( filePath ) )
        , m_path( utils::file::directory( filePath ) )
        , m_fullPath( filePath )
        , m_extension( utils::file::extension( filePath ) )
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
        , m_lastModification( 0 )
    {
    }

    File( const File& ) = default;

    virtual const std::string& name() const override
    {
        return m_name;
    }

    virtual const std::string& path() const override
    {
        return m_path;
    }

    virtual const std::string& fullPath() const override
    {
        return m_fullPath;
    }

    virtual const std::string& extension() const override
    {
        return m_extension;
    }

    virtual unsigned int lastModificationDate() const override
    {
        return m_lastModification;
    }

    std::string m_name;
    std::string m_path;
    std::string m_fullPath;
    std::string m_extension;
    unsigned int m_lastModification;
};

63 64 65
class Directory : public fs::IDirectory
{
public:
66
    Directory( const std::string& path, unsigned int lastModif )
67
        : m_path( path )
68
        , m_lastModificationDate( lastModif )
69 70 71 72 73 74 75 76 77 78 79 80 81
    {
    }

    virtual const std::string& path() const
    {
        return m_path;
    }

    virtual const std::vector<std::string>& files() const
    {
        return m_files;
    }

82 83 84 85 86
    virtual const std::vector<std::string>& dirs() const
    {
        return m_dirs;
    }

87 88 89 90 91
    virtual unsigned int lastModificationDate() const override
    {
        return m_lastModificationDate;
    }

92 93 94
    void addFile( const std::string& fileName )
    {
        m_files.emplace_back( m_path + fileName );
95
        m_lastModificationDate++;
96 97 98 99 100
    }

    void addFolder( const std::string& folder )
    {
        m_dirs.emplace_back( m_path + folder );
101
        m_lastModificationDate++;
102 103
    }

104 105 106
private:
    std::string m_path;
    std::vector<std::string> m_files;
107
    std::vector<std::string> m_dirs;
108
    unsigned int m_lastModificationDate;
109 110 111 112 113 114 115
};


struct FileSystemFactory : public factory::IFileSystem
{
    static constexpr const char* Root = "/a/";
    static constexpr const char* SubFolder = "/a/folder/";
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

    FileSystemFactory()
    {
        dirs[Root] = std::unique_ptr<mock::Directory>( new Directory{ Root, 123 } );
            addFile( Root, "video.avi" );
            addFile( Root, "audio.mp3" );
            addFile( Root, "not_a_media.something" );
            addFile( Root, "some_other_file.seaotter" );
            addFolder( Root, "folder/", 456 );
                addFile( SubFolder, "subfile.mp4" );
    }

    void addFile( const std::string& path, const std::string& fileName )
    {
        dirs[path]->addFile( fileName );
131
        files[path + fileName] = std::unique_ptr<mock::File>( new mock::File( path + fileName ) );
132 133
    }

134
    void addFolder( const std::string& parentPath, const std::string& path, unsigned int lastModif )
135
    {
136 137 138
        auto parent = dirs[parentPath];
        parent->addFolder( path );
        dirs[parentPath + path] = std::unique_ptr<mock::Directory>( new Directory( parent, parentPath + path, lastModif ) );
139 140
    }

141 142
    virtual std::unique_ptr<fs::IDirectory> createDirectory(const std::string& path) override
    {
143 144
        mock::Directory* res = nullptr;
        if ( path == "." )
145
        {
146
            res = dirs[Root].get();
147
        }
148
        else
149
        {
150 151 152
            auto it = dirs.find( path );
            if ( it != end( dirs ) )
                res = it->second.get();
153
        }
154 155 156 157 158
        if ( res == nullptr )
            throw std::runtime_error("Invalid path");
        return std::unique_ptr<fs::IDirectory>( new Directory( *res ) );
    }

159
    virtual std::unique_ptr<fs::IFile> createFile( const std::string &filePath ) override
160
    {
161
        const auto it = files.find( filePath );
162
        if ( it == end( files ) )
163
            files[filePath].reset( new File( filePath ) );
164
        return std::unique_ptr<fs::IFile>( new File( static_cast<const mock::File&>( * it->second.get() ) ) );
165
    }
166 167 168

    std::unordered_map<std::string, std::unique_ptr<mock::File>> files;
    std::unordered_map<std::string, std::unique_ptr<mock::Directory>> dirs;
169 170 171 172
};

}

173 174 175 176
class Folders : public testing::Test
{
    public:
        static std::unique_ptr<IMediaLibrary> ml;
177
        std::shared_ptr<mock::FileSystemFactory> fsMock;
178 179

    protected:
180
        virtual void Reload()
181 182
        {
            ml.reset( MediaLibraryFactory::create() );
183
            bool res = ml->initialize( "test.db", fsMock );
184 185 186
            ASSERT_TRUE( res );
        }

187 188 189 190 191 192
        virtual void SetUp()
        {
            fsMock.reset( new mock::FileSystemFactory );
            Reload();
        }

193 194 195 196 197 198 199 200 201 202 203
        virtual void TearDown()
        {
            ml.reset();
            unlink("test.db");
        }
};

std::unique_ptr<IMediaLibrary> Folders::ml;

TEST_F( Folders, Add )
{
204 205 206
    auto f = ml->addFolder( "." );
    ASSERT_NE( f, nullptr );

207
    auto files = ml->files();
208

209
    ASSERT_EQ( files.size(), 3u );
210 211 212 213 214 215
    ASSERT_FALSE( files[0]->isStandAlone() );
}

TEST_F( Folders, Delete )
{
    auto f = ml->addFolder( "." );
216
    ASSERT_NE( f, nullptr );
217

218 219
    auto folderPath = f->path();

220
    auto files = ml->files();
221
    ASSERT_EQ( files.size(), 3u );
222

223 224
    auto filePath = files[0]->mrl();

225 226
    ml->deleteFolder( f );

227 228 229
    f = ml->folder( folderPath );
    ASSERT_EQ( nullptr, f );

230
    files = ml->files();
231
    ASSERT_EQ( files.size(), 0u );
232 233 234 235 236 237 238 239 240 241

    // Check the file isn't cached anymore:
    auto file = ml->file( filePath );
    ASSERT_EQ( nullptr, file );

    SetUp();

    // Recheck folder deletion from DB:
    f = ml->folder( folderPath );
    ASSERT_EQ( nullptr, f );
242 243 244 245 246
}

TEST_F( Folders, Load )
{
    auto f = ml->addFolder( "." );
247
    ASSERT_NE( f, nullptr );
248 249 250

    SetUp();

251 252 253 254
    auto files = ml->files();
    ASSERT_EQ( files.size(), 3u );
    for ( auto& f : files )
        ASSERT_FALSE( f->isStandAlone() );
255
}
256 257 258 259 260 261

TEST_F( Folders, InvalidPath )
{
    auto f = ml->addFolder( "/invalid/path" );
    ASSERT_EQ( f, nullptr );

262
    auto files = ml->files();
263 264
    ASSERT_EQ( files.size(), 0u );
}
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279

TEST_F( Folders, List )
{
    auto f = ml->addFolder( "." );
    ASSERT_NE( f, nullptr );

    auto files = f->files();
    ASSERT_EQ( files.size(), 2u );

    SetUp();

    f = ml->folder( f->path() );
    files = f->files();
    ASSERT_EQ( files.size(), 2u );
}
280 281 282 283 284 285

TEST_F( Folders, AbsolutePath )
{
    auto f = ml->addFolder( "." );
    ASSERT_NE( f->path(), "." );
}
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313

TEST_F( Folders, ListFolders )
{
    auto f = ml->addFolder( "." );
    auto subFolders = f->folders();
    ASSERT_EQ( 1u, subFolders.size() );

    auto subFolder = subFolders[0];
    auto subFiles = subFolder->files();
    ASSERT_EQ( 1u, subFiles.size() );

    auto file = subFiles[0];
    ASSERT_EQ( std::string{ mock::FileSystemFactory::SubFolder } + "subfile.mp4", file->mrl() );

    // Now again, without cache
    SetUp();

    f = ml->folder( f->path() );
    subFolders = f->folders();
    ASSERT_EQ( 1u, subFolders.size() );

    subFolder = subFolders[0];
    subFiles = subFolder->files();
    ASSERT_EQ( 1u, subFiles.size() );

    file = subFiles[0];
    ASSERT_EQ( std::string{ mock::FileSystemFactory::SubFolder } + "subfile.mp4", file->mrl() );
}
314 315 316 317

TEST_F( Folders, LastModificationDate )
{
    auto f = ml->addFolder( "." );
318
    ASSERT_NE( 0u, f->lastModificationDate() );
319
    auto subFolders = f->folders();
320
    ASSERT_NE( 0u, subFolders[0]->lastModificationDate() );
321 322 323 324

    SetUp();

    f = ml->folder( f->path() );
325
    ASSERT_NE( 0u, f->lastModificationDate() );
326
    subFolders = f->folders();
327
    ASSERT_NE( 0u, subFolders[0]->lastModificationDate() );
328
}
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346

TEST_F( Folders, NewFile )
{
    ml->addFolder( "." );

    ASSERT_EQ( 3u, ml->files().size() );
    // Do not watch for live changes
    ml.reset();
    auto newFolder = std::string(mock::FileSystemFactory::Root) + "newfolder/";
    fsMock->addFolder( mock::FileSystemFactory::Root, "newfolder/", time( nullptr ) );
    fsMock->addFile( newFolder, "newfile.avi" );

    Reload();

    ASSERT_EQ( 4u, ml->files().size() );
    auto file = ml->file( newFolder + "newfile.avi" );
    ASSERT_NE( nullptr, file );
}