text:
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using Xunit;

namespace System.Threading.Tasks.Dataflow.Tests
{
    public partial class DataflowBlockTests : DataflowBlockTestBase
    {
        [Fact]
        public void RunJoinBlockTests()
        {
            Assert.True(IDataflowBlockTestHelper.TestToString(nameFormat => nameFormat != null ? new JoinBlock<int, int>(new GroupingDataflowBlockOptions() { NameFormat = nameFormat }) : new JoinBlock<int, int>()));
            Assert.True(IDataflowBlockTestHelper.TestToString(nameFormat => nameFormat != null ? new JoinBlock<int, int, int>(new GroupingDataflowBlockOptions() { NameFormat = nameFormat }) : new JoinBlock<int, int, int>()));
            Assert.True(ISourceBlockTestHelper.TestLinkTo<Tuple<int, int>>(ConstructJoinNewWithNMessages(2), 1));
            Assert.True(ISourceBlockTestHelper.TestReserveMessageAndReleaseReservation<Tuple<int, int>>(ConstructJoinNewWithNMessages(1)));
            //Assert.True(ISourceBlockTestHelper.TestReleaseReservation<Tuple<int, int>>(ConstructJoinNewWithNMessages(1)));
            Assert.True(ISourceBlockTestHelper.TestConsumeMessage<Tuple<int, int>>(ConstructJoinNewWithNMessages(1)));
            Assert.True(ISourceBlockTestHelper.TestTryReceiveWithFilter<Tuple<int, int>>(ConstructJoinNewWithNMessages(1), 1));
            Assert.True(ISourceBlockTestHelper.TestTryReceiveAll<Tuple<int, int>>(ConstructJoinNewWithNMessages(1), 1));

            Assert.True(TestJoinMaxNumberOfGroups(greedy: true, sync: true));
            Assert.True(TestJoinMaxNumberOfGroups(greedy: true, sync: false));
            // {non-greedy sync} is intentioanlly skipped because it is not supported by the block
            Assert.True(TestJoinMaxNumberOfGroups(greedy: false, sync: false));
        }

        private static JoinBlock<int, int> ConstructJoinNewWithNMessages(int messagesCount)
        {
            var block = new JoinBlock<int, int>();
            for (int i = 0; i < messagesCount; i++)
            {
                block.Target1.Post(i);
                block.Target2.Post(i);
            }

            // Spin until the messages have been properly buffered up.
            // Otherwise TryReceive fails.
            SpinWait.SpinUntil(() => block.OutputCount == messagesCount);

            return block;
        }

        [Fact]
        public void TestJoinBlockConstructor()
        {
            // without decline without option
            var block = new JoinBlock<int, int>();
            Assert.False(block.OutputCount != 0, "Constructor failed! OutputCount returned a non zero value for a brand new JoinBlock.");
            // decline without option
            block = new JoinBlock<int, int>(new GroupingDataflowBlockOptions { MaxNumberOfGroups = 1 });
            Assert.False(block.OutputCount != 0, "Constructor failed! OutputCount returned a non zero value for a brand new JoinBlock.");
            // decline with not cancelled token and default scheduler
            block = new JoinBlock<int, int>(new GroupingDataflowBlockOptions { MaxMessagesPerTask = 1 });
            Assert.False(block.OutputCount != 0, "Constructor failed! OutputCount returned a non zero value for a brand new JoinBlock.");
            // decline with a cancelled token and default scheduler
            var token = new CancellationToken(true);
            block = new JoinBlock<int, int>(new GroupingDataflowBlockOptions { MaxMessagesPerTask = 1, CancellationToken = token, MaxNumberOfGroups = 1 });
            Assert.False(block.OutputCount != 0, "Constructor failed! OutputCount returned a non zero value for a brand new JoinBlock.");
        }

        [Fact]
        public void TestJoinInvalidArgumentValidation()
        {
            Assert.Throws<ArgumentNullException>(() => new JoinBlock<int, int>(null));
            Assert.Throws<ArgumentNullException>(() => new JoinBlock<int, int, int>(null));
            Assert.Throws<NotSupportedException>(() => { var ignored = new JoinBlock<int, int>().Target1.Completion; });
            Assert.Throws<NotSupportedException>(() => { var ignored = new JoinBlock<int, int, int>().Target3.Completion; });

            Assert.True(ISourceBlockTestHelper.TestArgumentsExceptions<Tuple<int, int>>(new JoinBlock<int, int>()));
            Assert.True(ISourceBlockTestHelper.TestArgumentsExceptions<Tuple<int, int, int>>(new JoinBlock<int, int, int>()));
        }

