Saturday, June 28, 2014

Sending data to a server with Groovy

The Groovy language provides a lot of additions to existing Java classes that can make our jobs easier.

A couple of them we were able to take advantage of lately that use closures to make our coding simpler were:

Our use case: We have a service whose responsibility is to send "records" over a TCP/IP connection to a remote server.

Of course we want to include a test for this in our integration tests, but how can we do it? We cannot expect a client to leave a server available open to receive records sent by our tests. We could create our test server to accept and output the sent record.

We'll write a test server using Groovy that can be started at the beginning of the test run and shutdown at the end:

class TestServer {

    static defaultPort = 6666

    static ServerSocket start_on_default_port() {
        start_on defaultPort
    }

    static ServerSocket start_on(port) {

        def server = new ServerSocket(port)
        String receivedRecord ''
        def done = false

        Thread.start { t ->
            while (!done) {
                server.accept { socket ->
                    socket.withStreams { input, output ->
                        done = false

                        while (!done) {
                            def block = new byte[128]
                            int size = input.read block

                            if (size == -1) done = true // there is nothing left to have been received

                            block = trim(block as List)
                            receivedRecord += new String(block)
                        }
                    }
                }
            }
        }
        server
    }

    /** Remove any empty or non-set bytes at the end of the array. */
    private static def trim(List block) {
        block.reverse().findAll { b -> b != 0 }.reverse() as byte[]
    }
}

In our integration tests class, written with Spock, we start and stop the server at the beginning of the run:

@ContextConfiguration
class RecordDeliveryServiceIntegrationSpec extends Specification {

    @Autowired
    RecordDeliveryService service

    static def server

    def setupSpec() {
        server = TestServer.start_on_default_port()
    }

    def cleanupSpec() {
        server.close()
    }

    def 'delivers a record to a server'() {
        expect:
        expectedResponse == service.send 'localhost', TestServier.defaultPort, record
    }

    //...
}

For reference to complete the example, here's what a simplified service implementation could look like, using a methodology similar to that the test server uses to accept the record:

dclass RecordDeliveryService implements DeliveryService {

    public def send(String host, long port, Record record) {

        def socket = new Socket(host, port)

        socket.withStreams { input, output ->
            output << record.toString()
            output.flush()
            output.close()
        }

        socket.close()
    }
}   //...
}

If you can think of any improvements, or a better approach to the problem, I would be glad to hear from you!

Maven: Failing the Build After Running All Modules

Maven: Failing the Build After Running All Modules

Here's a quick one to help me feel a better about not posting anything for quite a while.

In our large project at work that contains several deployed services, we have several parent integration testing Maven modules that run after our nightly development install. Each has several child modules that each run tests against a particular endpoint in each service.

So naturally, we want our build server to kick off each parent testing module after the install. The problem we ran into is when that one of the earlier child modules failed, the build will stop, without running the rest of the modules (Maven's default behavior).

This would often lead to us making changes to get the tests in the failing module to pass, then re-running the testing build, only to have a later child module to fail. It would be nice to have had all the modules to run, reporting all failures, so that all the required changes and fixes could be made up front, saving us time.

Fortunately, Maven provides an option we learned about do just that:

-fae,--fail-at-end     Only fail the build afterwards;
                       allow all non-impacted builds to continue

There are also a couple more failure related options as well, but we have yet to find any use for them (yet):

-ff,--fail-fast        Stop at first failure in reactorized builds
-fn,--fail-never       NEVER fail the build, regardless of project result

When working on the tests locally, we can pick up the build from within the parent from the point of the failed chilid module after making changes to our running service to fix the test with:

-rf,--resume-from      Resume reactor from specified project

For example:

$ mvn verify -rf :service-integration-testing-records

For more on working with multiple modules, see: Guide to Working with Multiple Modules.