public async Task GetAnagramsFailedWhenWordsDictionaryIsEmpty()
        {
            _wordRepoMock.GetAllWords().Returns((List <WordEntity>)null);

            Assert.ThrowsAsync <Exception>(
                async() => await _anagramSolver.GetAnagrams("1"));

            await _wordRepoMock.Received().GetAllWords();
        }
Exemple #2
0
        public async Task <IActionResult> ExportLiftFile(string projectId)
        {
            if (!_permissionService.HasProjectPermission(Permission.ImportExport, HttpContext))
            {
                return(new ForbidResult());
            }

            // Ensure project exists
            var proj = _projectService.GetProject(projectId);

            if (proj == null)
            {
                return(new NotFoundObjectResult(projectId));
            }

            // Ensure there are words in the project
            var words = await _wordRepo.GetAllWords(projectId);

            if (words.Count == 0)
            {
                return(new BadRequestResult());
            }
            // Export the data to a zip directory
            var exportedFilepath = CreateLiftExport(projectId);

            var file        = System.IO.File.ReadAllBytes(exportedFilepath);
            var encodedFile = Convert.ToBase64String(file);

            return(new OkObjectResult(encodedFile));
        }
        public async Task AddNewWordSuccess()
        {
            var anagram = new Anagram()
            {
                Category = "cat", Word = "test-word"
            };

            var allWordsBefore = await _repo.GetAllWords();

            await _repo.AddNewWord(anagram);

            var allWordsAfter = await _repo.GetAllWords();

            Assert.AreEqual(allWordsBefore.Count + 1, allWordsAfter.Count);
            //if assertion successfull removes inserted word from file
            await RemoveLastAddedWord();
        }
Exemple #4
0
        // These internal methods are extracted for unit testing
        internal async Task <IActionResult> ExportLiftFile(string projectId, string userId)
        {
            if (!await _permissionService.HasProjectPermission(HttpContext, Permission.ImportExport))
            {
                return(Forbid());
            }

            // Sanitize projectId
            if (!Sanitization.SanitizeId(projectId))
            {
                return(new UnsupportedMediaTypeResult());
            }

            // Ensure project exists
            var proj = await _projRepo.GetProject(projectId);

            if (proj is null)
            {
                return(NotFound(projectId));
            }

            // Check if another export started
            if (_liftService.IsExportInProgress(userId))
            {
                return(Conflict());
            }

            // Store in-progress status for the export
            _liftService.SetExportInProgress(userId, true);

            try
            {
                // Ensure project has words
                var words = await _wordRepo.GetAllWords(projectId);

                if (words.Count == 0)
                {
                    _liftService.SetExportInProgress(userId, false);
                    return(BadRequest("No words to export."));
                }

                // Export the data to a zip, read into memory, and delete zip
                var exportedFilepath = await CreateLiftExport(projectId);

                // Store the temporary path to the exported file for user to download later.
                _liftService.StoreExport(userId, exportedFilepath);
                await _notifyService.Clients.All.SendAsync("DownloadReady", userId);

                return(Ok(projectId));
            }
            catch
            {
                _liftService.SetExportInProgress(userId, false);
                throw;
            }
        }
        //[BasicAuthentication(RequireSsl = false)]
        public async Task <IHttpActionResult> GetAllEnglishWords()
        {
            var resultData = await _englishWordRepository.GetAllWords();

            if (resultData == null)
            {
                return(NotFound());
            }
            return(Ok(resultData));
        }
        public async Task GetAllWordsListSuccessfully()
        {
            var anagrams = new List <Anagram>()
            {
                new Anagram()
                {
                    Category = "cat", Word = "Word"
                }
            };

            _wordRepoMock.GetAllWords().Returns(new List <WordEntity>()
            {
                new WordEntity()
            });
            _mapperMock.Map <List <Anagram> >(Arg.Any <List <WordEntity> >()).Returns(anagrams);

            await _wordService.GetAllWords();

            await _wordRepoMock.Received().GetAllWords();

            _mapperMock.Received().Map <List <Anagram> >(Arg.Any <List <WordEntity> >());
        }
        public async Task <List <Anagram> > GetAllWords()
        {
            var resultEntity = await _wordRepository.GetAllWords();

            if (resultEntity == null || resultEntity.Count < 1)
            {
                throw new Exception("No words found");
            }

            var words = _mapper.Map <List <Anagram> >(resultEntity);

            return(words);
        }
        public async Task <IActionResult> GetProjectWords(string projectId)
        {
            if (!await _permissionService.HasProjectPermission(HttpContext, Permission.WordEntry))
            {
                return(Forbid());
            }
            var proj = await _projRepo.GetProject(projectId);

            if (proj is null)
            {
                return(NotFound(projectId));
            }
            return(Ok(await _wordRepo.GetAllWords(projectId)));
        }