        //[Fact(Skip = "Outerloop")]
        public void RunJoinBlockConformanceTests()
        {
            // Test Post/Receive single block
            {
                int iter = 2;

                var block2 = new JoinBlock<int, int>();
                for (int i = 0; i < iter; i++)
                {
                    block2.Target1.Post(i);
                    block2.Target2.Post(i);
                    var msg = block2.Receive();

                    Assert.False(msg.Item1 != i || msg.Item2 != i, string.Format("JoinBlock Post/Receive failed expected {0},{1} and actual {2},{3}", i, i, msg.Item1, msg.Item2));
                }

                var block3 = new JoinBlock<int, int, int>();
                for (int i = 0; i < iter; i++)
                {
                    block3.Target1.Post(i);
                    block3.Target2.Post(i);
                    block3.Target3.Post(i);
                    var msg = block3.Receive();
                    Assert.False(msg.Item1 != i || msg.Item2 != i || msg.Item3 != i, string.Format("JoinBlock Post/Receive failed expected {0},{1},{2} and actual {3},{4},{5}", i, i, i, msg.Item1, msg.Item2, msg.Item3));
                }
            }

            // Test PostAll then Receive single block
            {
                int iter = 2;

                var block2 = new JoinBlock<int, int>();
                for (int i = 0; i < iter; i++)
                {
                    block2.Target1.Post(i);
                    block2.Target2.Post(i);
                }
                for (int i = 0; i < iter; i++)
                {
                    var msg = block2.Receive();
                    Assert.False(msg.Item1 != msg.Item2, "JoinBlock PostAll then Receive failed expected, incorrect msg pair");
                }

                var block3 = new JoinBlock<int, int, int>();
                for (int i = 0; i < iter; i++)
                {
                    block3.Target1.Post(i);
                    block3.Target2.Post(i);
                    block3.Target3.Post(i);
                }
                for (int i = 0; i < iter; i++)
                {
                    var msg = block3.Receive();
                    Assert.False(msg.Item1 != msg.Item2 || msg.Item2 != msg.Item3, "JoinBlock PostAll then Receive failed expected, incorrect msg pair");
                }
            }

            //Test one target Post with TryReceive
            {
                var block2 = new JoinBlock<int, int>();
                block2.Target1.Post(0);
                Tuple<int, int> result2;
                Assert.False(block2.TryReceive(out result2), "JoinBlock.TryReceive failed, returned true and only one target posted a message");
                Assert.False(block2.OutputCount > 0, "JoinBlock.OutputCount failed, returned count > 0 and only one target posted a message");
                var block3 = new JoinBlock<int, int, int>();
                block3.Target1.Post(0);
                Tuple<int, int, int> result3;
                Assert.False(block3.TryReceive(out result3), "JoinBlock.TryReceive failed, returned true and only one target posted a message");
                Assert.False(block3.OutputCount > 0, "JoinBlock.OutputCount failed, returned count > 0 and only one target posted a message");
            }

            // Test JoinBlock`2 using a precanceled token
            {
                var localPassed = true;
                try
                {
                    var cts = new CancellationTokenSource();
                    cts.Cancel();
                    var dbo = new GroupingDataflowBlockOptions { CancellationToken = cts.Token, MaxNumberOfGroups = 1 };
                    var jb = new JoinBlock<int, int>(dbo);

                    Tuple<int, int> ignoredValue;
                    IList<Tuple<int, int>> ignoredValues;
                    localPassed &= jb.LinkTo(new ActionBlock<Tuple<int, int>>(delegate { })) != null;
                    localPassed &= jb.Target1.Post(42) == false;
                    localPassed &= jb.Target2.Post(42) == false;
                    localPassed &= jb.Target1.SendAsync(42).Result == false;
                    localPassed &= jb.Target2.SendAsync(42).Result == false;
                    localPassed &= jb.TryReceiveAll(out ignoredValues) == false;
                    localPassed &= jb.TryReceive(out ignoredValue) == false;
                    localPassed &= jb.OutputCount == 0;
                    localPassed &= jb.Completion != null;
                    jb.Target1.Complete();
                    jb.Target2.Complete();
                }
                catch (Exception)
                {
                    localPassed = false;
                }

                Assert.True(localPassed, string.Format("Precanceled tokens on JB`2 - {0}", localPassed ? "Passed" : "FAILED"));
            }

            // Test JoinBlock`3 using a precanceled token
            {
                var localPassed = true;
                try
                {
                    var cts = new CancellationTokenSource();
                    cts.Cancel();
                    var dbo = new GroupingDataflowBlockOptions { CancellationToken = cts.Token, MaxNumberOfGroups = 1 };
                    var jb = new JoinBlock<int, int, int>(dbo);

                    Tuple<int, int, int> ignoredValue;
                    IList<Tuple<int, int, int>> ignoredValues;
                    localPassed &= jb.LinkTo(new ActionBlock<Tuple<int, int, int>>(delegate { })) != null;
                    localPassed &= jb.Target1.Post(42) == false;
                    localPassed &= jb.Target2.Post(42) == false;
                    localPassed &= jb.Target3.Post(42) == false;
                    localPassed &= jb.Target1.SendAsync(42).Result == false;
                    localPassed &= jb.Target2.SendAsync(42).Result == false;
                    localPassed &= jb.Target3.SendAsync(42).Result == false;
                    localPassed &= jb.TryReceiveAll(out ignoredValues) == false;
                    localPassed &= jb.TryReceive(out ignoredValue) == false;
                    localPassed &= jb.OutputCount == 0;
                    localPassed &= jb.Completion != null;
                    jb.Target1.Complete();
                    jb.Target2.Complete();
                    jb.Target3.Complete();
                }
                catch (Exception)
                {
                    localPassed = false;
                }

                Assert.True(localPassed, string.Format("Precanceled tokens on JB`3 - {0}", localPassed ? "Passed" : "FAILED"));
            }

            // Test JoinBlock`2 completion through all targets
            {
                var localPassed = true;
                var join = new JoinBlock<int, int>();
                join.Target1.Post(1);
                join.Target1.Complete();
                join.Target2.Complete();
                localPassed = join.Completion.Wait(2000);

                Assert.True(localPassed, string.Format("JoinBlock`2 completed through targets - {0}", localPassed ? "Passed" : "FAILED"));
            }

            // Test JoinBlock`3 completion through all targets
            {
                var localPassed = true;
                var join = new JoinBlock<int, int, int>();
                join.Target1.Post(1);
                join.Target1.Complete();
                join.Target2.Complete();
                join.Target3.Complete();
                localPassed = join.Completion.Wait(2000);

                Assert.True(localPassed, string.Format("JoinBlock`3 completed through targets - {0}", localPassed ? "Passed" : "FAILED"));
            }

            // Test JoinBlock`2 completion through block
            {
                var localPassed = true;
                var join = new JoinBlock<int, int>();
                join.Target1.Post(1);
                join.Complete();
                localPassed = join.Completion.Wait(2000);

                Assert.True(localPassed, string.Format("JoinBlock`2 completed through block - {0}", localPassed ? "Passed" : "FAILED"));
            }

            // Test JoinBlock`3 completion through block
            {
                var localPassed = true;
                var join = new JoinBlock<int, int, int>();
                join.Target1.Post(1);
                join.Complete();
                localPassed = join.Completion.Wait(2000);

                Assert.True(localPassed, string.Format("JoinBlock`3 completed through block - {0}", localPassed ? "Passed" : "FAILED"));
            }
        }

        [Fact]
        public void TestNonGreedyFailToConsumeReservedMessage()
        {
            NullOnConsumeSource<int> source1 = new NullOnConsumeSource<int>();
            NullOnConsumeSource<int> source2 = new NullOnConsumeSource<int>();
            var options = new GroupingDataflowBlockOptions { Greedy = false };
            JoinBlock<int, int> join = new JoinBlock<int, int>(options);

            source1.LinkTo(join.Target1);
            source2.LinkTo(join.Target2);

            try
            {
                join.Completion.Wait();
                Assert.True(false, "Failed to throw an exception");
            }
            catch (AggregateException ae)
            {
                ae.Handle(e => true);
            }

            if (source2.ConsumeMessageCalled)
            {
                Assert.True(false, "Failed to skip consuming the second message");
            }
        }

        //[Fact(Skip = "outerloop")]
        public void TestJoinNonGreedyCombo()
        {
            JoinBlock<int, int> join = new JoinBlock<int, int>(new GroupingDataflowBlockOptions { Greedy = false });

            // Offer 1 message - this should be postponed
            // To avoid implementing a source, we use SendAsync and we verify the task is not completed
            var send1 = join.Target1.SendAsync(1);
            bool localPassed = !send1.Wait(500);
            Assert.True(localPassed, string.Format("SendAsync not completed - {0}", localPassed ? "Passed" : "FAILED"));

            // Output count must be 0
            localPassed = join.OutputCount == 0;
            Assert.True(localPassed, string.Format("OutputCount == 0 - {0} ({1})", localPassed ? "Passed" : "FAILED", join.OutputCount));

            // Post 1 message - the result is non-deterministic but at least no exception should be thrown
            join.Target2.Post(2);
            Assert.True(localPassed, string.Format("Post did not throw - Passed"));

            // Offer 1 message - this should be postponed
            var send2 = join.Target2.SendAsync(2);

            // The SendAsync tasks must be completed
            localPassed = send1.Wait(500);
            Assert.True(localPassed, string.Format("SendAsync1 completed - {0}", localPassed ? "Passed" : "FAILED"));
            localPassed = send2.Wait(500);
            Assert.True(localPassed, string.Format("SendAsync2 completed - {0}", localPassed ? "Passed" : "FAILED"));

            // The SendAsync tasks must have a result of true
            if (localPassed)
            {
                localPassed = send1.Result;
                Assert.True(localPassed, string.Format("SendAsync1 true - {0}", localPassed ? "Passed" : "FAILED"));

                localPassed = send2.Result;
                Assert.True(localPassed, string.Format("SendAsync2 true - {0}", localPassed ? "Passed" : "FAILED"));
            }
            Task.Delay(500).Wait();

            // Output count must be 1
            localPassed = join.OutputCount == 1;
            Assert.True(localPassed, string.Format("OutputCount == 1 - {0} ({1})", localPassed ? "Passed" : "FAILED", join.OutputCount));

            // TryReceive should return 1 result
            Tuple<int, int> result;
            localPassed = join.TryReceive(out result);
            Assert.True(localPassed, string.Format("TryReceive - {0}", localPassed ? "Passed" : "FAILED"));
        }

