<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.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Database;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;

namespace osu.Game.Tests.Visual.OnlinePlay
{
    /// <summary>
    /// A base test scene for all online play components and screens.
    /// </summary>
    public abstract class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestSceneDependencies
    {
        public Bindable<Room> SelectedRoom => OnlinePlayDependencies?.SelectedRoom;
        public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager;
        public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies?.OngoingOperationTracker;
        public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies?.AvailabilityTracker;
        public TestUserLookupCache UserLookupCache => OnlinePlayDependencies?.UserLookupCache;
        public BeatmapLookupCache BeatmapLookupCache => OnlinePlayDependencies?.BeatmapLookupCache;

        /// <summary>
        /// All dependencies required for online play components and screens.
        /// </summary>
        protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies?.OnlinePlayDependencies;

        protected override Container<Drawable> Content => content;

        private readonly Container content;
        private readonly Container drawableDependenciesContainer;
        private DelegatedDependencyContainer dependencies;

        protected OnlinePlayTestScene()
        {
            base.Content.AddRange(new Drawable[]
            {
                drawableDependenciesContainer = new Container { RelativeSizeAxes = Axes.Both },
                content = new Container { RelativeSizeAxes = Axes.Both },
            });
        }

        protected sealed override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
        {
            dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent));
            return dependencies;
        }

        [SetUp]
        public void Setup() => Schedule(() =>
        {
            // Reset the room dependencies to a fresh state.
            drawableDependenciesContainer.Clear();
            dependencies.OnlinePlayDependencies = CreateOnlinePlayDependencies();
            drawableDependenciesContainer.AddRange(OnlinePlayDependencies.DrawableComponents);

            var handler = OnlinePlayDependencies.RequestsHandler;

            // Resolving the BeatmapManager in the test scene will inject the game-wide BeatmapManager, while many test scenes cache their own BeatmapManager instead.
            // To get around this, the BeatmapManager is looked up from the dependencies provided to the children of the test scene instead.
            var beatmapManager = dependencies.Get<BeatmapManager>();

            ((DummyAPIAccess)API).HandleRequest = request =>
            {
                TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();

                // Because some of the handlers use realm, we need to ensure the game is still alive when firing.
                // If we don't, a stray `PerformAsync` could hit an `ObjectDisposedException` if running too late.
                Scheduler.Add(() =>
                {
                    bool result = handler.HandleRequest(request, API.LocalUser.Value, beatmapManager);
                    tcs.SetResult(result);
                }, false);

#pragma warning disable RS0030
                // We can't GetResultSafely() here (will fail with "Can't use GetResultSafely from inside an async operation."), but Wait is safe enough due to
                // the task being a TaskCompletionSource.
                return tcs.Task.Result;
#pragma warning restore RS0030
            };
        });

        /// <summary>
        /// Creates the room dependencies. Called every <see cref="Setup"/>.
        /// </summary>
        /// <remarks>
        /// Any custom dependencies required for online play sub-classes should be added here.
        /// </remarks>
        protected virtual OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new OnlinePlayTestSceneDependencies();

        /// <summary>
        /// A <see cref="IReadOnlyDependencyContainer"/> providing a mutable lookup source for online play dependencies.
        /// </summary>
        private class DelegatedDependencyContainer : IReadOnlyDependencyContainer
        {
            /// <summary>
            /// The online play dependencies.
            /// </summary>
            public OnlinePlayTestSceneDependencies OnlinePlayDependencies { get; set; }

            private readonly IReadOnlyDependencyContainer parent;
            private readonly DependencyContainer injectableDependencies;

            /// <summary>
            /// Creates a new <see cref="DelegatedDependencyContainer"/>.
            /// </summary>
            /// <param name="parent">The fallback <see cref="IReadOnlyDependencyContainer"/> to use when <see cref="OnlinePlayDependencies"/> cannot satisfy a dependency.</param><commit_msg>Add comment regarding deadlock avoidance<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.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Database;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;

namespace osu.Game.Tests.Visual.OnlinePlay
{
    /// <summary>
    /// A base test scene for all online play components and screens.
    /// </summary>
    public abstract class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestSceneDependencies
    {
        public Bindable<Room> SelectedRoom => OnlinePlayDependencies?.SelectedRoom;
        public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager;
        public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies?.OngoingOperationTracker;
        public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies?.AvailabilityTracker;
        public TestUserLookupCache UserLookupCache => OnlinePlayDependencies?.UserLookupCache;
        public BeatmapLookupCache BeatmapLookupCache => OnlinePlayDependencies?.BeatmapLookupCache;

        /// <summary>
        /// All dependencies required for online play components and screens.
        /// </summary>
        protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies?.OnlinePlayDependencies;

        protected override Container<Drawable> Content => content;

        private readonly Container content;
        private readonly Container drawableDependenciesContainer;
        private DelegatedDependencyContainer dependencies;

        protected OnlinePlayTestScene()
        {
            base.Content.AddRange(new Drawable[]
            {
                drawableDependenciesContainer = new Container { RelativeSizeAxes = Axes.Both },
                content = new Container { RelativeSizeAxes = Axes.Both },
            });
        }

        protected sealed override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
        {
            dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent));
            return dependencies;
        }

        [SetUp]
        public void Setup() => Schedule(() =>
        {
            // Reset the room dependencies to a fresh state.
            drawableDependenciesContainer.Clear();
            dependencies.OnlinePlayDependencies = CreateOnlinePlayDependencies();
            drawableDependenciesContainer.AddRange(OnlinePlayDependencies.DrawableComponents);

            var handler = OnlinePlayDependencies.RequestsHandler;

            // Resolving the BeatmapManager in the test scene will inject the game-wide BeatmapManager, while many test scenes cache their own BeatmapManager instead.
            // To get around this, the BeatmapManager is looked up from the dependencies provided to the children of the test scene instead.
            var beatmapManager = dependencies.Get<BeatmapManager>();

            ((DummyAPIAccess)API).HandleRequest = request =>
            {
                TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();

                // Because some of the handlers use realm, we need to ensure the game is still alive when firing.
                // If we don't, a stray `PerformAsync` could hit an `ObjectDisposedException` if running too late.
                Scheduler.Add(() =>
                {
                    bool result = handler.HandleRequest(request, API.LocalUser.Value, beatmapManager);
                    tcs.SetResult(result);
                }, false);

#pragma warning disable RS0030
                // We can't GetResultSafely() here (will fail with "Can't use GetResultSafely from inside an async operation."), but Wait is safe enough due to
                // the task being a TaskCompletionSource.
                // Importantly, this doesn't deadlock because of the scheduler call above running inline where feasible (see the `false` argument).
                return tcs.Task.Result;
#pragma warning restore RS0030
            };
        });

        /// <summary>
        /// Creates the room dependencies. Called every <see cref="Setup"/>.
        /// </summary>
        /// <remarks>
        /// Any custom dependencies required for online play sub-classes should be added here.
        /// </remarks>
        protected virtual OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new OnlinePlayTestSceneDependencies();

        /// <summary>
        /// A <see cref="IReadOnlyDependencyContainer"/> providing a mutable lookup source for online play dependencies.
        /// </summary>
        private class DelegatedDependencyContainer : IReadOnlyDependencyContainer
        {
            /// <summary>
            /// The online play dependencies.
            /// </summary>
            public OnlinePlayTestSceneDependencies OnlinePlayDependencies { get; set; }

            private readonly IReadOnlyDependencyContainer parent;
            private readonly DependencyContainer injectableDependencies;

            /// <summary>
            /// Creates a new <see cref="DelegatedDependencyContainer"/>.
            /// </summary>
            /// <param name="parent">The fallback <see cref="IReadOnlyDependencyContainer"/> to use when <see cref="OnlinePlayDependencies"/> cannot satisfy a dependency.</param>
{'fraction_non_alphanumeric': 0.07871824791311373, 'fraction_numerical': 0.0014361367920294407, 'mean_word_length': 2.693072588664236, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4329095', 'n_tokens_mistral': 2611, 'n_tokens_neox': 2435, 'n_words': 793}