Handle the real semantics of `String#lines`...

The previous monkey-patching of `String#lines` and `IO#lines` led to their
behaving differently in our code than in standard Ruby code.  This is
generally surprising, and led to some subtle misuses of the method.

This corrects that, by adapting all the abusers to real Ruby calling
conventions over the enumerator interface.

Signed-off-by: Daniel Pittman <daniel@puppetlabs.com>
The return type of `methods` changed in 1.9

This test depended on the return type of `methods`, which went from array of
strings to array of symbols in Ruby 1.9.  Given that it really wanted to test
if the instance responded to the message, we can just directly test that.

Signed-off-by: Daniel Pittman <daniel@puppetlabs.com>
A correct implementation of IO#binwrite for Ruby 1.8

When we added the `IO#binwrite` method to our collection of backported
features, the specification was misinterpreted and the offset was treated as
"offset in the string we are writing".

Instead, it is an instruction to seek in the output file before writing, which
meant that our semantics were all wrong - and tests broke - when we ran
against the native binwrite on Ruby 1.9.

The new implementation is correct in behaviour on all tested cases, and has a
more extensive test suite exercising all the various parts of the behaviour
that we need.

Signed-off-by: Daniel Pittman <daniel@puppetlabs.com>
Fix Cisco device canonicalization regular expression on 1.9

The behaviour of the `\b` Regexp match operator, or rather, the classification
of `/` as an end of word character, changed between Ruby 1.8 and 1.9.

Most uses in our code are safe, and this will lead to equally correct
behaviour, but the Cisco device interface canonicalization code used it where
"end of string before newline" was intended.

Moving to the `\Z` match, which imposes the exactly desired condition,
resolves the problem.

Signed-off-by: Daniel Pittman <daniel@puppetlabs.com>
Partially fix UTF-8 and PSON encoding tests for Ruby 1.9

With the introduction of real encoding support in Ruby 1.9, various problems
including incorrectly encoded UTF-8 strings crop up.

By flagging the encoding of the spec file to Ruby, and forcing binary encoding
on strings we compare that contain invalid UTF-8, we can bypass some of those
headaches.

Since PSON is, by design, not compatible with JSON and can do useful things
with arbitrary binary data, this is the most reasonably current choice for how
to handle this troublesome set of data.

Signed-off-by: Daniel Pittman <daniel@puppetlabs.com>
Implement YAML 1.1 binary data encoding in ZAML

The YAML spec has a mechanism to flag arbitrary binary data, as opposed to
sequences of Unicode characters in UTF-8.  This implements full support for
that in the ZAML encoder.

This is used on the basis of a string that doesn't contain valid UTF-8.
Another stinking heuristic, but at least one that results in conformant YAML
being emitted.

Pleasantly, the !binary tagged data is correctly ready by Syck as far back as
Ruby 1.8.5, allowing us to confidently ship this data without too much concern
for compatibility with older libraries.

Additionally, we stop escaping all UTF-8 data as a sequence of bytes.
Theoretically we could go back to escaping it, using real Unicode character
markers, but literal UTF-8 in the output file is just as acceptable.

This should gain better support for the Ruby 1.9 encoding markers, so that
strings could carry their binary or non-binary nature in ... but this gets
things working and passes both Unicode and Binary data tests.

Signed-off-by: Daniel Pittman <daniel@puppetlabs.com>
When shutting down Mongrel, wait synchronously for stop.

The Mongrel tests on Ruby 1.9 were highly unreliable, sometimes failing
because they tried to bind a port that was already in use.

This turns out to be because the default shutdown mode is to asynchronously
stop workers - combined with the fact that our test made a TCP connection to
the service, but never actually completed the request.

That led to one thread that dangled, if the socket didn't close in a timely
fashion, and blocked up the listen port.

Instead, two things: first, wait for all threads to terminate (or 60 seconds
to pass) in the stop method, and second, use a full HTTP request to test, not
just a TCP connection with no content.

Signed-off-by: Daniel Pittman <daniel@puppetlabs.com>
Remove the "fails_on_ruby_1.9.2" tag from tests...

Now we have passing tests on Ruby 1.9, we can make all those tags go away and
enable the full suite.  Now anything that fails should be treated like a real
failure, which is reasonable since this is a real and supported platform.

Signed-off-by: Daniel Pittman <daniel@puppetlabs.com>