February 09, 2015
On Monday, 9 February 2015 at 04:16:26 UTC, Walter Bright wrote:
> std.internal.test.dummyrange
>
> Cursory review:
>
> 1. Yes, it's what I was asking for, at least in part.
>
> 2. Being in std.internal.test implies it is not for general usage. It needs to be for general usage.
>
> 3. It's used here:
>
> grep -r std.internal.test *.d
> algorithm\comparison.d:    import std.internal.test.dummyrange;
> algorithm\iteration.d:    import std.internal.test.dummyrange;
> algorithm\iteration.d:    import std.internal.test.dummyrange;
> algorithm\iteration.d:    import std.internal.test.dummyrange;
> algorithm\iteration.d:    import std.internal.test.dummyrange;
> algorithm\iteration.d:    import std.internal.test.dummyrange;
> algorithm\iteration.d:    import std.internal.test.dummyrange;
> algorithm\mutation.d:    import std.internal.test.dummyrange;
> algorithm\mutation.d:    import std.internal.test.dummyrange;
> algorithm\searching.d:    import std.internal.test.dummyrange;
> algorithm\searching.d:    import std.internal.test.dummyrange;
> algorithm\searching.d:    import std.internal.test.dummyrange;
> algorithm\searching.d:    import std.internal.test.dummyrange;
> algorithm\searching.d:    import std.internal.test.dummyrange;
> algorithm\searching.d:    import std.internal.test.dummyrange;
> internal\test\dummyrange.d:module std.internal.test.dummyrange;
> range\constraints.d:    import std.internal.test.dummyrange;
> range\interfaces.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\package.d:    import std.internal.test.dummyrange;
> range\primitives.d:    import std.internal.test.dummyrange;
>
> I'd like to see it used much more pervasively in Phobos - essentially with every range that is defined, and every component that takes a range as a parameter, unless there's a good reason not to on a case-by-case basis.
>
> 4. It's only for uint data. This should be parameterized.
>
> 5. It's terribly underdocumented. I have no idea what ReturnBy, Length, or RangeType are without reading the implementation code.
>
> 6. It does not contain any protocol verification - for example, front() does not check that empty() was called beforehand.
>
> 7. There's not a single unittest in it.
>
> 8. I don't see any connection between DummyRange and ReferenceInputRange.
>
> 9. There are no test functions which accept an input range and test that the protocol at least exists and does not crash.
>
> 10. No @system types.
>
> 11. No output ranges.

This looks like a good bugzilla enhancement request. As you often say: it will get lost here.
February 09, 2015
On Monday, 9 February 2015 at 01:41:33 UTC, Walter Bright wrote:
> More and more, D code is written as a component that takes a type parameters that are ranges. Unit testing becomes inconvenient, as types must be mocked up to call them. Using an array of data often is inadequate, because the component may have specializations for an array, or specifies a range that is a subset of what an array provides.
>
> For example, here's a test range I wrote once for a unittest:
>
>   struct Adapter
>   {
>       this(ubyte[] r) { this.r = r; }
>       @property bool empty() { return r.length == 0; }
>       @property ubyte front() { return r[0]; }
>       void popFront() { r = r[1 .. $]; }
>       @property size_t length() { return r.length; }
>
>     private:
>       ubyte[] r;
>   }
>
> I propose a std.test.ranges package, which contains templates defining each of the range types (InputRange, BiDirectionalRange, etc.). Each accepts an argument which is a static array of T, and then implements exactly the range interface indicated by its name, nothing more. The range will also have asserts to guarantee they are used correctly, i.e. front() cannot be called before empty() returns false.

Great idea. It might even be better to split the two concerns: Mock ranges taking the static array as data and testing wrappers that enforce correct usage of wrapped ranges.

So that I can

TokenRange lex() { ... } // returns a range of token

// check that the TokenRange is a valid forward range
testIsForwardRange!TokenRange

// parser
auto parse(TR)(TR r) { ... }

// normal use
auto result = parse(lex());
// testing that parse uses the TR correctly
auto result = parse(assertingForwardRange(lex()));

This way it's easier to craft input for testing the correctness of parse.
February 09, 2015
On Monday, 9 February 2015 at 04:40:36 UTC, H. S. Teoh wrote:
> On Sun, Feb 08, 2015 at 06:06:59PM -0800, Walter Bright via Digitalmars-d wrote:
>> I.e. by providing standard mockups for components, and standard tests
>> for component protocols, we can significantly improve the unit testing
>> and standard conformance of user designed components.
>
> Yes, I've suggested this a long time ago but it seemed to have fallen by
> the wayside. It would be good to provide standard testing stuff for:
>
> - Non-forward input ranges.
> - Forward but non-bidirectional ranges.
> - Bidirectional but not random access ranges.
> - Infinite ranges vs. finite ranges.
> - Ranges with reference semantics vs. value semantics.
> - Array-like ranges that are not arrays.
>
> Ideally, every range-based function in Phobos should be tested with each
> of these variations, to ensure correct semantics under all
> representative use cases.
>
>
> T
>
> --
> Everybody talks about it, but nobody does anything about it!  -- Mark Twain