Exemple #9
0
        public void TestDeleteAllWords()
        {
            var inWord1    = _wordRepo.Create(Util.RandomWord(_projId)).Result;
            var inWord2    = _wordRepo.Create(Util.RandomWord(_projId)).Result;
            var diffProjId = "OTHER_PROJECT";
            var outWord    = _wordRepo.Create(Util.RandomWord(diffProjId)).Result;

            _ = _wordController.DeleteProjectWords(_projId).Result;
            Assert.That(_wordRepo.GetAllWords(_projId).Result, Has.Count.Zero);
            Assert.That(_wordRepo.GetFrontier(_projId).Result, Has.Count.Zero);
            Assert.That(_wordRepo.GetAllWords(diffProjId).Result, Has.Count.EqualTo(1));
            Assert.That(_wordRepo.GetFrontier(diffProjId).Result, Has.Count.EqualTo(1));
        }
Exemple #10
0
        private async Task RefreshCache()
        {
            await logger.InfoAsync("Refreshing Lexicon Cache...");

            lexicons = await wordRepository.ListDictionaries();

            foreach (var l in lexicons.AsParallel())
            {
                var words = await wordRepository.GetAllWords(l.Language);

                DictionaryCache.Instance.AddOrUpdateDictionary(l.Language, words);
            }
            await logger.InfoAsync("Lexicon Cache Refreshed!");

            lastCacheUpdate = DateTime.UtcNow;
        }
        public void GetAllWords_ShouldGetAllWords()
        {
            wordRepository.GetAllWords().Returns(new List <string>
            {
                "langas",
                "stalas",
                "dangus"
            });

            var result = wordService.GetAllWords();

            Assert.IsNotNull(result);
            Assert.AreEqual("langas", result.First());

            wordRepository.Received().GetAllWords();
        }
Exemple #12
0
        public void TestGetAllWords()
        {
            _repo.Create(RandomWord());
            _repo.Create(RandomWord());
            _repo.Create(RandomWord());

            var words = (_wordController.Get(_projId).Result as ObjectResult).Value as List <Word>;

            Assert.That(words, Has.Count.EqualTo(3));
            _repo.GetAllWords(_projId).Result.ForEach(word => Assert.Contains(word, words));
        }
Exemple #13
0
        public async Task <IActionResult> Get(string projectId)
        {
            if (!_permissionService.HasProjectPermission(Permission.WordEntry, HttpContext))
            {
                return(new ForbidResult());
            }

            // Ensure project exists
            var proj = _projectService.GetProject(projectId);

            if (proj == null)
            {
                return(new NotFoundObjectResult(projectId));
            }

            return(new ObjectResult(await _wordRepo.GetAllWords(projectId)));
        }
Exemple #14
0
        public Dictionary <string, List <string> > GetDictionary(int?pageNum)
        {
            Dictionary <string, List <string> > wordList = new Dictionary <string, List <string> >();
            var query = new List <string>();

            if (pageNum == null)
            {
                query = _wordRepository.GetAllWords();
            }
            else
            {
                query = _wordRepository.GetSkipWords(pageNum);
            }
            var temp = "";

            foreach (var word in query)
            {
                var sortedWord = string.Concat(word.ToLower().OrderBy(c => c));
                if (sortedWord != temp)
                {
                    temp = sortedWord.ToLower();
                    if (!wordList.ContainsKey(temp))
                    {
                        wordList.Add(temp, new List <string>());
                        wordList[temp].Add(word);
                    }
                    else
                    {
                        wordList[temp].Add(word);
                    }
                }
                else
                {
                    wordList[temp].Add(word);
                }
            }
            return(wordList);
        }
Exemple #15
0
        /// <summary> Exports information from a project to a lift package zip </summary>
        /// <exception cref="MissingProjectException"> If Project does not exist. </exception>
        /// <returns> Path to compressed zip file containing export. </returns>
        public async Task <string> LiftExport(
            string projectId, IWordRepository wordRepo, IProjectRepository projRepo)
        {
            // Validate project exists.
            var proj = await projRepo.GetProject(projectId);

            if (proj is null)
            {
                throw new MissingProjectException($"Project does not exist: {projectId}");
            }
            var vernacularBcp47 = proj.VernacularWritingSystem.Bcp47;

            // Generate the zip dir.
            var exportDir     = FileStorage.GenerateLiftExportDirPath(projectId);
            var liftExportDir = Path.Combine(exportDir, "LiftExport");

            if (Directory.Exists(liftExportDir))
            {
                Directory.Delete(liftExportDir, true);
            }

            var projNameAsPath = Sanitization.MakeFriendlyForPath(proj.Name, "Lift");
            var zipDir         = Path.Combine(liftExportDir, projNameAsPath);

            Directory.CreateDirectory(zipDir);

            // Add audio dir inside zip dir.
            var audioDir = Path.Combine(zipDir, "audio");

            Directory.CreateDirectory(audioDir);
            var liftPath = Path.Combine(zipDir, projNameAsPath + ".lift");

            // noBOM will work with PrinceXML
            using var liftWriter = new CombineLiftWriter(liftPath, ByteOrderStyle.BOM);
            var rangesDest = Path.Combine(zipDir, projNameAsPath + ".lift-ranges");

            // Write header of lift document.
            var header =
                $@"
                    <ranges>
                        <range id = ""semantic-domain-ddp4"" href = ""{rangesDest}""/>
                    </ranges>
                    <fields>
                        <field tag = ""Plural"">
                            <form lang = ""en""><text></text></form>
                            <form lang = ""qaa-x-spec""><text> Class = LexEntry; Type = String; WsSelector = kwsVern </text></form>
                        </field>
                    </fields>
                ";

            liftWriter.WriteHeader(header);

            // Write out every word with all of its information
            var allWords = await wordRepo.GetAllWords(projectId);

            var frontier = await wordRepo.GetFrontier(projectId);

            var activeWords = frontier.Where(
                x => x.Senses.Any(s => s.Accessibility == State.Active)).ToList();

            // All words in the frontier with any senses are considered current.
            // The Combine does not import senseless entries and the interface is supposed to prevent creating them.
            // So the the words found in allWords with no matching guid in activeWords are exported as 'deleted'.
            var deletedWords = allWords.Where(
                x => activeWords.All(w => w.Guid != x.Guid)).DistinctBy(w => w.Guid).ToList();

            foreach (var wordEntry in activeWords)
            {
                var entry = new LexEntry(MakeSafeXmlAttribute(wordEntry.Vernacular), wordEntry.Guid);
                if (DateTime.TryParse(wordEntry.Created, out var createdTime))
                {
                    entry.CreationTime = createdTime;
                }

                if (DateTime.TryParse(wordEntry.Modified, out var modifiedTime))
                {
                    entry.ModificationTime = modifiedTime;
                }

                AddNote(entry, wordEntry);
                AddVern(entry, wordEntry, vernacularBcp47);
                AddSenses(entry, wordEntry);
                AddAudio(entry, wordEntry, audioDir, projectId);

                liftWriter.Add(entry);
            }

            foreach (var wordEntry in deletedWords)
            {
                var entry = new LexEntry(MakeSafeXmlAttribute(wordEntry.Vernacular), wordEntry.Guid);

                AddNote(entry, wordEntry);
                AddVern(entry, wordEntry, vernacularBcp47);
                AddSenses(entry, wordEntry);
                AddAudio(entry, wordEntry, audioDir, projectId);

                liftWriter.AddDeletedEntry(entry);
            }

            liftWriter.End();

            // Export semantic domains to lift-ranges
            var    extractedPathToImport = FileStorage.GenerateImportExtractedLocationDirPath(projectId, false);
            string?firstImportDir        = null;

            if (Directory.Exists(extractedPathToImport))
            {
                // TODO: Should an error be raised if this returns null?
                firstImportDir = Directory.GetDirectories(extractedPathToImport).Select(
                    Path.GetFileName).ToList().Single();
            }

            var importLiftDir = firstImportDir ?? "";
            var rangesSrc     = Path.Combine(extractedPathToImport, importLiftDir, $"{importLiftDir}.lift-ranges");

            // If there are no new semantic domains, and the old lift-ranges file is still around, just copy it
            if (proj.SemanticDomains.Count == 0 && File.Exists(rangesSrc))
            {
                File.Copy(rangesSrc, rangesDest, true);
            }
            else // Make a new lift-ranges file
            {
                using var liftRangesWriter = XmlWriter.Create(rangesDest, new XmlWriterSettings
                {
                    Indent = true,
                    NewLineOnAttributes = true,
                    Async = true
                });
                await liftRangesWriter.WriteStartDocumentAsync();

                liftRangesWriter.WriteStartElement("lift-ranges");
                liftRangesWriter.WriteStartElement("range");
                liftRangesWriter.WriteAttributeString("id", "semantic-domain-ddp4");

                // Pull from resources file with all English semantic domains
                var          assembly       = typeof(LiftService).GetTypeInfo().Assembly;
                const string semDomListFile = "BackendFramework.Data.sdList.txt";
                var          resource       = assembly.GetManifestResourceStream(semDomListFile);
                if (resource is null)
                {
                    throw new Exception($"Unable to load semantic domain list: {semDomListFile}");
                }

                string sdList;
                using (var reader = new StreamReader(resource, Encoding.UTF8))
                {
                    sdList = await reader.ReadToEndAsync();
                }

                var sdLines = sdList.Split(Environment.NewLine);
                foreach (var line in sdLines)
                {
                    if (line != "")
                    {
                        var items = line.Split("`");
                        WriteRangeElement(liftRangesWriter, items[0], items[1], items[2], items[3]);
                    }
                }

                // Pull from new semantic domains in project
                foreach (var sd in proj.SemanticDomains)
                {
                    WriteRangeElement(liftRangesWriter, sd.Id, Guid.NewGuid().ToString(), sd.Name, sd.Description);
                }

                await liftRangesWriter.WriteEndElementAsync(); //end semantic-domain-ddp4 range

                await liftRangesWriter.WriteEndElementAsync(); //end lift-ranges

                await liftRangesWriter.WriteEndDocumentAsync();

                await liftRangesWriter.FlushAsync();

                liftRangesWriter.Close();
            }

            // Export character set to ldml.
            var ldmlDir = Path.Combine(zipDir, "WritingSystems");

            Directory.CreateDirectory(ldmlDir);
            if (vernacularBcp47 != "")
            {
                var validChars = proj.ValidCharacters;
                LdmlExport(ldmlDir, vernacularBcp47, validChars);
            }

            // Compress everything.
            var destinationFileName = Path.Combine(exportDir,
                                                   Path.Combine($"LiftExportCompressed-{proj.Id}_{DateTime.Now:yyyy-MM-dd_hh-mm-ss}.zip"));
            var zipParentDir = Path.GetDirectoryName(zipDir);

            if (zipParentDir is null)
            {
                throw new Exception($"Unable to find parent dir of: {zipDir}");
            }
            ZipFile.CreateFromDirectory(zipParentDir, destinationFileName);

            // Clean up the temporary folder structure that was compressed.
            Directory.Delete(liftExportDir, true);

            return(destinationFileName);
        }
        /// <summary> Exports information from a project to a lift package zip </summary>
        public string LiftExport(string projectId)
        {
            // The helper tag must be included because there are also SIL.Utilities.
            var util = new Utilities();

            // Generate the zip dir.
            var exportDir = util.GenerateFilePath(Utilities.FileType.Dir, true, "",
                                                  Path.Combine(projectId, "Export"));

            if (Directory.Exists(Path.Combine(exportDir, "LiftExport")))
            {
                Directory.Delete(Path.Combine(exportDir, "LiftExport"), true);
            }
            var zipDir = Path.Combine(exportDir, "LiftExport", "Lift");

            Directory.CreateDirectory(zipDir);

            // Add audio dir inside zip dir.
            var audioDir = Path.Combine(zipDir, "audio");

            Directory.CreateDirectory(audioDir);
            var liftPath = Path.Combine(zipDir, "NewLiftFile.lift");

            // noBOM will work with PrinceXML
            var liftWriter = new CombineLiftWriter(liftPath, ByteOrderStyle.BOM);
            var rangesDest = Path.Combine(zipDir, "NewLiftFile.lift-ranges");

            // write header of lift document
            var header =
                $@"
                    <ranges>
                        <range id = ""semantic-domain-ddp4"" href = ""{rangesDest}""/>
                    </ranges>
                    <fields>
                        <field tag = ""Plural"">
                            <form lang = ""en""><text></text></form>
                            <form lang = ""qaa-x-spec""><text> Class = LexEntry; Type = String; WsSelector = kwsVern </text></form>
                        </field>
                    </fields>
                ";

            liftWriter.WriteHeader(header);

            // Write out every word with all of its information
            var allWords    = _repo.GetAllWords(projectId).Result;
            var frontier    = _repo.GetFrontier(projectId).Result;
            var activeWords = frontier.Where(x => x.Senses.First().Accessibility == (int)State.Active).ToList();

            // TODO: this is wrong, deleted is a subset of active, are not exclusive
            var deletedWords = allWords.Where(x => activeWords.Contains(x)).ToList();

            foreach (var wordEntry in activeWords)
            {
                var entry = new LexEntry();

                AddVern(entry, wordEntry, projectId);
                AddSenses(entry, wordEntry);
                AddAudio(entry, wordEntry, audioDir);

                liftWriter.Add(entry);
            }
            foreach (var wordEntry in deletedWords)
            {
                var entry = new LexEntry();

                AddVern(entry, wordEntry, projectId);
                AddSenses(entry, wordEntry);
                AddAudio(entry, wordEntry, audioDir);

                liftWriter.AddDeletedEntry(entry);
            }

            liftWriter.End();

            // Export semantic domains to lift-ranges
            var proj = _projService.GetProject(projectId).Result;
            var extractedPathToImport = Path.Combine(GetProjectDir(projectId), "Import", "ExtractedLocation");
            var importLiftDir         = "";

            if (Directory.Exists(extractedPathToImport))
            {
                importLiftDir = Directory.GetDirectories(extractedPathToImport).Select(Path.GetFileName).ToList().Single();
            }
            var rangesSrc = Path.Combine(extractedPathToImport, importLiftDir, $"{importLiftDir}.lift-ranges");

            // If there are no new semantic domains, and the old lift-ranges file is still around, just copy it
            if (proj.SemanticDomains.Count == 0 && File.Exists(rangesSrc))
            {
                File.Copy(rangesSrc, rangesDest, true);
            }
            else // Make a new lift-ranges file
            {
                var liftRangesWriter = XmlWriter.Create(rangesDest, new XmlWriterSettings
                {
                    Indent = true,
                    NewLineOnAttributes = true
                });
                liftRangesWriter.WriteStartDocument();
                liftRangesWriter.WriteStartElement("lift-ranges");
                liftRangesWriter.WriteStartElement("range");
                liftRangesWriter.WriteAttributeString("id", "semantic-domain-ddp4");

                // Pull from resources file with all English semantic domains
                var    assembly = typeof(LiftService).GetTypeInfo().Assembly;
                var    resource = assembly.GetManifestResourceStream("BackendFramework.Data.sdList.txt");
                string sdList;
                using (var reader = new StreamReader(resource, Encoding.UTF8))
                {
                    sdList = reader.ReadToEndAsync().Result;
                }
                var sdLines = sdList.Split(Environment.NewLine);
                foreach (var line in sdLines)
                {
                    if (line != "")
                    {
                        var items = line.Split("`");
                        WriteRangeElement(liftRangesWriter, items[0], items[1], items[2], items[3]);
                    }
                }

                // Pull from new semantic domains in project
                foreach (var sd in proj.SemanticDomains)
                {
                    WriteRangeElement(liftRangesWriter, sd.Id, Guid.NewGuid().ToString(), sd.Name, sd.Description);
                }

                liftRangesWriter.WriteEndElement(); //end semantic-domain-ddp4 range
                liftRangesWriter.WriteEndElement(); //end lift-ranges
                liftRangesWriter.WriteEndDocument();

                liftRangesWriter.Flush();
                liftRangesWriter.Close();
            }


            // Export character set to ldml
            var ldmlDir = Path.Combine(zipDir, "WritingSystems");

            Directory.CreateDirectory(ldmlDir);
            if (proj.VernacularWritingSystem != "")
            {
                LdmlExport(ldmlDir, proj.VernacularWritingSystem);
            }

            // Compress everything
            var destinationFileName = Path.Combine(exportDir,
                                                   Path.Combine($"LiftExportCompressed-{proj.Id}_{string.Format("{0:yyyy-MM-dd_hh-mm-ss}", DateTime.Now)}.zip"));

            ZipFile.CreateFromDirectory(Path.GetDirectoryName(zipDir), destinationFileName);

            return(destinationFileName);
        }
