Пример #1
0
        /// <summary>
        /// Получить информацию для поиска.
        /// </summary>
        /// <param name="entityType">Тип сущности.</param>
        /// <param name="link">Ссылка.</param>
        /// <returns>Результат.</returns>
        protected virtual (string boardId, int sequenceId)? ExtractLinkKey(PostStoreEntityType entityType, ILink link)
        {
            if (link is IEngineLink el)
            {
                if (string.Equals(el.Engine, EngineId, StringComparison.OrdinalIgnoreCase))
                {
                    switch (entityType)
                    {
                    case PostStoreEntityType.Post:
                    case PostStoreEntityType.ThreadPreviewPost:
                    case PostStoreEntityType.CatalogPost:
                        switch (link)
                        {
                        case PostLink l:
                            return(l.Board, l.PostNum);

                        case ThreadLink l:
                            return(l.Board, l.OpPostNum);
                        }
                        break;

                    case PostStoreEntityType.Thread:
                    case PostStoreEntityType.ThreadPreview:
                        switch (link)
                        {
                        case ThreadLink l:
                            return(l.Board, l.OpPostNum);
                        }
                        break;

                    case PostStoreEntityType.Catalog:
                        switch (link)
                        {
                        case CatalogLink l:
                            return(l.Board, (int)l.SortMode);
                        }
                        break;

                    case PostStoreEntityType.BoardPage:
                        switch (link)
                        {
                        case BoardPageLink l:
                            return(l.Board, l.Page);

                        case BoardLink l:
                            return(l.Board, 0);
                        }
                        break;
                    }
                }
            }
            return(null);
        }
Пример #2
0
 protected void AssertLinkOnlyLoadedPost(PostStoreEntityId collectionId, PostStoreEntityType entityType,
                                         IBoardPost post, string messagePrefix, IBoardPostEntity opLinkOnly, PostStoreEntityId opId)
 {
     Assert.IsNotNull(opLinkOnly, $"{messagePrefix}: opLinkOnly != null");
     Assert.AreEqual(post.Link.GetLinkHash(), opLinkOnly.Link.GetLinkHash(), $"{messagePrefix}: opLinkOnly.Link");
     Assert.AreEqual(post.ParentLink.GetLinkHash(), opLinkOnly.ParentLink.GetLinkHash(),
                     $"{messagePrefix}: opLinkOnly.ParentLink");
     Assert.AreEqual(entityType, opLinkOnly.EntityType, $"{messagePrefix}: opLinkOnly.EntityType");
     Assert.IsNotNull(opLinkOnly.StoreId, $"{messagePrefix}: opLinkOnly.StoreId");
     Assert.AreEqual(opId, opLinkOnly.StoreId.Value, $"{messagePrefix}: opLinkOnly.StoreId");
     Assert.IsNotNull(opLinkOnly.StoreParentId, $"{messagePrefix}: opLinkOnly.StoreParentId");
     Assert.AreEqual(collectionId, opLinkOnly.StoreParentId.Value, $"{messagePrefix}: opLinkOnly.StoreParentId");
 }
Пример #3
0
 protected void AssertBareEntityLoadedPost(PostStoreEntityId collectionId, PostStoreEntityType entityType,
                                           IBoardPost post, string messagePrefix, IBoardPostEntity opEntity, PostStoreEntityId opId)
 {
     AssertLinkOnlyLoadedPost(collectionId, entityType, post, messagePrefix, opEntity, opId);
     Assert.AreEqual(post.Subject, opEntity.Subject, $"{messagePrefix}: opEntity.Subject");
     if (post.Thumbnail != null)
     {
         Assert.IsNotNull(opEntity.Thumbnail, $"{messagePrefix}: opEntity.Thumbnail != null");
         Assert.AreEqual(post.Thumbnail.MediaLink?.GetLinkHash(), opEntity.Thumbnail.MediaLink?.GetLinkHash(), $"{messagePrefix}: opEntity.Thumbnail.MediaLink");
         Assert.AreEqual(post.Thumbnail.Size, opEntity.Thumbnail.Size, $"{messagePrefix}: opEntity.Thumbnail.Size");
         Assert.AreEqual(post.Thumbnail.FileSize, opEntity.Thumbnail.FileSize, $"{messagePrefix}: opEntity.Thumbnail.FileSize");
         Assert.AreEqual(post.Thumbnail.MediaType, opEntity.Thumbnail.MediaType, $"{messagePrefix}: opEntity.Thumbnail.MediaType");
     }
     else
     {
         Assert.IsNull(opEntity.Thumbnail, "opEntity.Thumbnail == null");
     }
 }