        //[Fact(Skip = "outerloop")]
        public void TestJoinCancelationWaits()
        {
            bool passed = true;
            bool localPassed;

            var cts = new CancellationTokenSource();
            var nonGreedyOptionsWithCancellation = new GroupingDataflowBlockOptions { CancellationToken = cts.Token, Greedy = false };

            var badSource = new BlockOnConsumeSource<int>(1, true);
            var goodSource = new BlockOnConsumeSource<int>(2, false);

            var join = new JoinBlock<int, int>(nonGreedyOptionsWithCancellation);

            // Linking a target behind the Join and feeding messages into the targets
            // is important to trigger the functionality implemented by SourceCore.
            var terminator = new ActionBlock<Tuple<int, int>>(x => { Console.WriteLine("terminator: ({0},{1})", x.Item1, x.Item2); });
            join.LinkTo(terminator);
            var send1 = join.Target1.SendAsync(98);
            var send2 = join.Target2.SendAsync(99);

            // Wait for the sent messages to be consumed
            send1.Wait();
            send2.Wait();

            // Each linking will offer a message
            badSource.LinkTo(join.Target1);
            goodSource.LinkTo(join.Target2);

            // Both messages must be reserved
            badSource.ReservedEvent.WaitOne();
            goodSource.ReservedEvent.WaitOne();

            // The message from badSource must be consumed
            badSource.ConsumedEvent.WaitOne();

            // Cancel the Join
            cts.Cancel();

            // The Join must not complete, because the targets are still working
            try
            {
                localPassed = !join.Completion.Wait(1000);
            }
            catch (AggregateException ae)
            {
                ae.Handle(e => e is TaskCanceledException);
                localPassed = false;
            }
            passed &= localPassed;
            Assert.True(localPassed, string.Format("Join is not complete ({0}) - {1}", join.Completion.Status, localPassed ? "Passed" : "FAILED"));

            // Unblock the blocked operation
            badSource.BlockingEvent.Set();

            // The Join must become Canceled now
            try
            {
                join.Completion.Wait(1000);
                localPassed = false;
            }
            catch (AggregateException ae)
            {
                ae.Handle(e => e is TaskCanceledException);
                localPassed = join.Completion.Status == TaskStatus.Canceled;
            }
            passed &= localPassed;
            Assert.True(localPassed, string.Format("Join is canceled ({0}) - {1}", join.Completion.Status, localPassed ? "Passed" : "FAILED"));
        }

        //[Fact(Skip = "Outerloop")]
        public void TestJoinWithFaultedTarget()
        {
            bool passed = true;

            var nonGreedyOptions = new GroupingDataflowBlockOptions { Greedy = false };
            var goodSource = new ThrowerBlock();
            var badSource = new ThrowerBlock();
            var join = new JoinBlock<ThrowOn, ThrowOn>(nonGreedyOptions);
            var terminator = new ActionBlock<Tuple<ThrowOn, ThrowOn>>(xy => { Console.WriteLine("Terminator: We shouldn't be here - FAILED"); passed = false; });

            // Pre-load the sources
            goodSource.Post(ThrowOn.TryReceive); // Will not throw in this test
            badSource.Post(ThrowOn.ConsumeMessage);

            // Link
            join.LinkTo(terminator);
            goodSource.LinkTo(join.Target1);
            badSource.LinkTo(join.Target2);
            Task.Delay(500).Wait();

            // The Join must be faulted now
            passed &= TaskHasFaulted(join.Completion, "ConsumeMessage");

            Assert.True(passed, string.Format("{0}", passed ? "Passed" : "FAILED"));
        }

        private static bool TestJoinMaxNumberOfGroups(bool greedy, bool sync)
        {
            Contract.Assert(greedy || !sync, "Non-greedy sync doesn't make sense.");

            Console.WriteLine("* TestJoinMaxNumberOfGroups (greedy={0}, sync={1})", greedy, sync);
            bool passed = true;

            for (int maxNumberOfGroups = 1; maxNumberOfGroups <= 3; maxNumberOfGroups += 2)
            {
                var options = new GroupingDataflowBlockOptions { Greedy = greedy, MaxNumberOfGroups = maxNumberOfGroups };
                var join = new JoinBlock<int, int>(options);

                for (int joinNum = 0; joinNum < maxNumberOfGroups; joinNum++)
                {
                    // Feed each target to make sure one join is produced
                    if (sync)
                    {
                        passed &= join.Target1.Post(1);
                        Assert.True(passed, string.Format("FAILED join.Target1.Post(1) should be accepted in group num {0}", joinNum));
                        if (joinNum == maxNumberOfGroups - 1)
                        {
                            passed &= !join.Target1.Post(2);
                            Assert.True(passed, string.Format("FAILED join.Target1.Post(2) should be declined in group num {0}", joinNum));
                        }

                        passed &= join.Target2.Post(3);
                        Assert.True(passed, string.Format("FAILED join.Target2.Post(3) should be accepted in group num {0}", joinNum));
                    }
                    else
                    {
                        var feed1 = join.Target1.SendAsync(1);
                        if (greedy && joinNum == maxNumberOfGroups - 1)
                        {
                            var feed2 = join.Target1.SendAsync(2);
                            passed &= feed2.Status == TaskStatus.RanToCompletion && feed2.Result == false;
                            Assert.True(passed,
                                string.Format("FAILED join.Target1.SendAsync(2) should be declined in group num {0}", joinNum));
                        }
                        var feed3 = join.Target2.SendAsync(3);

                        passed &= feed1.Result;
                        Assert.True(passed, string.Format("FAILED join.Target1.SendAsync(1) should be accepted in group num {0}", joinNum));
                        passed &= feed3.Result;
                        Assert.True(passed, string.Format("FAILED join.Target2.SendAsync(3) should be accepted in group num {0}", joinNum));
                    }
                }

                // Wait until the first join is produced
                passed &= SpinWait.SpinUntil(() => join.OutputCount == maxNumberOfGroups, 4000);
                Assert.True(passed, string.Format("FAILED Not all joins completed in a timely fashion - completed {0} out of {1}", join.OutputCount, maxNumberOfGroups));

                // This attempt to feed should fail on each target
                if (sync)
                {
                    passed &= !join.Target1.Post(4);
                    Assert.True(passed, string.Format("FAILED Target1 incorrectly accepted a post after all {0} groups completed", maxNumberOfGroups));
                    passed &= !join.Target2.Post(5);
                    Assert.True(passed, string.Format("FAILED Target2 incorrectly accepted a post after all {0} groups completed", maxNumberOfGroups));
                }
                else
                {
                    passed &= !join.Target1.SendAsync(4).Result;
                    Assert.True(passed, string.Format("FAILED Target1 incorrectly accepted a SendAsync after all {0} groups completed", maxNumberOfGroups));
                    passed &= !join.Target2.SendAsync(5).Result;
                    Assert.True(passed, string.Format("FAILED Target2 incorrectly accepted a SendAsync after all {0} groups completed", maxNumberOfGroups));
                }
            }

            return passed;
        }
    }