Exemple #17
0
 public IList <string> GetAllWords()
 {
     return(wordRepository.GetAllWords());
 }
        public async Task <IList <string> > GetAnagrams(string inputWords)
        {
            var joinedInput = ValidateInputData(inputWords);

            if (string.IsNullOrEmpty(joinedInput))
            {
                throw new Exception("You must enter at least one word");
            }

            //getting all dictionary
            var allWords = await _wordRepository.GetAllWords();

            if (allWords == null || allWords.Count < 1)
            {
                throw new Exception("No anagrams found for your input");
            }
            //sorting user phrase
            var sortedInput = String.Concat(joinedInput.OrderBy(x => x));

            var sortedList = new List <WordEntity>();

            sortedList = SortWordsContainingInInput(allWords, sortedInput);

            var tmpInput = sortedInput;

            //look for single word anagrams first
            var singleWord = await GetAllSingleWordAnagrams(sortedInput);

            if (singleWord == null)
            {
                singleWord = new List <WordEntity>();
            }

            var resultAnagrams = singleWord.Select(x => x.Word).ToList();
            var idsList        = singleWord.Select(x => x.ID.ToString()).ToList();


            //look for multi word anagrams
            foreach (var elem in sortedList)
            {
                //assign element to current variable
                var current = elem;
                //trimming elem letters from input
                tmpInput = TrimLetters(tmpInput, current.SortedWord);
                foreach (var elem2 in sortedList)
                {
                    //both are then same - continue
                    if (current.SortedWord == elem2.SortedWord)
                    {
                        continue;
                    }

                    var foundWordsLength = elem.SortedWord.Length + tmpInput.Length;
                    //if leftover makes word and all words do not exceed input length
                    var contais = ContainsKey(sortedList, tmpInput);
                    if (contais != null && foundWordsLength == sortedInput.Length)
                    {
                        // adding found words to reult list
                        resultAnagrams.Add($"{elem.Word} {contais.Word}");
                        //adding found words to ids collection
                        idsList.Add($"{elem.ID}/{contais.ID}");
                        break;
                    }
                }
                //recover primary input
                tmpInput = sortedInput;
                if (resultAnagrams.Count == Settings.AnagramsToGenerate)
                {
                    break;
                }
            }

            //adding search to cached table
            await _cachedWordService.AddCachedWord(inputWords, idsList.Take(Settings.AnagramsToGenerate).ToList());

            return(resultAnagrams.Take(Settings.AnagramsToGenerate).ToList());
        }