Пример #4
0
        protected async Task AssertLoadedPost(PostStoreEntityId collectionId, PostStoreEntityType entityType, IBoardPost post, int postCounterNum, string messagePrefix)
        {
            var opLink = post.Link;
            var opIdn  = await _store.FindEntity(entityType, opLink);

            Assert.IsNotNull(opIdn, $"{messagePrefix}: opId != null");
            var opId       = opIdn.Value;
            var loadedPost = await LoadPost(opId);

            loadedPost.Id            = opId;
            loadedPost.Counter       = postCounterNum;
            loadedPost.MessagePrefix = messagePrefix;
            loadedPost.EntityType    = entityType;
            loadedPost.Post          = post;
            var lpa = new LoadedPost[] { loadedPost };

            AssertLoadedPosts(collectionId, lpa);
        }
Пример #5
0
        private async ValueTask <List <PostStoreEntityId> > FilterByFlags(PostStoreEntityType type, PostStoreEntityId?parentId, IList <Guid> havingFlags, IList <Guid> notHavingFlags, IEsentSession session)
        {
            var bookmarks = await DoQueryByFlags(session, type, parentId, havingFlags);

            if (bookmarks == null || bookmarks.Length == 0)
            {
                return(new List <PostStoreEntityId>());
            }

            return(await session.Run(() =>
            {
                var result = new List <PostStoreEntityId>();

                var nhs = notHavingFlags != null ? new HashSet <Guid>(notHavingFlags) : new HashSet <Guid>();

                using (var table = OpenPostsTable(session, OpenTableGrbit.ReadOnly))
                {
                    foreach (var bm in bookmarks)
                    {
                        if (table.Indexes.PrimaryIndex.Find(table.Indexes.PrimaryIndex.CreateKey(bm.Id)))
                        {
                            if (nhs.Count > 0)
                            {
                                if (table.Columns.Flags.Values.All(v => v?.Value == null || !nhs.Contains(v?.Value ?? Guid.Empty)))
                                {
                                    result.Add(new PostStoreEntityId()
                                    {
                                        Id = table.Columns.Id
                                    });
                                }
                            }
                            else
                            {
                                result.Add(new PostStoreEntityId()
                                {
                                    Id = table.Columns.Id
                                });
                            }
                        }
                    }
                }
                return result;
            }));
        }
Пример #6
0
        /// <summary>
        /// Сформировать ссылку.
        /// </summary>
        /// <param name="entityType">Тип сущности.</param>
        /// <param name="boardId">Идентификатор доски.</param>
        /// <param name="sequenceId">Номер в последовательности.</param>
        /// <param name="parentSequenceId">Родительский номер в последовательности.</param>
        /// <returns></returns>
        protected virtual ILink ConstructLink(PostStoreEntityType entityType, string boardId, int sequenceId, int?parentSequenceId)
        {
            switch (entityType)
            {
            case PostStoreEntityType.Post:
            case PostStoreEntityType.CatalogPost:
            case PostStoreEntityType.ThreadPreviewPost:
                return(new PostLink()
                {
                    Engine = EngineId,
                    Board = boardId,
                    OpPostNum = parentSequenceId ?? 0,
                    PostNum = sequenceId
                });

            case PostStoreEntityType.Thread:
            case PostStoreEntityType.ThreadPreview:
                return(new ThreadLink()
                {
                    Engine = EngineId,
                    Board = boardId,
                    OpPostNum = sequenceId
                });

            case PostStoreEntityType.BoardPage:
                return(new BoardPageLink()
                {
                    Engine = EngineId,
                    Board = boardId,
                    Page = sequenceId
                });

            case PostStoreEntityType.Catalog:
                return(new CatalogLink()
                {
                    Engine = EngineId,
                    Board = boardId,
                    SortMode = (BoardCatalogSort)sequenceId
                });

            default:
                return(null);
            }
        }
