Tests written for service info persistence.
Class names also changed.
This commit is contained in:
		@@ -0,0 +1,176 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using GameServiceWarden.Core.Games;
 | 
			
		||||
using GameServiceWarden.ModuleAPI;
 | 
			
		||||
 | 
			
		||||
namespace GameServiceWarden.Core.Persistence
 | 
			
		||||
{
 | 
			
		||||
    public class PersistedGameServiceInfos : IPersistent<GameServiceInfo>
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IReadOnlyPersistent<IReadOnlyDictionary<string, IGameServiceModule>> modules;
 | 
			
		||||
        private readonly string mapDirectory;
 | 
			
		||||
        private const string ASSEMBLY_NAME = "Assembly Name";
 | 
			
		||||
        private const string MODULE_NAME = "Module Name";
 | 
			
		||||
        private const string EXTENSION = ".sin";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public PersistedGameServiceInfos(string mapDirectory, IReadOnlyPersistent<IReadOnlyDictionary<string, IGameServiceModule>> modules)
 | 
			
		||||
        {
 | 
			
		||||
            this.mapDirectory = mapDirectory;
 | 
			
		||||
            this.modules = modules;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public GameServiceInfo this[string key]
 | 
			
		||||
        {
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                value.ServiceName = key;
 | 
			
		||||
                SaveService(key, value.GetAssemblyName(), value.ModuleName);
 | 
			
		||||
            }
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (!ContainsKey(key)) throw new KeyNotFoundException();
 | 
			
		||||
                string assemblyName = GetServiceInfoValue(key, ASSEMBLY_NAME);
 | 
			
		||||
                string moduleName = GetServiceInfoValue(key, MODULE_NAME);
 | 
			
		||||
                IGameService service = modules[assemblyName][moduleName].InstantiateGameService(GetPathForKey(key), false);
 | 
			
		||||
                return new GameServiceInfo(service, moduleName, assemblyName);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string MapDirectory { get { return mapDirectory; } }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public int Count
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return Directory.GetFiles(mapDirectory).Length;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<GameServiceInfo> Values {
 | 
			
		||||
            get {
 | 
			
		||||
                IEnumerable<string> keys = Keys;
 | 
			
		||||
                List<GameServiceInfo> res = new List<GameServiceInfo>();
 | 
			
		||||
                foreach (string key in keys)
 | 
			
		||||
                {
 | 
			
		||||
                    res.Add(this[key]);
 | 
			
		||||
                }
 | 
			
		||||
                return res;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<string> Keys {
 | 
			
		||||
            get {
 | 
			
		||||
                IEnumerable<string> keys = Directory.EnumerateDirectories(mapDirectory);
 | 
			
		||||
                List<string> res = new List<string>();
 | 
			
		||||
                foreach (string key in keys)
 | 
			
		||||
                {
 | 
			
		||||
                    res.Add(Path.GetDirectoryName(key));
 | 
			
		||||
                }
 | 
			
		||||
                return res;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void AddToPersistence(string key, GameServiceInfo value)
 | 
			
		||||
        {
 | 
			
		||||
            if (key == null) throw new ArgumentNullException();
 | 
			
		||||
            if (ContainsKey(key)) throw new ArgumentException();
 | 
			
		||||
            this[key] = value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Clear()
 | 
			
		||||
        {
 | 
			
		||||
            IEnumerable<string> directories = Keys;
 | 
			
		||||
            foreach (string directory in directories)
 | 
			
		||||
            {
 | 
			
		||||
                Directory.Delete(directory);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool ContainsKey(string key)
 | 
			
		||||
        {
 | 
			
		||||
            return Directory.Exists(GetPathForKey(key));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerator<KeyValuePair<string, GameServiceInfo>> GetEnumerator()
 | 
			
		||||
        {
 | 
			
		||||
            IEnumerable<string> keys = Keys;
 | 
			
		||||
            List<KeyValuePair<string, GameServiceInfo>> result = new List<KeyValuePair<string, GameServiceInfo>>();
 | 
			
		||||
            foreach (string key in keys)
 | 
			
		||||
            {
 | 
			
		||||
                result.Add(new KeyValuePair<string, GameServiceInfo>(key, this[key]));
 | 
			
		||||
            }
 | 
			
		||||
            return result.GetEnumerator();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string GetPathForKey(string key)
 | 
			
		||||
        {
 | 
			
		||||
            return Path.Combine(mapDirectory, key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool Delete(string key)
 | 
			
		||||
        {
 | 
			
		||||
            if (!ContainsKey(key)) return false;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                Directory.Delete(GetPathForKey(key));
 | 
			
		||||
            }
 | 
			
		||||
            catch (System.Exception)
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
                throw;
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool TryLoadValue(string key, [MaybeNullWhen(false)] out GameServiceInfo value)
 | 
			
		||||
        {
 | 
			
		||||
            try {
 | 
			
		||||
                value = this[key];
 | 
			
		||||
            } catch (KeyNotFoundException) {
 | 
			
		||||
                value = null;
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        IEnumerator IEnumerable.GetEnumerator()
 | 
			
		||||
        {
 | 
			
		||||
            return GetEnumerator();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void SaveService(string key, string assemblyName, string moduleName)
 | 
			
		||||
        {
 | 
			
		||||
            if (key == null) throw new ArgumentNullException("key");
 | 
			
		||||
            if (assemblyName == null) throw new ArgumentNullException("assemblyName");
 | 
			
		||||
            if (moduleName == null) throw new ArgumentNullException("moduleName");
 | 
			
		||||
            string serviceInfoPath = GetPathForKey(key);
 | 
			
		||||
            Directory.CreateDirectory(serviceInfoPath);
 | 
			
		||||
            using (StreamWriter writer = File.CreateText(Path.Combine(serviceInfoPath, key + EXTENSION)))
 | 
			
		||||
            {
 | 
			
		||||
                writer.WriteLine($"{ASSEMBLY_NAME}: {assemblyName}");
 | 
			
		||||
                writer.WriteLine($"{MODULE_NAME}: {moduleName}");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private string GetServiceInfoValue(string key, string value)
 | 
			
		||||
        {
 | 
			
		||||
            string path = GetPathForKey(key);
 | 
			
		||||
            IEnumerable<string> lines = File.ReadAllLines(Path.Combine(path, key + EXTENSION));
 | 
			
		||||
            foreach (string line in lines)
 | 
			
		||||
            {
 | 
			
		||||
                if (line.StartsWith($"{value}: "))
 | 
			
		||||
                {
 | 
			
		||||
                    return line.Substring(value.Length + 2);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            throw new FormatException($"\"{path}\" is corrupted. Could not find value for: {value}.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,95 @@
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using GameServiceWarden.Core.Games;
 | 
			
		||||
using GameServiceWarden.Core.Persistence;
 | 
			
		||||
using GameServiceWarden.Core.Tests.Modules;
 | 
			
		||||
using GameServiceWarden.Core.Tests.Modules.Games;
 | 
			
		||||
using GameServiceWarden.ModuleAPI;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace GameServiceWarden.Core.Tests.Persistence
 | 
			
		||||
{
 | 
			
		||||
    public class PersistedGameServiceInfosTest
 | 
			
		||||
    {
 | 
			
		||||
        //MethodTested_ScenarioTested_ExpectedBehavior
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void GetPathForKey_PathGen_ExpectedPathResult()
 | 
			
		||||
        {
 | 
			
		||||
            //Given
 | 
			
		||||
            const string TEST_DIR = "services";
 | 
			
		||||
            const string MODULE_NAME = "fake_module";
 | 
			
		||||
            const string ASSEMBLY_NAME = "fake_assembly";
 | 
			
		||||
            const string SERVICE_NAME = "fake_service";
 | 
			
		||||
            FakePersistence<IReadOnlyDictionary<string, IGameServiceModule>> stubModulesPersistence = new FakePersistence<IReadOnlyDictionary<string, IGameServiceModule>>();
 | 
			
		||||
            Dictionary<string, IGameServiceModule> stubAssemblyDict = new Dictionary<string, IGameServiceModule>();
 | 
			
		||||
            FakeGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
 | 
			
		||||
 | 
			
		||||
            stubAssemblyDict[MODULE_NAME] = stubGameServiceModule;
 | 
			
		||||
            stubModulesPersistence[ASSEMBLY_NAME] = stubAssemblyDict;
 | 
			
		||||
 | 
			
		||||
            PersistedGameServiceInfos persistedGameServices = new PersistedGameServiceInfos(TEST_DIR, stubModulesPersistence);
 | 
			
		||||
 | 
			
		||||
            //Then
 | 
			
		||||
            Assert.True(persistedGameServices.GetPathForKey(SERVICE_NAME).Equals(Path.Combine(TEST_DIR, SERVICE_NAME)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void Save_SavingService_FileCreated()
 | 
			
		||||
        {
 | 
			
		||||
            //Given
 | 
			
		||||
            const string TEST_DIR = "services";
 | 
			
		||||
            const string MODULE_NAME = "fake_module";
 | 
			
		||||
            const string ASSEMBLY_NAME = "fake_assembly";
 | 
			
		||||
            const string SERVICE_NAME = "fake_service";
 | 
			
		||||
            FakePersistence<IReadOnlyDictionary<string, IGameServiceModule>> stubModulesPersistence = new FakePersistence<IReadOnlyDictionary<string, IGameServiceModule>>();
 | 
			
		||||
            Dictionary<string, IGameServiceModule> stubAssemblyDict = new Dictionary<string, IGameServiceModule>();
 | 
			
		||||
            FakeGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
 | 
			
		||||
 | 
			
		||||
            stubAssemblyDict[MODULE_NAME] = stubGameServiceModule;
 | 
			
		||||
            stubModulesPersistence[ASSEMBLY_NAME] = stubAssemblyDict;
 | 
			
		||||
 | 
			
		||||
            PersistedGameServiceInfos persistedGameServiceInfos = new PersistedGameServiceInfos(TEST_DIR, stubModulesPersistence);
 | 
			
		||||
 | 
			
		||||
            GameServiceInfo stubGameServiceInfo = new GameServiceInfo(stubModulesPersistence[ASSEMBLY_NAME][MODULE_NAME].InstantiateGameService(persistedGameServiceInfos.GetPathForKey(SERVICE_NAME), true), MODULE_NAME, ASSEMBLY_NAME);
 | 
			
		||||
            //When
 | 
			
		||||
            persistedGameServiceInfos[SERVICE_NAME] = stubGameServiceInfo;
 | 
			
		||||
            //Then
 | 
			
		||||
            Assert.True(Directory.Exists(TEST_DIR));
 | 
			
		||||
            Assert.True(Directory.Exists(persistedGameServiceInfos.GetPathForKey(SERVICE_NAME)));
 | 
			
		||||
            string[] files = Directory.GetFiles(persistedGameServiceInfos.GetPathForKey(SERVICE_NAME));
 | 
			
		||||
            Assert.True(files.Length == 1);
 | 
			
		||||
            Assert.StartsWith(SERVICE_NAME, Path.GetFileName(files[0]));
 | 
			
		||||
 | 
			
		||||
            Directory.Delete(TEST_DIR, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void Save_ReadingService_MetadataRead()
 | 
			
		||||
        {
 | 
			
		||||
            //Given
 | 
			
		||||
            const string TEST_DIR = "services";
 | 
			
		||||
            const string MODULE_NAME = "fake_module";
 | 
			
		||||
            const string ASSEMBLY_NAME = "fake_assembly";
 | 
			
		||||
            const string SERVICE_NAME = "fake_service";
 | 
			
		||||
            FakePersistence<IReadOnlyDictionary<string, IGameServiceModule>> stubModulesPersistence = new FakePersistence<IReadOnlyDictionary<string, IGameServiceModule>>();
 | 
			
		||||
            Dictionary<string, IGameServiceModule> stubAssemblyDict = new Dictionary<string, IGameServiceModule>();
 | 
			
		||||
            FakeGameServiceModule stubGameServiceModule = new FakeGameServiceModule();
 | 
			
		||||
 | 
			
		||||
            stubAssemblyDict[MODULE_NAME] = stubGameServiceModule;
 | 
			
		||||
            stubModulesPersistence[ASSEMBLY_NAME] = stubAssemblyDict;
 | 
			
		||||
 | 
			
		||||
            PersistedGameServiceInfos persistedGameServices = new PersistedGameServiceInfos(TEST_DIR, stubModulesPersistence);
 | 
			
		||||
 | 
			
		||||
            GameServiceInfo stubGameServiceInfo = new GameServiceInfo(stubModulesPersistence[ASSEMBLY_NAME][MODULE_NAME].InstantiateGameService(persistedGameServices.GetPathForKey(SERVICE_NAME), true), MODULE_NAME, ASSEMBLY_NAME);
 | 
			
		||||
            persistedGameServices[SERVICE_NAME] = stubGameServiceInfo;
 | 
			
		||||
            //When
 | 
			
		||||
            GameServiceInfo loadedService = persistedGameServices[SERVICE_NAME];
 | 
			
		||||
            //Then
 | 
			
		||||
            Assert.True(loadedService.ModuleName.Equals(MODULE_NAME));
 | 
			
		||||
            Assert.True(loadedService.GetAssemblyName().Equals(ASSEMBLY_NAME));
 | 
			
		||||
 | 
			
		||||
            Directory.Delete(TEST_DIR, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user