简体   繁体   中英

How to unit test a thread safe queue

I need a simple data structure with these requirements:

  • it should behave like a queue,
  • all the enqueue operations should be atomic.

I have very limited experience with multithreading, but this is what I came up to:

public class Tickets
{
    private ConcurrentQueue<uint> _tickets;

    public Tickets(uint from, uint to)
    {
        Initialize(from, to);
    }

    private readonly object _lock = new object();
    public void Initialize(uint from, uint to)
    {
        lock(_lock)
        {
            _tickets = new ConcurrentQueue<uint>();

            for (uint i = from; i <= to; i++)
            {
                _tickets.Enqueue(i);
            }
        }
    }

    public uint Dequeue()
    {
        uint number;
        if (_tickets.TryDequeue(out number))
        {
            return number;
        }

        throw new ArgumentException("Ticket queue empty!");
    }
}

First question: is this code ok?

Secod question: how can I unit test this class (for instance with two threads which are perfoming dequeue operation periodically on the queue with elements (1, 2, 3, 4, 5, 6) and the first thread should get only odd numbers and the second thread only the even numbers)? I tried this, but the asserts aren't executing:

[Test]
public void Test()
{
    var tickets = new Tickets(1, 4);
    var t1 = new Thread(() =>
                            {
                                Assert.AreEqual(1, tickets.Dequeue());
                                Thread.Sleep(100);
                                Assert.AreEqual(3, tickets.Dequeue());
                            });


    var t2 = new Thread(() =>
                            {
                                Assert.AreEqual(2, tickets.Dequeue());
                                Thread.Sleep(100);
                                Assert.AreEqual(4, tickets.Dequeue());
                            });

    t1.Start();
    t2.Start();
}

I would use chess: http://research.microsoft.com/en-us/projects/chess

CHESS is a tool for finding and reproducing Heisenbugs in concurrent programs. CHESS repeatedly runs a concurrent test ensuring that every run takes a different interleaving. If an interleaving results in an error, CHESS can reproduce the interleaving for improved debugging. CHESS is available for both managed and native programs.

The problem with multithreading and unit tests is one of timing. When you try to introduce multiple threads to unit tests you run the risk of non-reproducable test results, tests that pass sometimes but not other times.

But just to explain why your asserts may not be executing, the unit test completes before the threads. It needs to wait for the threads to complete rather than just kicking them off and moving on. It's also feasible that the unit test framework itself is not threadsafe or capable of Asserts being called from other threads.

Sorry it's not a solution, but I don't know of any automated testing solution for multithreaded code either.

See also: How should I unit test threaded code?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM