MediaScannerService unit test and test media library

(cherry picked from commit c2b17f0)

Signed-off-by: Rémi Cocula <rcocula@gmail.com>
master
remi 8 years ago committed by Rémi Cocula
parent 81730fe52f
commit ba28d52ba4
  1. 9
      libresonic-main/pom.xml
  2. 5
      libresonic-main/src/main/java/org/libresonic/player/service/MediaScannerService.java
  3. 93
      libresonic-main/src/test/java/org/libresonic/player/TestCaseUtils.java
  4. 39
      libresonic-main/src/test/java/org/libresonic/player/dao/MusicFolderDaoMock.java
  5. 141
      libresonic-main/src/test/java/org/libresonic/player/service/MediaScannerServiceTestCase.java
  6. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Céline Frisch- Café Zimmermann - Bach- Goldberg Variations, Canons [Disc 1]/01 - Bach- Goldberg Variations, BWV 988 - Aria.flac
  7. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Céline Frisch- Café Zimmermann - Bach- Goldberg Variations, Canons [Disc 1]/02 - Bach- Goldberg Variations, BWV 988 - Variatio 1 A 1 Clav..flac
  8. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Céline Frisch- Café Zimmermann - Bach- Goldberg Variations, Canons [Disc 1]/Folder.jpg
  9. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Ravel/_DIR_ Ravel - Chamber Music With Voice/01 - Sonata Violin & Cello I. Allegro.ogg
  10. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Ravel/_DIR_ Ravel - Chamber Music With Voice/02 - Sonata Violin & Cello II. Tres Vif.ogg
  11. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Ravel/_DIR_ Ravel - Chamber Music With Voice/Folder.jpg
  12. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Ravel/_DIR_ Ravel - Complete Piano Works/01 - Gaspard de la Nuit - i. Ondine.mp3
  13. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Ravel/_DIR_ Ravel - Complete Piano Works/02 - Gaspard de la Nuit - ii. Le Gibet.mp3
  14. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Ravel/_DIR_ Ravel - Complete Piano Works/Folder.jpeg
  15. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Sixteen Horsepower/_DIR_ Sackcloth 'n' Ashes/Sixteen Horsepower - 01 I Seen What I Saw.mp3
  16. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Sixteen Horsepower/_DIR_ Sackcloth 'n' Ashes/Sixteen Horsepower - 02 Black Soul Choir.mp3
  17. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Sixteen Horsepower/_DIR_ Sackcloth 'n' Ashes/Sixteen Horsepower - 10 Reed Neck Reel.mp3
  18. BIN
      libresonic-main/src/test/resources/MEDIAS/Music/_DIR_ Sixteen Horsepower/_DIR_ Sackcloth 'n' Ashes/cover.jpg
  19. BIN
      libresonic-main/src/test/resources/MEDIAS/Music2/_DIR_ chrome hoof - 2004/02 eyes like dull hazlenuts.mp3
  20. BIN
      libresonic-main/src/test/resources/MEDIAS/Music2/_DIR_ chrome hoof - 2004/10 telegraph hill.mp3
  21. BIN
      libresonic-main/src/test/resources/MEDIAS/Music2/_DIR_ chrome hoof - 2004/Folder.jpg
  22. 17
      libresonic-main/src/test/resources/org/libresonic/player/service/mediaScannerServiceTestCase/applicationContext-cache.xml
  23. 186
      libresonic-main/src/test/resources/org/libresonic/player/service/mediaScannerServiceTestCase/applicationContext-service.xml

@ -26,6 +26,15 @@
<version>${project.version}</version>
</dependency>
<!-- Metrics -->
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>

@ -70,6 +70,11 @@ public class MediaScannerService {
schedule();
}
public void initNoSchedule() {
deleteOldIndexFiles();
statistics = settingsService.getMediaLibraryStatistics();
}
/**
* Schedule background execution of media library scanning.
*/