Exemple #19
0
        //public Words(IWordRepository repository)
        //{
        //    _repository = repository;
        //}

        public List <Word> GetAll()
        {
            return(_repository.GetAllWords());
        }
        public IActionResult Index()
        {
            var vocabulary = repo.GetAllWords();

            return(View(vocabulary));
        }
        public void TestRoundtrip()
        {
            // This test assumes you have the starting .zip included in your project files.

            // Get path to the starting dir
            var pathToStartZips = Path.Combine(Directory.GetParent(Directory.GetParent(
                                                                       Directory.GetParent(Environment.CurrentDirectory).ToString()).ToString()).ToString(), "Assets");
            var testZips = Directory.GetFiles(pathToStartZips, "*.zip");

            var fileMapping = new Dictionary <string, RoundTripObj>();

            // Add new .zip file information here
            var gusillaay = new RoundTripObj("gsl-Qaaa-x-orth", new List <string>(), 8045 /*number of words*/);

            fileMapping.Add("Gusillaay.zip", gusillaay);
            var lotad = new RoundTripObj("dtr", new List <string>(), 5400);

            fileMapping.Add("Lotad.zip", lotad);
            var natqgu = new RoundTripObj("qaa-x-stc-natqgu", new List <string>(), 11570 /*number of words*/);

            fileMapping.Add("Natqgu.zip", natqgu);
            var resembli = new RoundTripObj("ags", new List <string>(), 255 /*number of words*/);

            fileMapping.Add("Resembli.zip", resembli);
            var rwc = new RoundTripObj("es", new List <string>(), 132 /*number of words*/);

            fileMapping.Add("RWC.zip", rwc);
            var sena = new RoundTripObj("seh", new List <string>(), 1462 /*number of words*/);

            fileMapping.Add("Sena.zip", sena);
            var singleEntryLiftWithSound = new RoundTripObj(
                "ptn", new List <string> {
                "short.mp3"
            }, 1 /*number of words*/);

            fileMapping.Add("SingleEntryLiftWithSound.zip", singleEntryLiftWithSound);
            var singleEntryLiftWithTwoSound = new RoundTripObj(
                "ptn",
                new List <string> {
                "short.mp3", "short1.mp3"
            }, 1 /*number of words*/);

            fileMapping.Add("SingleEntryLiftWithTwoSound.zip", singleEntryLiftWithTwoSound);

            foreach (var dataSet in fileMapping)
            {
                var actualFilename = dataSet.Key;
                var pathToStartZip = Path.Combine(pathToStartZips, actualFilename);

                // Upload the zip file

                // Init the project the .zip info is added to
                var proj = RandomProject();
                _projServ.Create(proj);

                // Generate api parameter with filestream
                if (File.Exists(pathToStartZip))
                {
                    var fstream    = File.OpenRead(pathToStartZip);
                    var fileUpload = InitFile(fstream, actualFilename);

                    // Make api call
                    var result = _liftController.UploadLiftFile(proj.Id, fileUpload).Result;
                    Assert.That(!(result is BadRequestObjectResult));

                    proj = _projServ.GetProject(proj.Id).Result;
                    Assert.AreEqual(proj.VernacularWritingSystem, dataSet.Value.Language);

                    fstream.Close();

                    var allWords = _wordrepo.GetAllWords(proj.Id);
                    // Export
                    var exportedFilePath  = _liftController.CreateLiftExport(proj.Id);
                    var exportedDirectory = Path.GetDirectoryName(exportedFilePath);

                    // Assert the file was created with desired heirarchy
                    Assert.That(Directory.Exists(exportedDirectory));
                    Assert.That(Directory.Exists(Path.Combine(exportedDirectory, "LiftExport", "Lift", "audio")));
                    foreach (var audioFile in dataSet.Value.AudioFiles)
                    {
                        Assert.That(File.Exists(Path.Combine(
                                                    exportedDirectory, "LiftExport", "Lift", "audio", audioFile)));
                    }
                    Assert.That(Directory.Exists(Path.Combine(exportedDirectory, "LiftExport", "Lift", "WritingSystems")));
                    Assert.That(File.Exists(Path.Combine(
                                                exportedDirectory,
                                                "LiftExport", "Lift", "WritingSystems", dataSet.Value.Language + ".ldml")));
                    Assert.That(File.Exists(Path.Combine(exportedDirectory, "LiftExport", "Lift", "NewLiftFile.lift")));
                    var dirList = new List <string>(
                        Directory.GetDirectories(Path.GetDirectoryName(exportedDirectory)));
                    dirList.Remove(exportedDirectory);
                    Assert.That(Directory.Exists(Path.Combine(Path.GetDirectoryName(exportedDirectory), dirList.Single())));

                    _wordrepo.DeleteAllWords(proj.Id);

                    // Roundtrip Part 2

                    // Upload the exported words again
                    // Init the project the .zip info is added to
                    var proj2 = RandomProject();
                    _projServ.Create(proj2);

                    // Generate api parameter with filestream
                    fstream    = File.OpenRead(exportedFilePath);
                    fileUpload = InitFile(fstream, actualFilename);

                    // Make api call
                    var result2 = _liftController.UploadLiftFile(proj2.Id, fileUpload).Result;
                    Assert.That(!(result is BadRequestObjectResult));

                    proj2 = _projServ.GetProject(proj2.Id).Result;
                    Assert.AreEqual(proj2.VernacularWritingSystem, dataSet.Value.Language);

                    fstream.Close();

                    allWords = _wordrepo.GetAllWords(proj2.Id);
                    Assert.AreEqual(allWords.Result.Count, dataSet.Value.NumOfWords);

                    // Export
                    exportedFilePath  = _liftController.CreateLiftExport(proj2.Id);
                    exportedDirectory = Path.GetDirectoryName(exportedFilePath);

                    // Assert the file was created with desired hierarchy
                    Assert.That(Directory.Exists(exportedDirectory));
                    Assert.That(Directory.Exists(Path.Combine(exportedDirectory, "LiftExport", "Lift", "audio")));
                    foreach (var audioFile in dataSet.Value.AudioFiles)
                    {
                        var path = Path.Combine(exportedDirectory, "LiftExport", "Lift", "audio", audioFile);
                        Assert.That(File.Exists(path),
                                    "The file " + audioFile + " can not be found at this path: " + path);
                    }
                    Assert.That(Directory.Exists(Path.Combine(exportedDirectory, "LiftExport", "Lift", "WritingSystems")));
                    Assert.That(File.Exists(Path.Combine(
                                                exportedDirectory,
                                                "LiftExport", "Lift", "WritingSystems", dataSet.Value.Language + ".ldml")));
                    Assert.That(File.Exists(Path.Combine(exportedDirectory, "LiftExport", "Lift", "NewLiftFile.lift")));
                    dirList = new List <string>(Directory.GetDirectories(Path.GetDirectoryName(exportedDirectory)));
                    dirList.Remove(exportedDirectory);
                    Assert.That(Directory.Exists(Path.Combine(Path.GetDirectoryName(exportedDirectory), dirList.Single())));

                    _wordrepo.DeleteAllWords(proj.Id);
                }
            }
        }