<commit_before>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Lists;
using osuTK;
using osuTK.Graphics;

namespace osu.Framework.Tests.Visual.Drawables
{
    public class TestSceneDelayedLoadUnloadWrapper : FrameworkTestScene
    {
        private const int panel_count = 1024;

        private FillFlowContainer<Container> flow;
        private ScrollContainer<Drawable> scroll;

        [SetUp]
        public void SetUp() => Schedule(() =>
        {
            Children = new Drawable[]
            {
                scroll = new BasicScrollContainer
                {
                    RelativeSizeAxes = Axes.Both,
                    Children = new Drawable[]
                    {
                        flow = new FillFlowContainer<Container>
                        {
                            RelativeSizeAxes = Axes.X,
                            AutoSizeAxes = Axes.Y,
                        }
                    }
                }
            };
        });

        [Test]
        public void TestRemovedStillUnload()
        {
            WeakList<Container> references = new WeakList<Container>();

            AddStep("populate panels", () =>
            {
                for (int i = 0; i < 16; i++)
                    flow.Add(new Container
                    {
                        Size = new Vector2(128),
                        Children = new Drawable[]
                        {
                            new DelayedLoadUnloadWrapper(() =>
                            {
                                var container = new Container
                                {
                                    RelativeSizeAxes = Axes.Both,
                                    Children = new Drawable[]
                                    {
                                        new TestBox { RelativeSizeAxes = Axes.Both }
                                    },
                                };

                                references.Add(container);

                                return container;
                            }, 500, 2000),
                            new SpriteText { Text = i.ToString() },
                        }
                    });
            });

            AddUntilStep("references counted", () => references.Count() == 16);
            AddStep("Remove all panels", () => flow.Clear());
            AddUntilStep("references lost", () =>
            {
                GC.Collect();
                return !references.Any();
            });
        }

        [Test]
        public void TestManyChildrenUnload()
        {
            AddStep("populate panels", () =>
            {
                for (int i = 1; i < panel_count; i++)
                    flow.Add(new Container
                    {
                        Size = new Vector2(128),
                        Children = new Drawable[]
                        {
                            new DelayedLoadUnloadWrapper(() => new Container
                            {
                                RelativeSizeAxes = Axes.Both,
                                Children = new Drawable[]
                                {
                                    new TestBox { RelativeSizeAxes = Axes.Both }
                                }
                            }, 500, 2000),
                            new SpriteText { Text = i.ToString() },
                        }
                    });
            });

            Func<int> childrenWithAvatarsLoaded = () =>
                flow.Children.Count(c => c.Children.OfType<DelayedLoadWrapper>().First().Content?.IsLoaded ?? false);

            int loadedCountInitial = 0;
            int loadedCountSecondary = 0;

            AddUntilStep("wait some loaded", () => (loadedCountInitial = childrenWithAvatarsLoaded()) > 5);

            AddStep("scroll down", () => scroll.ScrollToEnd());

            AddUntilStep("wait more loaded", () => (loadedCountSecondary = childrenWithAvatarsLoaded()) > loadedCountInitial);

            AddAssert("not too many loaded", () => childrenWithAvatarsLoaded() < panel_count / 4);

            AddUntilStep("wait some unloaded", () => childrenWithAvatarsLoaded() < loadedCountSecondary);
        }

        public class TestBox : Container
        {
            public TestBox()
            {
                RelativeSizeAxes = Axes.Both;
            }

            [BackgroundDependencyLoader]<commit_msg>Add tests for scheduler events<commit_after>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Lists;
using osu.Framework.Threading;
using osuTK;
using osuTK.Graphics;

namespace osu.Framework.Tests.Visual.Drawables
{
    public class TestSceneDelayedLoadUnloadWrapper : FrameworkTestScene
    {
        private const int panel_count = 1024;

        private FillFlowContainer<Container> flow;
        private TestScrollContainer scroll;

        [SetUp]
        public void SetUp() => Schedule(() =>
        {
            Children = new Drawable[]
            {
                scroll = new TestScrollContainer
                {
                    RelativeSizeAxes = Axes.Both,
                    Children = new Drawable[]
                    {
                        flow = new FillFlowContainer<Container>
                        {
                            RelativeSizeAxes = Axes.X,
                            AutoSizeAxes = Axes.Y,
                        }
                    }
                }
            };
        });

        [Test]
        public void TestRemovedStillUnload()
        {
            WeakList<Container> references = new WeakList<Container>();

            AddStep("populate panels", () =>
            {
                references.Clear();

                for (int i = 0; i < 16; i++)
                    flow.Add(new Container
                    {
                        Size = new Vector2(128),
                        Children = new Drawable[]
                        {
                            new DelayedLoadUnloadWrapper(() =>
                            {
                                var container = new Container
                                {
                                    RelativeSizeAxes = Axes.Both,
                                    Children = new Drawable[]
                                    {
                                        new TestBox { RelativeSizeAxes = Axes.Both }
                                    },
                                };

                                references.Add(container);

                                return container;
                            }, 500, 2000),
                            new SpriteText { Text = i.ToString() },
                        }
                    });
            });

            AddUntilStep("references counted", () => references.Count() == 16);

            AddAssert("check schedulers present", () => scroll.Scheduler.HasPendingTasks);

            AddStep("Remove all panels", () => flow.Clear());

            AddUntilStep("repeating schedulers removed", () => !scroll.Scheduler.HasPendingTasks);

            AddUntilStep("references lost", () =>
            {
                GC.Collect();
                return !references.Any();
            });
        }

        [Test]
        public void TestManyChildrenUnload()
        {
            AddStep("populate panels", () =>
            {
                for (int i = 1; i < panel_count; i++)
                    flow.Add(new Container
                    {
                        Size = new Vector2(128),
                        Children = new Drawable[]
                        {
                            new DelayedLoadUnloadWrapper(() => new Container
                            {
                                RelativeSizeAxes = Axes.Both,
                                Children = new Drawable[]
                                {
                                    new TestBox { RelativeSizeAxes = Axes.Both }
                                }
                            }, 500, 2000),
                            new SpriteText { Text = i.ToString() },
                        }
                    });
            });

            Func<int> childrenWithAvatarsLoaded = () =>
                flow.Children.Count(c => c.Children.OfType<DelayedLoadWrapper>().First().Content?.IsLoaded ?? false);

            int loadedCountInitial = 0;
            int loadedCountSecondary = 0;

            AddUntilStep("wait some loaded", () => (loadedCountInitial = childrenWithAvatarsLoaded()) > 5);

            AddStep("scroll down", () => scroll.ScrollToEnd());

            AddUntilStep("wait more loaded", () => (loadedCountSecondary = childrenWithAvatarsLoaded()) > loadedCountInitial);

            AddAssert("not too many loaded", () => childrenWithAvatarsLoaded() < panel_count / 4);

            AddUntilStep("wait some unloaded", () => childrenWithAvatarsLoaded() < loadedCountSecondary);
        }

        public class TestScrollContainer : BasicScrollContainer
        {
            public new Scheduler Scheduler => base.Scheduler;
        }

        public class TestBox : Container
        {
            public TestBox()
            {
                RelativeSizeAxes = Axes.Both;
            }

            [BackgroundDependencyLoader]
{'fraction_non_alphanumeric': 0.08902107067244681, 'fraction_numerical': 0.007258796249621937, 'mean_word_length': 1.1119863742814562, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5014089', 'n_tokens_mistral': 2397, 'n_tokens_neox': 2141, 'n_words': 489}