    /// <summary>
    /// A source block that always returns messageConsumed==false on ConsumeMessage even for reserved messages.
    /// It is testing JoinBlock only.
    /// </summary>
    internal class NullOnConsumeSource<TOutput> : ISourceBlock<TOutput>
    {
        internal bool ConsumeMessageCalled = false;

        TOutput ISourceBlock<TOutput>.ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock<TOutput> target, out Boolean messageConsumed)
        {
            ConsumeMessageCalled = true;
            messageConsumed = false; // This is the purpose of the block
            return default(TOutput);
        }

        IDisposable ISourceBlock<TOutput>.LinkTo(ITargetBlock<TOutput> target, DataflowLinkOptions linkOptions)
        {
            target.OfferMessage(new DataflowMessageHeader(1), default(TOutput), this, true /* call back ConsumeMassage */);
            return new NoopOnUnlinked();
        }

        void ISourceBlock<TOutput>.ReleaseReservation(DataflowMessageHeader messageHeader, ITargetBlock<TOutput> target)
        {
        }

        bool ISourceBlock<TOutput>.ReserveMessage(DataflowMessageHeader messageHeader, ITargetBlock<TOutput> target)
        {
            return true;
        }

        Task IDataflowBlock.Completion
        {
            get { throw new NotImplementedException(); }
        }

        public void Complete()
        {
            throw new NotImplementedException();
        }

        void IDataflowBlock.Fault(Exception exception)
        {
            throw new NotImplementedException();
        }
    }

    internal class NoopOnUnlinked : IDisposable
    {
        void IDisposable.Dispose()
        {
        }
    }

    /// <summary>
    /// Dummy Source that will offer one message and will block on consume (if required).
    /// This block should be used by the Non greedy joins.
    /// </summary>
    public class BlockOnConsumeSource<TOutput> : ISourceBlock<TOutput>
    {
        public ManualResetEvent ReservedEvent = new ManualResetEvent(false);
        public ManualResetEvent ConsumedEvent = new ManualResetEvent(false);
        public ManualResetEvent ReleasedEvent = new ManualResetEvent(false);
        public ManualResetEvent BlockingEvent = new ManualResetEvent(false);

        private TOutput _m_value;
        private bool _m_blockOnConsume;

        public BlockOnConsumeSource(TOutput value, bool blockOnConsume)
        {
            _m_value = value;
            _m_blockOnConsume = blockOnConsume;

            if (!blockOnConsume) BlockingEvent.Set();
        }

        TOutput ISourceBlock<TOutput>.ConsumeMessage(DataflowMessageHeader messageHeader, ITargetBlock<TOutput> target, out Boolean messageConsumed)
        {
            ConsumedEvent.Set();
            this.BlockingEvent.WaitOne();
            messageConsumed = true;
            return _m_value;
        }

        IDisposable ISourceBlock<TOutput>.LinkTo(ITargetBlock<TOutput> target, DataflowLinkOptions linkOptions)
        {
            target.OfferMessage(new DataflowMessageHeader(1), _m_value, this, consumeToAccept: true);
            return new NoopOnUnlinked();
        }

        void ISourceBlock<TOutput>.ReleaseReservation(DataflowMessageHeader messageHeader, ITargetBlock<TOutput> target)
        {
            ReleasedEvent.Set();
        }

        bool ISourceBlock<TOutput>.ReserveMessage(DataflowMessageHeader messageHeader, ITargetBlock<TOutput> target)
        {
            ReservedEvent.Set();
            return true;
        }

        Task IDataflowBlock.Completion
        {
            get { throw new NotImplementedException(); }
        }

        public void Complete()
        {
            throw new NotImplementedException();
        }

        void IDataflowBlock.Fault(Exception exception)
        {
            throw new NotImplementedException();
        }
    }
}


text:
module.exports = function(grunt) {
  // measure task run times
  require('time-grunt')(grunt);

  // Load Grunt config
  require('load-grunt-config')(grunt);
};

redpajama_set_name: RedPajamaGithub


text:
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{parse_quote, spanned::Spanned};

use crate::{common::scalar, result::GraphQLScope};

use super::{Attr, Definition, Field, Methods, ParseToken, TypeOrIdent};

/// [`GraphQLScope`] of errors for `#[derive(GraphQLScalar)]` macro.
const ERR: GraphQLScope = GraphQLScope::ScalarDerive;

/// Expands `#[derive(GraphQLScalar)]` macro into generated code.
pub fn expand(input: TokenStream) -> syn::Result<TokenStream> {
    let ast = syn::parse2::<syn::DeriveInput>(input)?;
    let attr = Attr::from_attrs("graphql", &ast.attrs)?;
    let methods = parse_derived_methods(&ast, &attr)?;
    let scalar = scalar::Type::parse(attr.scalar.as_deref(), &ast.generics);

    Ok(Definition {
        ty: TypeOrIdent::Ident(ast.ident.clone()),
        where_clause: attr
            .where_clause
            .map_or_else(Vec::new, |cl| cl.into_inner()),
        generics: ast.generics.clone(),
        methods,
        name: attr
            .name
            .as_deref()
            .cloned()
            .unwrap_or_else(|| ast.ident.to_string()),
        description: attr.description.as_deref().cloned(),
        specified_by_url: attr.specified_by_url.as_deref().cloned(),
        scalar,
    }
    .to_token_stream())
}