Was the Mark Twain quote intentional?

February 09, 2015
On Mon, 09 Feb 2015 13:48:55 +0000, CraigDillabaugh wrote:

>> Everybody talks about it, but nobody does anything about it! -- Mark Twain
> 
> Was the Mark Twain quote intentional?

it's a Fortune Wisdom. ;-)

February 10, 2015
On Sunday, February 08, 2015 18:08:31 Walter Bright via Digitalmars-d wrote:
> On 2/8/2015 5:52 PM, Jakob Ovrum wrote:
> > On Monday, 9 February 2015 at 01:41:33 UTC, Walter Bright wrote:
> >> Anyone interested in taking up this flag?
> >
> > Is this idea different from the one in std.internal.test.dummyrange?
>
> I wasn't aware of the existence of that. Will check it out.

It's a nice start, but it's far too limited IMHO, since it only defines a very restricted subset of range types (though it's certainly better than nothing). I started implementing a more full-featured solution (one which would allow you to define any combination of range types - bidirectional with length, without length, infinite, etc.), but I ran into either compiler bugs or library bugs IIRC, and it fell by the wayside.

Regardless, I think that we should create a general solution which allows you to instantiate the full combination of range types (as well as specifying a reasonable subsets for those who want decent coverage but don't want to test every combination) and which can be used in anyone's code rathear than just in Phobos.

And perhaps, a package containing a variety of unit test helpers is in order, where a module handling ranges would be just one of the modules therein.

- Jonathan M Davis

February 10, 2015
On 2/9/2015 3:03 AM, John Colvin wrote:
> This looks like a good bugzilla enhancement request. As you often say: it will
> get lost here.

It needs to be rethought from the ground up, and introduced as a new module. I'm looking for someone to carry the flag on this.
February 10, 2015
On Monday, 9 February 2015 at 14:47:09 UTC, ketmar wrote:
> On Mon, 09 Feb 2015 13:48:55 +0000, CraigDillabaugh wrote:
>
>>> Everybody talks about it, but nobody does anything about it! -- Mark
>>> Twain
>> 
>> Was the Mark Twain quote intentional?
>
> it's a Fortune Wisdom. ;-)

If I recall correctly, H.S. Teoh has...assisted the randomness of his signature in the past :P.
February 10, 2015
On Tue, Feb 10, 2015 at 05:46:20PM +0000, Brad Anderson via Digitalmars-d wrote:
> On Monday, 9 February 2015 at 14:47:09 UTC, ketmar wrote:
> >On Mon, 09 Feb 2015 13:48:55 +0000, CraigDillabaugh wrote:
> >
> >>>Everybody talks about it, but nobody does anything about it! -- Mark Twain
> >>
> >>Was the Mark Twain quote intentional?
> >
> >it's a Fortune Wisdom. ;-)
> 
> If I recall correctly, H.S. Teoh has...assisted the randomness of his signature in the past :P.

Yes I have been guilty of that in the past... but this particular instance is solely the genius of my Perl script. :-)


T

-- 
Век живи - век учись. А дураком помрёшь.
February 10, 2015
On Tue, 10 Feb 2015 17:46:20 +0000, Brad Anderson wrote:

> On Monday, 9 February 2015 at 14:47:09 UTC, ketmar wrote:
>> On Mon, 09 Feb 2015 13:48:55 +0000, CraigDillabaugh wrote:
>>
>>>> Everybody talks about it, but nobody does anything about it! -- Mark Twain
>>> 
>>> Was the Mark Twain quote intentional?
>>
>> it's a Fortune Wisdom. ;-)
> 
> If I recall correctly, H.S. Teoh has...assisted the randomness of his signature in the past :P.

but his actions depends of such many things that we can consider that help as random action too. maybe just not cryptographically strong randomness. ;-)

February 10, 2015
To get things started, I created an InputRange and a function to test any InputRange. Compiling it:

    dmd inputrange -unittest -main -cov

shows 100% coverage.

-------------
struct InputRange(T : T[])
{
    this(T[] r)
    {
	this.r = r;
    }

    @property bool empty()
    {
	hasData = (r.length != 0);
	return !hasData;
    }

    @property T front()
    {
	assert(hasData);
	return r[0];
    }

    void popFront()
    {
	assert(hasData);
	r = r[1 .. $];
	hasData = false;
    }

  private:
    T[] r;
    bool hasData;
}

void testInputRange(R)(R r, int n)
{
    foreach (i; 0 .. n)
    {
	if (!r.empty)
	{
	    if (i & 1)
	    {
		auto e = r.front;
		auto e2 = r.front;
		assert(e == e2);
	    }
	    r.popFront();
	}
    }
}

unittest
{
    string s = "hello";
    auto r = InputRange!string(s);
    r.testInputRange(10);
}
-------------