Пример #7
0
 protected void AssertLightLoadedPost(PostStoreEntityId collectionId, PostStoreEntityType entityType,
                                      IBoardPost post, string messagePrefix, IBoardPostEntity opEntity, PostStoreEntityId opId, bool counterRetrieved, int postCounterNum)
 {
     AssertBareEntityLoadedPost(collectionId, entityType, post, messagePrefix, opEntity, opId);
     if (opEntity is IBoardPostLight opLight)
     {
         Assert.AreEqual(post.BoardSpecificDate, opLight.BoardSpecificDate, $"{messagePrefix}: opLight.BoardSpecificDate");
         var dateDiff = Math.Abs((post.Date - opLight.Date).TotalSeconds);
         Assert.IsTrue(dateDiff < 1.5, $"{messagePrefix}: opLight.Date");
         if (post.Likes != null)
         {
             Assert.IsNotNull(opLight.Likes, $"{messagePrefix}: opLight.Likes != null");
             Assert.AreEqual(post.Likes.Likes, opLight.Likes.Likes, $"{messagePrefix}: opLight.Likes.Likes");
             Assert.AreEqual(post.Likes.Dislikes, opLight.Likes.Dislikes, $"{messagePrefix}: opLight.Likes.Dislikes");
         }
         else
         {
             Assert.IsNull(opLight.Likes, $"{messagePrefix}: opLight.Likes == null");
         }
         if (post.Tags != null)
         {
             Assert.IsNotNull(opLight.Tags, $"{messagePrefix}: opLight.Tags != null");
             CollectionAssert.AreEquivalent(post.Tags.Tags.Distinct().ToList(), opLight.Tags.Tags.Distinct().ToList(), $"{messagePrefix}: opLight.Tags");
         }
         else
         {
             Assert.IsNull(opLight.Tags, $"{messagePrefix}: opLight.Tags == null");
         }
         Assert.IsNotNull(opLight.Flags, $"{messagePrefix}: opLight.Flags != null");
         CollectionAssert.AreEquivalent(post.Flags.Distinct().ToList(), opLight.Flags.Distinct().ToList(), $"{messagePrefix}: opLight.Flags");
         if (counterRetrieved)
         {
             Assert.AreEqual(postCounterNum, opLight.Counter, $"{messagePrefix}: opLight.Counter");
         }
     }
     else
     {
         Assert.Fail($"{messagePrefix}: не типа IBoardPostLight");
     }
 }
Пример #8
0
        protected async Task AssertQuotes(PostStoreEntityType entityType, ILink opLink, ILink[] expectedQuotes, string msgPrefix)
        {
            var opId = await _store.FindEntity(PostStoreEntityType.Post, opLink);

            Assert.IsNotNull(opId, $"{msgPrefix}: opId != null");
            Assert.AreEqual(PostStoreEntityType.Post, await _store.GetCollectionType(opId.Value), $"{msgPrefix}: post type = {entityType}");
            var quoteIds = await _store.GetPostQuotes(opId.Value);

            Assert.IsNotNull(quoteIds, $"{msgPrefix}: quoteIds != null");
            Assert.AreEqual(expectedQuotes.Length, quoteIds.Count, $"{msgPrefix}: quoteIds.Count");

            var quotes = await _store.GetEntityLinks(quoteIds.ToArray());

            Assert.IsNotNull(quotes, $"{msgPrefix}: quotes != null");
            Assert.AreEqual(expectedQuotes.Length, quotes.Count, $"{msgPrefix}: quotes.Count");
            var quotesToCheck = quotes.Select(q => q.Link).OrderBy(q => q, BoardLinkComparer.Instance).ToArray();

            for (var i = 0; i < expectedQuotes.Length; i++)
            {
                Assert.AreEqual(expectedQuotes[i].GetLinkHash(), quotesToCheck[i].GetLinkHash(), $"{msgPrefix}: quote {i}");
            }
        }
Пример #9
0
        protected GenericPostStoreEntityType ToGenericEntityType(PostStoreEntityType entityType)
        {
            switch (entityType)
            {
            case PostStoreEntityType.BoardPage:
                return(GenericPostStoreEntityType.BoardPage);

            case PostStoreEntityType.Thread:
            case PostStoreEntityType.ThreadPreview:
                return(GenericPostStoreEntityType.Thread);

            case PostStoreEntityType.Catalog:
                return(GenericPostStoreEntityType.Catalog);

            case PostStoreEntityType.Post:
            case PostStoreEntityType.ThreadPreviewPost:
            case PostStoreEntityType.CatalogPost:
                return(GenericPostStoreEntityType.Post);

            default:
                return(GenericPostStoreEntityType.Unknown);
            }
        }
Пример #10
0
        private bool SeekExistingEntityOnBoard(PostsTable table, PostStoreEntityType entityType, string boardId, int sequenceId, out PostStoreEntityId id)
        {
            var index = table.Indexes.TypeAndPostIdIndex;

            index.SetAsCurrentIndex();
            var r = index.Find(index.CreateKey((byte)entityType, boardId, sequenceId));

            if (!r)
            {
                id = new PostStoreEntityId()
                {
                    Id = -1
                };
            }
            else
            {
                id = new PostStoreEntityId()
                {
                    Id = index.Views.RetrieveIdFromIndexView.Fetch().Id
                };
            }
            return(r);
        }
Пример #11
0
        private IBoardPostEntity LoadThreadCollection(IEsentSession session, ref LoadPostDataContext loadContext, PostStoreLoadMode loadMode, PostStoreEntityType entityType)
        {
            switch (loadMode.EntityLoadMode)
            {
            case PostStoreEntityLoadMode.LinkOnly:
                return(LoadLinkOnly(loadContext.table));

            case PostStoreEntityLoadMode.EntityOnly:
                return(LoadBareEntity(loadContext.table, entityType));

            case PostStoreEntityLoadMode.Light:
            case PostStoreEntityLoadMode.Full:
                return(LoadThreadCollection(loadContext.table));

            default:
                return(null);
            }
        }
Пример #12
0
        private IBoardPostEntity LoadPost(IEsentSession session, ref LoadPostDataContext loadContext, PostStoreLoadMode loadMode, PostStoreEntityType entityType)
        {
            switch (loadMode.EntityLoadMode)
            {
            case PostStoreEntityLoadMode.LinkOnly:
                return(LoadLinkOnly(loadContext.table));

            case PostStoreEntityLoadMode.EntityOnly:
                return(LoadBareEntity(loadContext.table, entityType));

            case PostStoreEntityLoadMode.Light:
                return(LoadPostLight(session, loadContext.table, loadMode.RetrieveCounterNumber, entityType));

            case PostStoreEntityLoadMode.Full:
                return(LoadPost(session, ref loadContext, loadMode.RetrieveCounterNumber, entityType));

            default:
                return(null);
            }
        }
Пример #13
0
        private async ValueTask <PostStoreEntityId[]> DoQueryByFlags(IEsentSession session, PostStoreEntityType type, PostStoreEntityId?parentId, IList <Guid> havingFlags)
        {
            return(await session.Run(() =>
            {
                var found = new List <HashSet <int> >();

                if (havingFlags != null && havingFlags.Count > 0)
                {
                    using (var table = OpenPostsTable(session, OpenTableGrbit.ReadOnly))
                    {
                        foreach (var flag in havingFlags)
                        {
                            if (parentId != null)
                            {
                                var index = table.Indexes.DirectParentFlagsIndex;
                                index.SetAsCurrentIndex();
                                found.Add(index.EnumerateAsRetrieveIdFromIndexView(index.CreateKey(parentId.Value.Id, flag)).Select(id => id.Id).ToHashSet());
                            }
                            else
                            {
                                var index = table.Indexes.TypeFlagsIndex;
                                index.SetAsCurrentIndex();
                                found.Add(index.EnumerateAsRetrieveIdFromIndexView(index.CreateKey((byte)type, flag)).Select(id => id.Id).ToHashSet());
                            }
                        }
                    }
                }


                if (found.Count == 0)
                {
                    goto CancelLabel;
                }

                var r = found[0];
                foreach (var f in found.Skip(1))
                {
                    r.IntersectWith(f);
                }

                return r.Select(id => new PostStoreEntityId()
                {
                    Id = id
                }).ToArray();

CancelLabel:
                return new PostStoreEntityId[0];
            }));
        }