/// Parses [`Methods`] from the provided [`Attr`] for the specified
/// [`syn::DeriveInput`].
pub(super) fn parse_derived_methods(ast: &syn::DeriveInput, attr: &Attr) -> syn::Result<Methods> {
    match (
        attr.to_output.as_deref().cloned(),
        attr.from_input.as_deref().cloned(),
        attr.parse_token.as_deref().cloned(),
        attr.with.as_deref().cloned(),
        attr.transparent,
    ) {
        (Some(to_output), Some(from_input), Some(parse_token), None, false) => {
            Ok(Methods::Custom {
                to_output,
                from_input,
                parse_token,
            })
        }
        (to_output, from_input, parse_token, module, false) => {
            let module = module.unwrap_or_else(|| parse_quote! { Self });
            Ok(Methods::Custom {
                to_output: to_output.unwrap_or_else(|| parse_quote! { #module::to_output }),
                from_input: from_input.unwrap_or_else(|| parse_quote! { #module::from_input }),
                parse_token: parse_token
                    .unwrap_or_else(|| ParseToken::Custom(parse_quote! { #module::parse_token })),
            })
        }
        (to_output, from_input, parse_token, None, true) => {
            let data = if let syn::Data::Struct(data) = &ast.data {
                data
            } else {
                return Err(ERR.custom_error(
                    ast.span(),
                    "`transparent` attribute argument requires exactly 1 field",
                ));
            };
            let field = match &data.fields {
                syn::Fields::Unit => Err(ERR.custom_error(
                    ast.span(),
                    "`transparent` attribute argument requires exactly 1 field",
                )),
                syn::Fields::Unnamed(fields) => fields
                    .unnamed
                    .first()
                    .filter(|_| fields.unnamed.len() == 1)
                    .cloned()
                    .map(Field::Unnamed)
                    .ok_or_else(|| {
                        ERR.custom_error(
                            ast.span(),
                            "`transparent` attribute argument requires \
                             exactly 1 field",
                        )
                    }),
                syn::Fields::Named(fields) => fields
                    .named
                    .first()
                    .filter(|_| fields.named.len() == 1)
                    .cloned()
                    .map(Field::Named)
                    .ok_or_else(|| {
                        ERR.custom_error(
                            ast.span(),
                            "`transparent` attribute argument requires \
                             exactly 1 field",
                        )
                    }),
            }?;
            Ok(Methods::Delegated {
                to_output,
                from_input,
                parse_token,
                field: Box::new(field),
            })
        }
        (_, _, _, Some(module), true) => Err(ERR.custom_error(
            module.span(),
            "`with = <path>` attribute argument cannot be combined with \
             `transparent`. \
             You can specify custom resolvers with `to_output_with`, \
             `from_input_with`, `parse_token`/`parse_token_with` attribute \
             arguments and still use `transparent` for unspecified ones.",
        )),
    }
}


text:
package com.intellij.codeInsight.daemon.impl.quickfix;

import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.CommonQuickFixBundle;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

public class ReplaceAddAllArrayToCollectionFix implements IntentionAction {
  private final PsiMethodCallExpression myMethodCall;

  public ReplaceAddAllArrayToCollectionFix(@NotNull PsiMethodCallExpression methodCall) {
    myMethodCall = methodCall;
  }

  @Override
  @NotNull
  public String getText() {
    return CommonQuickFixBundle.message("fix.replace.x.with.y", myMethodCall.getText(), getCollectionsMethodCall());
  }

  @Override
  @NotNull
  public String getFamilyName() {
    return getText();
  }

  @Override
  public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
    if (!myMethodCall.isValid()) return false;

    final Module module = ModuleUtilCore.findModuleForPsiElement(file);
    if (module == null) return false;
    final Sdk jdk = ModuleRootManager.getInstance(module).getSdk();
    if (jdk == null || !JavaSdk.getInstance().isOfVersionOrHigher(jdk, JavaSdkVersion.JDK_1_5)) return false;

    final PsiReferenceExpression expression = myMethodCall.getMethodExpression();
    final PsiElement element = expression.resolve();
    if (element instanceof PsiMethod) {
      final PsiMethod method = (PsiMethod)element;
      final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
      final PsiClass collectionsClass = psiFacade.findClass("java.util.Collection", GlobalSearchScope.allScope(project));
      if (collectionsClass != null && InheritanceUtil.isInheritorOrSelf(method.getContainingClass(), collectionsClass, true)) {
        if (Comparing.strEqual(method.getName(), "addAll") && PsiType.BOOLEAN.equals(method.getReturnType())) {
          final PsiParameter[] psiParameters = method.getParameterList().getParameters();
          if (psiParameters.length == 1 &&
              psiParameters[0].getType() instanceof PsiClassType &&
              InheritanceUtil.isInheritorOrSelf(((PsiClassType)psiParameters[0].getType()).resolve(), collectionsClass, true)) {
            final PsiExpressionList list = myMethodCall.getArgumentList();
            final PsiExpression[] expressions = list.getExpressions();
            if (expressions.length == 1) {
              if (expressions[0].getType() instanceof PsiArrayType) {
                return true;
              }
            }
          }
        }
      }
    }
    return false;
  }

  @Override
  public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
    final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
    final PsiExpression toReplace = elementFactory.createExpressionFromText(getCollectionsMethodCall(), myMethodCall);
    JavaCodeStyleManager.getInstance(project).shortenClassReferences(myMethodCall.replace(toReplace));
  }

  @NonNls
  private String getCollectionsMethodCall() {
    final PsiExpression qualifierExpression = myMethodCall.getMethodExpression().getQualifierExpression();
    PsiExpression[] expressions = myMethodCall.getArgumentList().getExpressions();
    return "java.util.Collections.addAll(" +
           (qualifierExpression != null ? qualifierExpression.getText() : "this") +
           ", " + (expressions.length == 0 ? "" : expressions[0].getText()) + ")";
  }

  @Override
  public boolean startInWriteAction() {
    return true;
  }
}


text:
package io.motown.ocpi.persistence.entities;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

/**
 * TokenSyncDate entity class
 *
 * @author bartwolfs
 *
 */
@Entity
@Table(name = "TOKEN_SYNC_DATE")
public class TokenSyncDate {

	@Id
	@Column(name = "id")
	@SequenceGenerator(name = "TOKEN_SYNC_DATE_SEQ", allocationSize = 1, initialValue = 1)
	@GeneratedValue(generator = "TOKEN_SYNC_DATE_SEQ")
	private Integer id;

	@Column(name = "SYNC_DATE", nullable = false)
	private Date syncDate;

	@Column(name = "SUBSCRIPTION_ID", nullable = false)
	private Integer subscriptionId;

	public TokenSyncDate() {

	}

	public Integer getId() {
		return id;
	}

	public Integer getSubscriptionId() {
		return subscriptionId;
	}

	public Date getSyncDate() {
		return syncDate;
	}

	public void setSubscriptionId(Integer subscriptionId) {
		this.subscriptionId = subscriptionId;
	}

	public void setSyncDate(Date syncDate) {
		this.syncDate = syncDate;
	}
}


text:
//==================================================================================
// BSD 2-Clause License
//
// Copyright (c) 2014-2022, NJIT, Duality Technologies Inc. and other contributors
//
// All rights reserved.
//
// Author TPOC: contact@openfhe.org
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==================================================================================

/*
  This code runs unit tests for the FHEW methods of the OpenFHE lattice encryption library
 */

#include "gtest/gtest.h"

// these header files are needed for serialization
#include "binfhecontext-ser.h"

using namespace lbcrypto;

class UnitTestFHEWSerial : public ::testing::Test {
protected:
    virtual void SetUp() {}

    virtual void TearDown() {
        // Code here will be called immediately after each test
        // (right before the destructor).
    }
};
// ---------------  TESTING SERIALIZATION METHODS OF FHEW ---------------

// Checks serialization for JSON mode
TEST(UnitTestFHEWSerialAP, JSON) {
    auto cc1 = BinFHEContext();
    cc1.GenerateBinFHEContext(TOY, AP);

    auto sk1 = cc1.KeyGen();
    // cc1.BTKeyGen(sk1);

    // Encryption for a ciphertext that will be serialized
    auto ct1 = cc1.Encrypt(sk1, 1, FRESH);

    std::string msg = "JSON serialization test failed: ";

    std::stringstream s;
    Serial::Serialize(cc1, s, SerType::JSON);
    BinFHEContext cc;
    Serial::Deserialize(cc, s, SerType::JSON);

    EXPECT_EQ(*cc.GetParams(), *cc1.GetParams()) << msg << " Context mismatch";

    s.str("");
    s.clear();

    Serial::Serialize(sk1, s, SerType::JSON);
    LWEPrivateKey sk;
    Serial::Deserialize(sk, s, SerType::JSON);

    s.str("");
    s.clear();

    EXPECT_EQ(*sk1, *sk) << msg << " Secret key mismatch";

    Serial::Serialize(ct1, s, SerType::JSON);
    LWECiphertext ct;
    Serial::Deserialize(ct, s, SerType::JSON);

    EXPECT_EQ(*ct1, *ct) << msg << " Ciphertext mismatch";
}

// Checks serialization for JSON mode
TEST(UnitTestFHEWSerialGINX, JSON) {
    auto cc1 = BinFHEContext();
    cc1.GenerateBinFHEContext(TOY, GINX);

    auto sk1 = cc1.KeyGen();
    // cc1.BTKeyGen(sk1);

    // Encryption for a ciphertext that will be serialized
    auto ct1 = cc1.Encrypt(sk1, 1, FRESH);

    std::string msg = "JSON serialization test failed: ";

    std::stringstream s;
    Serial::Serialize(cc1, s, SerType::JSON);
    BinFHEContext cc;
    Serial::Deserialize(cc, s, SerType::JSON);

    EXPECT_EQ(*cc.GetParams(), *cc1.GetParams()) << msg << " Context mismatch";

    s.str("");
    s.clear();

    Serial::Serialize(sk1, s, SerType::JSON);
    LWEPrivateKey sk;
    Serial::Deserialize(sk, s, SerType::JSON);

    s.str("");
    s.clear();

    EXPECT_EQ(*sk1, *sk) << msg << " Secret key mismatch";

    Serial::Serialize(ct1, s, SerType::JSON);
    LWECiphertext ct;
    Serial::Deserialize(ct, s, SerType::JSON);

    EXPECT_EQ(*ct1, *ct) << msg << " Ciphertext mismatch";
}

// Checks serialization for BINARY mode
TEST(UnitTestFHEWSerialAP, BINARY) {
    auto cc1 = BinFHEContext();
    cc1.GenerateBinFHEContext(TOY, AP);

    auto sk1 = cc1.KeyGen();
    // cc1.BTKeyGen(sk1);

    // Encryption for a ciphertext that will be serialized
    auto ct111 = cc1.Encrypt(sk1, 1, FRESH);

    std::string msg = "BINARY serialization test failed: ";

    std::stringstream s;
    Serial::Serialize(cc1, s, SerType::BINARY);
    BinFHEContext cc;
    Serial::Deserialize(cc, s, SerType::BINARY);

    EXPECT_EQ(*cc.GetParams(), *cc1.GetParams()) << msg << " Context mismatch";

    /* commented out for now; the bootstrapping key is too large to fit in the
  std::stringstream

  s.str("");
  s.clear();

  Serial::Serialize(cc.GetRefreshKey(), s, SerType::BINARY);
  RingGSWACCKey refreshKey;
  Serial::Deserialize(refreshKey, s, SerType::BINARY);

  s.str("");
  s.clear();

  Serial::Serialize(cc.GetSwitchKey(), s, SerType::BINARY);
  LWESwitchingKey switchKey;
  Serial::Deserialize(switchKey, s, SerType::BINARY);

  // Loading deserialized bootstrapping keys
  cc.BTKeyLoad({refreshKey,switchKey});

  EXPECT_EQ( *cc.GetRefreshKey(), *cc1.GetRefreshKey() ) << msg << "
  Bootstrapping key mismatch: refresh key";
  //EXPECT_EQ( *cc.GetSwitchKey(), *cc1.GetSwitchKey() ) << msg << "
  Bootstrapping key mismatch: refresh key";

  */

    s.str("");
    s.clear();

    Serial::Serialize(sk1, s, SerType::BINARY);
    LWEPrivateKey sk;
    Serial::Deserialize(sk, s, SerType::BINARY);

    EXPECT_EQ(*sk1, *sk) << msg << " Secret key mismatch";

    s.str("");
    s.clear();

    Serial::Serialize(ct111, s, SerType::BINARY);
    LWECiphertext ct;
    Serial::Deserialize(ct, s, SerType::BINARY);

    EXPECT_EQ(*ct111, *ct) << msg << " Ciphertext mismatch";
}

// Checks serialization for BINARY mode
TEST(UnitTestFHEWSerialGINX, BINARY) {
    auto cc1 = BinFHEContext();
    cc1.GenerateBinFHEContext(TOY);

    auto sk1 = cc1.KeyGen();
    // cc1.BTKeyGen(sk1);

    // Encryption for a ciphertext that will be serialized
    auto ct111 = cc1.Encrypt(sk1, 1, FRESH);

    std::string msg = "BINARY serialization test failed: ";

    std::stringstream s;
    Serial::Serialize(cc1, s, SerType::BINARY);
    BinFHEContext cc;
    Serial::Deserialize(cc, s, SerType::BINARY);

    EXPECT_EQ(*cc.GetParams(), *cc1.GetParams()) << msg << " Context mismatch";

    /* commented out for now; the bootstrapping key is too large to fit in the
  std::stringstream

  s.str("");
  s.clear();

  Serial::Serialize(cc.GetRefreshKey(), s, SerType::BINARY);
  RingGSWACCKey refreshKey;
  Serial::Deserialize(refreshKey, s, SerType::BINARY);

  s.str("");
  s.clear();

  Serial::Serialize(cc.GetSwitchKey(), s, SerType::BINARY);
  LWESwitchingKey switchKey;
  Serial::Deserialize(switchKey, s, SerType::BINARY);

  // Loading deserialized bootstrapping keys
  cc.BTKeyLoad({refreshKey,switchKey});

  EXPECT_EQ( *cc.GetRefreshKey(), *cc1.GetRefreshKey() ) << msg << "
  Bootstrapping key mismatch: refresh key";
  //EXPECT_EQ( *cc.GetSwitchKey(), *cc1.GetSwitchKey() ) << msg << "
  Bootstrapping key mismatch: refresh key";

  */

    s.str("");
    s.clear();

    Serial::Serialize(sk1, s, SerType::BINARY);
    LWEPrivateKey sk;
    Serial::Deserialize(sk, s, SerType::BINARY);

    EXPECT_EQ(*sk1, *sk) << msg << " Secret key mismatch";

    s.str("");
    s.clear();

    Serial::Serialize(ct111, s, SerType::BINARY);
    LWECiphertext ct;
    Serial::Deserialize(ct, s, SerType::BINARY);

    EXPECT_EQ(*ct111, *ct) << msg << " Ciphertext mismatch";
}


text:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;

namespace FluentAssertions.Common
{
    internal class DefaultReflector : IReflector
    {
        public IEnumerable<Type> GetAllTypesFromAppDomain(Func<Assembly, bool> predicate)
        {
            return AppDomain.CurrentDomain
                .GetAssemblies()
                .Where(a => predicate(a) && !IsDynamic(a))
                .SelectMany(GetExportedTypes).ToArray();
        }

        private static bool IsDynamic(Assembly assembly)
        {
            return (assembly is AssemblyBuilder) ||
                   (assembly.GetType().FullName == "System.Reflection.Emit.InternalAssemblyBuilder");
        }

        private static IEnumerable<Type> GetExportedTypes(Assembly assembly)
        {
            try
            {
                return assembly.GetExportedTypes();
            }
            catch (ReflectionTypeLoadException ex)
            {
                return ex.Types;
            }
            catch (FileLoadException)
            {
                return new Type[0];
            }
            catch (Exception)
            {
                return new Type[0];
            }
        }
    }
}


text:
using System;
using System.Globalization;
using Newtonsoft.Json;

// -----===== autogenerated code =====-----
// ReSharper disable All
// generator: DerivedUnitGenerator, FractionValuesGenerator, UnitJsonConverterGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator, MultiplyAlgebraGenerator

namespace iSukces.UnitedValues
{
    [Serializable]
    [JsonConverter(typeof(LinearDensityJsonConverter))]
    public partial struct LinearDensity : IUnitedValue<LinearDensityUnit>, IEquatable<LinearDensity>, IFormattable
    {
        /// <summary>
        /// creates instance of LinearDensity
        /// </summary>
        /// <param name="value">value</param>
        /// <param name="unit">unit</param>
        public LinearDensity(decimal value, LinearDensityUnit unit)
        {
            Value = value;
            Unit = unit;
        }

        public LinearDensity(decimal value, MassUnit counterUnit, LengthUnit denominatorUnit)
        {
            Value = value;
            Unit = new LinearDensityUnit(counterUnit, denominatorUnit);
        }

        public LinearDensity ConvertTo(LinearDensityUnit newUnit)
        {
            // generator : FractionValuesGenerator.Add_ConvertTo
            if (Unit.Equals(newUnit))
                return this;
            var a = new Mass(Value, Unit.CounterUnit);
            var b = new Length(1, Unit.DenominatorUnit);
            a = a.ConvertTo(newUnit.CounterUnit);
            b = b.ConvertTo(newUnit.DenominatorUnit);
            return new LinearDensity(a.Value / b.Value, newUnit);
        }

        public bool Equals(LinearDensity other)
        {
            return Value == other.Value && !(Unit is null) && Unit.Equals(other.Unit);
        }

        public bool Equals(IUnitedValue<LinearDensityUnit> other)
        {
            if (other is null)
                return false;
            return Value == other.Value && !(Unit is null) && Unit.Equals(other.Unit);
        }

        public override bool Equals(object other)
        {
            return other is IUnitedValue<LinearDensityUnit> unitedValue ? Equals(unitedValue) : false;
        }

        public LinearDensity FromKgPerMeter(decimal value)
        {
            return new LinearDensity(value, LinearDensityUnits.KgPerMeter.Unit);
        }

        public decimal GetBaseUnitValue()
        {
            // generator : BasicUnitValuesGenerator.Add_GetBaseUnitValue
            var factor1 = GlobalUnitRegistry.Factors.Get(Unit.CounterUnit);
            var factor2 = GlobalUnitRegistry.Factors.Get(Unit.DenominatorUnit);
            if ((factor1.HasValue && factor2.HasValue))
                return Value * factor1.Value / factor2.Value;
            throw new Exception("Unable to find multiplication for unit " + Unit);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (Value.GetHashCode() * 397) ^ Unit?.GetHashCode() ?? 0;
            }
        }

        public LinearDensity Round(int decimalPlaces)
        {
            return new LinearDensity(Math.Round(Value, decimalPlaces), Unit);
        }

        /// <summary>
        /// Returns unit name
        /// </summary>
        public override string ToString()
        {
            return Value.ToString(CultureInfo.InvariantCulture) + Unit.UnitName;
        }

        /// <summary>
        /// Returns unit name
        /// </summary>
        /// <param name="format"></param>
        /// <param name="provider"></param>
        public string ToString(string format, IFormatProvider provider = null)
        {
            return this.ToStringFormat(format, provider);
        }

        public LinearDensity WithCounterUnit(MassUnit newUnit)
        {
            // generator : FractionValuesGenerator.Add_WithCounterUnit
            var oldUnit = Unit.CounterUnit;
            if (oldUnit == newUnit)
                return this;
            var oldFactor = GlobalUnitRegistry.Factors.GetThrow(oldUnit);
            var newFactor = GlobalUnitRegistry.Factors.GetThrow(newUnit);
            var resultUnit = Unit.WithCounterUnit(newUnit);
            return new LinearDensity(oldFactor / newFactor * Value, resultUnit);
        }

        public LinearDensity WithDenominatorUnit(LengthUnit newUnit)
        {
            // generator : FractionValuesGenerator.Add_WithDenominatorUnit
            var oldUnit = Unit.DenominatorUnit;
            if (oldUnit == newUnit)
                return this;
            var oldFactor = GlobalUnitRegistry.Factors.GetThrow(oldUnit);
            var newFactor = GlobalUnitRegistry.Factors.GetThrow(newUnit);
            var resultUnit = Unit.WithDenominatorUnit(newUnit);
            return new LinearDensity(newFactor / oldFactor * Value, resultUnit);
        }

        /// <summary>
        /// Inequality operator
        /// </summary>
        /// <param name="left">first value to compare</param>
        /// <param name="right">second value to compare</param>
        public static bool operator !=(LinearDensity left, LinearDensity right)
        {
            return !left.Equals(right);
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="length">a divisor (denominator) - a value which dividend is divided by</param>
        public static PlanarDensity operator /(LinearDensity linearDensity, Length length)
        {
            // generator : MultiplyAlgebraGenerator.CreateCodeForLeftFractionValue
            // PlanarDensity operator /(LinearDensity linearDensity, Length length)
            // scenario with hint
            // .Is<LinearDensity, Length, PlanarDensity>("/")
            // hint location GetBasicOperatorHints, line 31
            var linearDensityUnit = linearDensity.Unit;
            var tmp1 = linearDensityUnit.DenominatorUnit;
            var resultUnit = new PlanarDensityUnit(linearDensityUnit.CounterUnit, linearDensityUnit.DenominatorUnit.GetAreaUnit());
            var lengthConverted = length.ConvertTo(tmp1);
            var value = linearDensity.Value / lengthConverted.Value;
            return new PlanarDensity(value, resultUnit);
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="planarDensity">a divisor (denominator) - a value which dividend is divided by</param>
        public static Length operator /(LinearDensity linearDensity, PlanarDensity planarDensity)
        {
            // generator : MultiplyAlgebraGenerator.CreateOperator
            // scenario with hint
            // .Is<LinearDensity, PlanarDensity, Length>("/")
            // hint location GetBasicOperatorHints, line 31
            var linearDensityUnit = linearDensity.Unit;
            var tmp1 = linearDensityUnit.DenominatorUnit;
            var targetRightUnit = new PlanarDensityUnit(linearDensityUnit.CounterUnit, tmp1.GetAreaUnit());
            var planarDensityConverted = planarDensity.ConvertTo(targetRightUnit);
            var value = linearDensity.Value / planarDensityConverted.Value;
            return new Length(value, tmp1);
            // scenario F1
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="length">a divisor (denominator) - a value which dividend is divided by</param>
        public static PlanarDensity? operator /(LinearDensity? linearDensity, Length length)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (linearDensity is null)
                return null;
            return linearDensity.Value / length;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="planarDensity">a divisor (denominator) - a value which dividend is divided by</param>
        public static Length? operator /(LinearDensity? linearDensity, PlanarDensity planarDensity)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (linearDensity is null)
                return null;
            return linearDensity.Value / planarDensity;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="length">a divisor (denominator) - a value which dividend is divided by</param>
        public static PlanarDensity? operator /(LinearDensity linearDensity, Length? length)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (length is null)
                return null;
            return linearDensity / length.Value;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="planarDensity">a divisor (denominator) - a value which dividend is divided by</param>
        public static Length? operator /(LinearDensity linearDensity, PlanarDensity? planarDensity)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (planarDensity is null)
                return null;
            return linearDensity / planarDensity.Value;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="length">a divisor (denominator) - a value which dividend is divided by</param>
        public static PlanarDensity? operator /(LinearDensity? linearDensity, Length? length)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (linearDensity is null || length is null)
                return null;
            return linearDensity.Value / length.Value;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="planarDensity">a divisor (denominator) - a value which dividend is divided by</param>
        public static Length? operator /(LinearDensity? linearDensity, PlanarDensity? planarDensity)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (linearDensity is null || planarDensity is null)
                return null;
            return linearDensity.Value / planarDensity.Value;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="area">a divisor (denominator) - a value which dividend is divided by</param>
        public static Density operator /(LinearDensity linearDensity, Area area)
        {
            // generator : MultiplyAlgebraGenerator.CreateCodeForLeftFractionValue
            // Density operator /(LinearDensity linearDensity, Area area)
            // scenario with hint
            // .Is<LinearDensity, Area, Density>("/")
            // hint location GetBasicOperatorHints, line 31
            var linearDensityUnit = linearDensity.Unit;
            var tmp1 = linearDensityUnit.DenominatorUnit;
            var resultUnit = new DensityUnit(linearDensityUnit.CounterUnit, tmp1.GetVolumeUnit());
            var areaConverted = area.ConvertTo(tmp1.GetAreaUnit());
            var value = linearDensity.Value / areaConverted.Value;
            return new Density(value, resultUnit);
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="density">a divisor (denominator) - a value which dividend is divided by</param>
        public static Area operator /(LinearDensity linearDensity, Density density)
        {
            // generator : MultiplyAlgebraGenerator.CreateOperator
            // scenario with hint
            // .Is<LinearDensity, Density, Area>("/")
            // hint location GetBasicOperatorHints, line 31
            var linearDensityUnit = linearDensity.Unit;
            var tmp1 = linearDensityUnit.DenominatorUnit;
            var targetRightUnit = new DensityUnit(linearDensityUnit.CounterUnit, tmp1.GetVolumeUnit());
            var densityConverted = density.ConvertTo(targetRightUnit);
            var value = linearDensity.Value / densityConverted.Value;
            return new Area(value, tmp1.GetAreaUnit());
            // scenario F1
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="area">a divisor (denominator) - a value which dividend is divided by</param>
        public static Density? operator /(LinearDensity? linearDensity, Area area)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (linearDensity is null)
                return null;
            return linearDensity.Value / area;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="density">a divisor (denominator) - a value which dividend is divided by</param>
        public static Area? operator /(LinearDensity? linearDensity, Density density)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (linearDensity is null)
                return null;
            return linearDensity.Value / density;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="area">a divisor (denominator) - a value which dividend is divided by</param>
        public static Density? operator /(LinearDensity linearDensity, Area? area)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (area is null)
                return null;
            return linearDensity / area.Value;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="density">a divisor (denominator) - a value which dividend is divided by</param>
        public static Area? operator /(LinearDensity linearDensity, Density? density)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (density is null)
                return null;
            return linearDensity / density.Value;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="area">a divisor (denominator) - a value which dividend is divided by</param>
        public static Density? operator /(LinearDensity? linearDensity, Area? area)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (linearDensity is null || area is null)
                return null;
            return linearDensity.Value / area.Value;
        }

        /// <summary>
        /// Division operation, calculates value dividend/divisor with unit that derives from dividend unit
        /// </summary>
        /// <param name="linearDensity">a dividend (counter) - a value that is being divided</param>
        /// <param name="density">a divisor (denominator) - a value which dividend is divided by</param>
        public static Area? operator /(LinearDensity? linearDensity, Density? density)
        {
            // generator : MultiplyAlgebraGenerator.CreateCode
            if (linearDensity is null || density is null)
                return null;
            return linearDensity.Value / density.Value;
        }

        /// <summary>
        /// Equality operator
        /// </summary>
        /// <param name="left">first value to compare</param>
        /// <param name="right">second value to compare</param>
        public static bool operator ==(LinearDensity left, LinearDensity right)
        {
            return left.Equals(right);
        }

        public static LinearDensity Parse(string value)
        {
            // generator : FractionValuesGenerator.Add_Parse
            if (string.IsNullOrEmpty(value))
                throw new ArgumentNullException(nameof(value));
            var r = CommonParse.Parse(value, typeof(LinearDensity));
            var units = Common.SplitUnitNameBySlash(r.UnitName);
            if (units.Length != 2)
                throw new Exception($"{r.UnitName} is not valid LinearDensity unit");
            var counterUnit = new MassUnit(units[0]);
            var denominatorUnit = new LengthUnit(units[1]);
            return new LinearDensity(r.Value, counterUnit, denominatorUnit);
        }

        /// <summary>
        /// value
        /// </summary>
        public decimal Value { get; }

        /// <summary>
        /// unit
        /// </summary>
        public LinearDensityUnit Unit { get; }

    }

    public partial class LinearDensityJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(LinearDensityUnit);
        }

        /// <summary>
        /// Reads the JSON representation of the object.
        /// </summary>
        /// <param name="reader">The JsonReader to read from.</param>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="existingValue">The existing value of object being read.</param>
        /// <param name="serializer">The calling serializer.</param>
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.ValueType == typeof(string))
            {
                if (objectType == typeof(LinearDensity))
                    return LinearDensity.Parse((string)reader.Value);
            }
            throw new NotImplementedException();
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value is null)
                writer.WriteNull();
            else
                writer.WriteValue(value.ToString());
        }

    }
}


text:
asynctest('browser/core/MeasureTest', [
	'ephox.mcagar.api.TinyLoader',
	'tinymce/inlite/core/Measure',
	'ephox.agar.api.Pipeline',
	'ephox.mcagar.api.TinyApis',
	'ephox.agar.api.Step',
	'ephox.agar.api.Chain',
	'ephox.agar.api.UiFinder',
	'ephox.agar.api.Assertions'
], function (TinyLoader, Measure, Pipeline, TinyApis, Step, Chain, UiFinder, Assertions) {
	var success = arguments[arguments.length - 2];
	var failure = arguments[arguments.length - 1];

	var containsXY = function (r, x, y) {
		return x >= r.x && x <= r.x + r.w && y >= r.y && y <= r.y + r.h;
	};

	var contains = function (a, b) {
		return containsXY(a, b.x, b.y) && containsXY(a, b.x + b.w, b.y + b.h);
	};

	var sAssertRect = function (editor, measure) {
		return Step.sync(function () {
			var elementRect = measure();
			var pageAreaRect = Measure.getPageAreaRect(editor);
			var contentAreaRect = Measure.getContentAreaRect(editor);

			Assertions.assertEq(contains(pageAreaRect, elementRect), true, 'Rect is not in page area rect');
			Assertions.assertEq(contains(contentAreaRect, elementRect), true, 'Rect is not in content area rect');
			Assertions.assertEq(elementRect.w > 0, true, 'Rect should have width');
			Assertions.assertEq(elementRect.h > 0, true, 'Rect should have height');
		});
	};

	var getElementRectFromSelector = function (editor, selector) {
		return function () {
			var elm = editor.dom.select(selector)[0];
			var rect = Measure.getElementRect(editor, elm);
			return rect;
		};
	};

	var getSelectionRectFromSelector = function (editor) {
		return function () {
			var rect = Measure.getSelectionRect(editor);
			return rect;
		};
	};

	TinyLoader.setup(function (editor, onSuccess, onFailure) {
		var tinyApis = TinyApis(editor);

		Pipeline.async({}, [
			tinyApis.sSetContent('
a

b

c
'),
			sAssertRect(editor, getElementRectFromSelector(editor, 'p:nth-child(1)')),
			tinyApis.sSetCursor([0, 0], 0),
			sAssertRect(editor, getSelectionRectFromSelector(editor))
		], onSuccess, onFailure);
	}, {
		inline: true
	}, success, failure);
});