@ -0,0 +1,93 @@
package org.libresonic.player;
import org.libresonic.player.dao.DaoHelper;
import org.libresonic.player.service.MediaScannerService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TestCaseUtils {
/**
* Constructs a map of records count per table.
*
* @param daoHelper DaoHelper object
* @return Map table name -> records count
*/
public static Map<String, Integer> recordsInAllTables(DaoHelper daoHelper) {
List<String> tableNames = daoHelper.getJdbcTemplate().queryForList("" +
"select table_name " +
"from information_schema.system_tables " +
"where table_name not like 'SYSTEM%'"
, String.class);
Map<String, Integer> nbRecords =
tableNames.stream()
.collect(Collectors.toMap(table -> table, table -> recordsInTable(table,daoHelper)));
return nbRecords;
}
/**
* Counts records in a table.
*
* @param tableName
* @param daoHelper
* @return
*/
public static Integer recordsInTable(String tableName, DaoHelper daoHelper) {
return daoHelper.getJdbcTemplate().queryForInt("select count(1) from " + tableName);
}
/**
* Constructs the path of a resource according to the path of the current class.
*
* @param baseResources
* @return
*/
private static String basePath(String baseResources) {
String basePath = TestCaseUtils.class.getResource(baseResources).toString();
if (basePath.startsWith("file:")) {
return TestCaseUtils.class.getResource(baseResources).toString().replace("file:","");
}
return basePath;
}
public static void setLibresonicHome(String baseResources) {
String subsoncicHome = basePath(baseResources);
System.setProperty("libresonic.home",subsoncicHome);
}
public static ApplicationContext loadSpringApplicationContext(String baseResources) {
String applicationContextService = baseResources + "applicationContext-service.xml";
String applicationContextCache = baseResources + "applicationContext-cache.xml";
String[] configLocations = new String[]{
TestCaseUtils.class.getClass().getResource(applicationContextCache).toString(),
TestCaseUtils.class.getClass().getResource(applicationContextService).toString()
};
return new ClassPathXmlApplicationContext(configLocations);
}
/**
* Scans the music library * @param mediaScannerService
*/
public static void execScan(MediaScannerService mediaScannerService) {
mediaScannerService.scanLibrary();
while (mediaScannerService.isScanning()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

@ -0,0 +1,39 @@
package org.libresonic.player.dao;
import org.libresonic.player.domain.MusicFolder;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class MusicFolderDaoMock extends MusicFolderDao {
private static String baseResources = "/MEDIAS/";
public static String resolveBaseMediaPath() {
String baseDir = MusicFolderDaoMock.class.getResource(baseResources).toString().replace("file:","");
return baseDir;
}
public static String resolveMusicFolderPath() {
return (MusicFolderDaoMock.resolveBaseMediaPath() + "Music");
}
public static String resolveMusic2FolderPath() {
return (MusicFolderDaoMock.resolveBaseMediaPath() + "Music2");
}
@Override
public List<MusicFolder> getAllMusicFolders() {
List<MusicFolder> liste = new ArrayList<>();
File musicDir = new File(MusicFolderDaoMock.resolveMusicFolderPath());
MusicFolder musicFolder = new MusicFolder(1,musicDir,"Music",true,new Date());
liste.add(musicFolder);
File music2Dir = new File(MusicFolderDaoMock.resolveMusic2FolderPath());
MusicFolder musicFolder2 = new MusicFolder(2,music2Dir,"Music2",true,new Date());
liste.add(musicFolder2);
return liste;
}
}

@ -0,0 +1,141 @@
package org.libresonic.player.service;
import com.codahale.metrics.ConsoleReporter;
import com.codahale.metrics.JmxReporter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.libresonic.player.TestCaseUtils;
import org.libresonic.player.dao.*;
import org.libresonic.player.domain.Album;
import org.libresonic.player.domain.Artist;
import org.libresonic.player.domain.MediaFile;
import org.springframework.context.ApplicationContext;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* A unit test class to test the MediaScannerService.
*
* This class uses the Spring application context configuration present in the
* /org/libresonic/player/service/mediaScannerServiceTestCase/ directory.
*
* The media library is found in the /MEDIAS directory.
* It is composed of 2 musicFolders (Music and Music2) and several little weight audio files.
*
* At runtime, the subsonic_home dir is set to target/test-classes/org/libresonic/player/service/mediaScannerServiceTestCase.
* An empty database is created on the fly.
*
*/
public class MediaScannerServiceTestCase extends TestCase {
private static String baseResources = "/org/libresonic/player/service/mediaScannerServiceTestCase/";
private final MetricRegistry metrics = new MetricRegistry();
private MediaScannerService mediaScannerService = null;
private MediaFileDao mediaFileDao = null;
private MusicFolderDao musicFolderDao = null;
private DaoHelper daoHelper = null;
private MediaFileService mediaFileService = null;
private ArtistDao artistDao = null;
private AlbumDao albumDao = null;
@Override
protected void setUp() throws Exception {
super.setUp();
TestCaseUtils.setLibresonicHome(baseResources);
// load spring context
ApplicationContext context = TestCaseUtils.loadSpringApplicationContext(baseResources);
mediaScannerService = (MediaScannerService)context.getBean("mediaScannerService");
mediaFileDao = (MediaFileDao)context.getBean("mediaFileDao");
musicFolderDao = (MusicFolderDao) context.getBean("musicFolderDao");
daoHelper = (DaoHelper) context.getBean("daoHelper");
mediaFileService = (MediaFileService) context.getBean("mediaFileService");
artistDao = (ArtistDao) context.getBean("artistDao");
albumDao = (AlbumDao) context.getBean("albumDao");
}
/**
* Tests the MediaScannerService by scanning the test media library into an empty database.
*/
public void testScanLibrary() {
//startMetricsReport();
Timer globalTimer = metrics.timer(MetricRegistry.name(MediaScannerServiceTestCase.class, "Timer.global"));
Timer.Context globalTimerContext = globalTimer.time();
TestCaseUtils.execScan(mediaScannerService);
globalTimerContext.stop();
System.out.println("--- Report of records count per table ---");
Map<String,Integer> records = TestCaseUtils.recordsInAllTables(daoHelper);
records.keySet().forEach(tableName -> System.out.println(tableName+" : "+records.get(tableName).toString() ));
System.out.println("--- *********************** ---");
// Music Folder Music must have 3 children
List<MediaFile> listeMusicChildren = mediaFileDao.getChildrenOf(MusicFolderDaoMock.resolveMusicFolderPath());
Assert.assertEquals(3,listeMusicChildren.size());
// Music Folder Music2 must have 1 children
List<MediaFile> listeMusic2Children = mediaFileDao.getChildrenOf(MusicFolderDaoMock.resolveMusic2FolderPath());
Assert.assertEquals(1,listeMusic2Children.size());
System.out.println("--- List of all artists ---");
System.out.println("artistName#albumCount");
List<Artist> allArtists = artistDao.getAlphabetialArtists(0,0,musicFolderDao.getAllMusicFolders());
allArtists.forEach(artist -> System.out.println(artist.getName()+"#"+artist.getAlbumCount()));
System.out.println("--- *********************** ---");
System.out.println("--- List of all albums ---");
System.out.println("name#artist");
List<Album> allAlbums = albumDao.getAlphabetialAlbums(0,0,true,musicFolderDao.getAllMusicFolders());
allAlbums.forEach(album -> System.out.println(album.getName()+"#"+album.getArtist()));
Assert.assertEquals(5,allAlbums.size());
System.out.println("--- *********************** ---");
List<MediaFile> listeSongs = mediaFileDao.getSongsByGenre("Baroque Instrumental",0,0,musicFolderDao.getAllMusicFolders());
// display out metrics report
ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics)
.convertRatesTo(TimeUnit.SECONDS.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.report();
System.out.print("End");
}
/**
* Starts a Metrics Console and JMX reporter.
*/
private void startMetricsReport() {
// Reporter console
ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics)
.convertRatesTo(TimeUnit.SECONDS.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.start(10, TimeUnit.SECONDS);
// Jmx reporter
final JmxReporter jmxReporter = JmxReporter.forRegistry(metrics).build();
jmxReporter.start();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="cacheFactory" class="org.libresonic.player.cache.CacheFactory"/>
<bean id="userCache" factory-bean="cacheFactory" factory-method="getCache">
<constructor-arg value="userCache"/>
</bean>
<bean id="mediaFileMemoryCache" factory-bean="cacheFactory" factory-method="getCache">
<constructor-arg value="mediaFileMemoryCache"/>
</bean>
</beans>

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- DAO's -->
<bean id="playerDao" class="org.libresonic.player.dao.PlayerDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="mediaFileDao" class="org.libresonic.player.dao.MediaFileDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="artistDao" class="org.libresonic.player.dao.ArtistDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="albumDao" class="org.libresonic.player.dao.AlbumDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="playlistDao" class="org.libresonic.player.dao.PlaylistDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="playQueueDao" class="org.libresonic.player.dao.PlayQueueDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="internetRadioDao" class="org.libresonic.player.dao.InternetRadioDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="musicFileInfoDao" class="org.libresonic.player.dao.RatingDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="musicFolderDao" class="org.libresonic.player.dao.MusicFolderDaoMock">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="userDao" class="org.libresonic.player.dao.UserDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="transcodingDao" class="org.libresonic.player.dao.TranscodingDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="podcastDao" class="org.libresonic.player.dao.PodcastDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="avatarDao" class="org.libresonic.player.dao.AvatarDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="shareDao" class="org.libresonic.player.dao.ShareDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="bookmarkDao" class="org.libresonic.player.dao.BookmarkDao">
<property name="daoHelper" ref="daoHelper"/>
</bean>
<bean id="daoHelper" class="org.libresonic.player.dao.DaoHelperFactory" factory-method="create"/>
<!-- Services -->
<bean id="mediaFileService" class="org.libresonic.player.service.MediaFileService">
<property name="securityService" ref="securityService"/>
<property name="settingsService" ref="settingsService"/>
<property name="mediaFileMemoryCache" ref="mediaFileMemoryCache"/>
<property name="mediaFileDao" ref="mediaFileDao"/>
<property name="albumDao" ref="albumDao"/>
<property name="metaDataParserFactory" ref="metaDataParserFactory"/>
</bean>
<bean id="securityService" class="org.libresonic.player.service.SecurityService">
<property name="settingsService" ref="settingsService"/>
<property name="userDao" ref="userDao"/>
<property name="userCache" ref="userCache"/>
</bean>
<bean id="settingsService" class="org.libresonic.player.service.SettingsService" init-method="init">
<property name="internetRadioDao" ref="internetRadioDao"/>
<property name="musicFolderDao" ref="musicFolderDao"/>
<property name="userDao" ref="userDao"/>
<property name="avatarDao" ref="avatarDao"/>
<property name="versionService" ref="versionService"/>
</bean>
<bean id="mediaScannerService" class="org.libresonic.player.service.MediaScannerService" init-method="initNoSchedule" depends-on="metaDataParserFactory">
<property name="settingsService" ref="settingsService"/>
<property name="mediaFileService" ref="mediaFileService"/>
<property name="mediaFileDao" ref="mediaFileDao"/>
<property name="playlistService" ref="playlistService"/>
<property name="artistDao" ref="artistDao"/>
<property name="albumDao" ref="albumDao"/>
<property name="searchService" ref="searchService"/>
<!-- <property name="queueSender" ref="queueSender"/> -->
</bean>
<bean id="searchService" class="org.libresonic.player.service.SearchService">
<property name="mediaFileService" ref="mediaFileService"/>
<property name="artistDao" ref="artistDao"/>
<property name="albumDao" ref="albumDao"/>
</bean>
<bean id="networkService" class="org.libresonic.player.service.NetworkService" init-method="init">
<property name="settingsService" ref="settingsService"/>
</bean>
<bean id="playerService" class="org.libresonic.player.service.PlayerService" init-method="init">
<property name="playerDao" ref="playerDao"/>
<property name="statusService" ref="statusService"/>
<property name="securityService" ref="securityService"/>
<property name="transcodingService" ref="transcodingService"/>
</bean>
<bean id="playlistService" class="org.libresonic.player.service.PlaylistService">
<property name="mediaFileService" ref="mediaFileService"/>
<property name="securityService" ref="securityService"/>
<property name="settingsService" ref="settingsService"/>
<property name="mediaFileDao" ref="mediaFileDao"/>
<property name="playlistDao" ref="playlistDao"/>
</bean>
<bean id="versionService" class="org.libresonic.player.service.VersionService" init-method="init"/>
<bean id="statusService" class="org.libresonic.player.service.StatusService">
<property name="mediaFileService" ref="mediaFileService"/>
</bean>
<bean id="ratingService" class="org.libresonic.player.service.RatingService">
<property name="ratingDao" ref="musicFileInfoDao"/>
<property name="mediaFileService" ref="mediaFileService"/>
<property name="securityService" ref="securityService"/>
</bean>
<bean id="musicIndexService" class="org.libresonic.player.service.MusicIndexService">
<property name="settingsService" ref="settingsService"/>
<property name="mediaFileService" ref="mediaFileService"/>
</bean>
<bean id="transcodingService" class="org.libresonic.player.service.TranscodingService">
<property name="transcodingDao" ref="transcodingDao"/>
<property name="settingsService" ref="settingsService"/>
</bean>
<bean id="podcastService" class="org.libresonic.player.service.PodcastService" init-method="init">
<property name="podcastDao" ref="podcastDao"/>
<property name="settingsService" ref="settingsService"/>
<property name="securityService" ref="securityService"/>
<property name="mediaFileService" ref="mediaFileService"/>
<property name="metaDataParserFactory" ref="metaDataParserFactory"/>
</bean>
<bean id="metaDataParserFactory" class="org.libresonic.player.service.metadata.MetaDataParserFactory">
<property name="parsers">
<list>
<bean class="org.libresonic.player.service.metadata.JaudiotaggerParser"/>
<bean class="org.libresonic.player.service.metadata.FFmpegParser">
<property name="transcodingService" ref="transcodingService"/>
</bean>
<bean class="org.libresonic.player.service.metadata.DefaultMetaDataParser"/>
</list>
</property>
</bean>
<bean id="localeResolver" class="org.libresonic.player.i18n.LibresonicLocaleResolver">
<property name="securityService" ref="securityService"/>
<property name="settingsService" ref="settingsService"/>
</bean>
</beans>
Loading…
Cancel
Save