Пример #14
0
        protected void AssertFullLoadedPost(PostStoreEntityId collectionId, PostStoreEntityType entityType,
                                            IBoardPost post, string messagePrefix, IBoardPostEntity opEntity, PostStoreEntityId opId,
                                            bool counterRetrieved, int postCounterNum)
        {
            AssertLightLoadedPost(collectionId, entityType, post, messagePrefix, opEntity, opId, counterRetrieved, postCounterNum);
            if (opEntity is IBoardPost opPost)
            {
                Assert.AreEqual(post.UniqueId, opPost.UniqueId, $"{messagePrefix}: opPost.UniqueId");
                PostModelsTests.AssertDocuments(_provider, post.Comment, opPost.Comment);
                if (post.Country != null)
                {
                    Assert.IsNotNull(opPost.Country, $"{messagePrefix}: opPost.Country != null");
                    Assert.AreEqual(post.Country.ImageLink?.GetLinkHash(), opPost.Country.ImageLink?.GetLinkHash(), $"{messagePrefix}: opPost.Country");
                }
                else
                {
                    Assert.IsNull(opPost.Country, $"{messagePrefix}: opPost.Country == null");
                }
                if (post.Icon != null)
                {
                    Assert.IsNotNull(opPost.Icon, $"{messagePrefix}: opPost.Icon != null");
                    Assert.AreEqual(post.Icon.ImageLink?.GetLinkHash(), opPost.Icon.ImageLink?.GetLinkHash(), $"{messagePrefix}: opPost.Icon.ImageLink");
                    Assert.AreEqual(post.Icon.Description, opPost.Icon.Description, $"{messagePrefix}: opPost.Icon.Description");
                }
                else
                {
                    Assert.IsNull(opPost.Icon, $"{messagePrefix}: opPost.Icon == null");
                }
                Assert.AreEqual(post.Email, opPost.Email, $"{messagePrefix}: opPost.Email");
                Assert.AreEqual(post.Hash, opPost.Hash, $"{messagePrefix}: opPost.Email");
                if (post.Poster != null)
                {
                    Assert.IsNotNull(opPost.Poster, $"{messagePrefix}: opPost.Poster != null");
                    Assert.AreEqual(post.Poster.Name, opPost.Poster.Name, $"{messagePrefix}: opPost.Poster.Name");
                    Assert.AreEqual(post.Poster.Tripcode, opPost.Poster.Tripcode, $"{messagePrefix}: opPost.Poster.Tripcode");
                    Assert.AreEqual(post.Poster.NameColor, opPost.Poster.NameColor, $"{messagePrefix}: opPost.Poster.NameColor");
                    Assert.AreEqual(post.Poster.NameColorStr, opPost.Poster.NameColorStr, $"{messagePrefix}: opPost.Poster.NameColorStr");
                }
                else
                {
                    Assert.IsNull(opPost.Poster, $"{messagePrefix}: opPost.Poster == null");
                }
                Assert.IsNotNull(opPost.Quotes, $"{messagePrefix}: opPost.Quotes != null");
                CollectionAssert.AreEquivalent(post.Quotes.Distinct(BoardLinkEqualityComparer.Instance).Select(l => l.GetLinkHash()).ToList(), opPost.Quotes.Distinct(BoardLinkEqualityComparer.Instance).Select(l => l.GetLinkHash()).ToList(), $"{messagePrefix}: opPost.Quotes");
                Assert.IsNotNull(opPost.MediaFiles, $"{messagePrefix}: opPost.MediaFiles != null");

                Assert.AreEqual(post.MediaFiles.Count, opPost.MediaFiles.Count, $"{messagePrefix}: opPost.MediaFiles.Count");
                for (var i = 0; i < post.MediaFiles.Count; i++)
                {
                    var pMedia  = post.MediaFiles[i];
                    var opMedia = opPost.MediaFiles[i];
                    Assert.AreEqual(pMedia is IPostMediaWithSize, opMedia is IPostMediaWithSize, $"{messagePrefix}: opPost.MediaFiles[{i}] is IPostMediaWithSize");
                    Assert.AreEqual(pMedia is IPostMediaWithThumbnail, opMedia is IPostMediaWithThumbnail, $"{messagePrefix}: opPost.MediaFiles[{i}] is IPostMediaWithThumbnail");
                    Assert.AreEqual(pMedia is IPostMediaWithInfo, opMedia is IPostMediaWithInfo, $"{messagePrefix}: opPost.MediaFiles[{i}] is IPostMediaWithInfo");
                    Assert.AreEqual(pMedia.MediaLink?.GetLinkHash(), opMedia.MediaLink?.GetLinkHash(), $"{messagePrefix}: opPost.MediaFiles[{i}].MediaLink");
                    Assert.AreEqual(pMedia.FileSize, opMedia.FileSize, $"{messagePrefix}: opPost.MediaFiles[{i}].FileSize");
                    Assert.AreEqual(pMedia.MediaType, opMedia.MediaType, $"{messagePrefix}: opPost.MediaFiles[{i}].MediaType");
                    if (pMedia is IPostMediaWithSize pMedia2 && opMedia is IPostMediaWithSize opMedia2)
                    {
                        Assert.AreEqual(pMedia2.Size, opMedia2.Size, $"{messagePrefix}: opPost.MediaFiles[{i}].Size");
                    }
                    if (pMedia is IPostMediaWithThumbnail pMedia3 && opMedia is IPostMediaWithThumbnail opMedia3)
                    {
                        Assert.AreEqual(pMedia3.Thumbnail?.MediaLink.GetLinkHash(), opMedia3.Thumbnail?.MediaLink.GetLinkHash(), $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.MediaLink");
                        Assert.AreEqual(pMedia3.Thumbnail?.FileSize, opMedia3.Thumbnail?.FileSize, $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.FileSize");
                        Assert.AreEqual(pMedia3.Thumbnail?.MediaType, opMedia3.Thumbnail?.MediaType, $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.MediaType");
                        Assert.AreEqual(pMedia3.Thumbnail?.Size, opMedia3.Thumbnail?.Size, $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.Size");
                    }
                    if (pMedia is IPostMediaWithInfo pMedia4 && opMedia is IPostMediaWithInfo opMedia4)
                    {
                        Assert.AreEqual(pMedia4.Nsfw, opMedia4.Nsfw, $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.Nsfw");
                        Assert.AreEqual(pMedia4.DisplayName, opMedia4.DisplayName, $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.DisplayName");
                        Assert.AreEqual(pMedia4.Duration, opMedia4.Duration, $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.Duration");
                        Assert.AreEqual(pMedia4.FullName, opMedia4.FullName, $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.FullName");
                        Assert.AreEqual(pMedia4.Hash, opMedia4.Hash, $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.Hash");
                        Assert.AreEqual(pMedia4.Name, opMedia4.Name, $"{messagePrefix}: opPost.MediaFiles[{i}].Thumbnail.Name");
                    }
                }

                var dateDiff = Math.Abs((post.LoadedTime - opPost.LoadedTime).TotalSeconds);
                Assert.IsTrue(dateDiff < 1.5, $"{messagePrefix}: opPost.LoadedTime");
            }
            else
            {
                Assert.Fail($"{messagePrefix}: не типа IBoardPost");
            }
        }