Skip to content

Conversation

@dnachbaur
Copy link
Contributor

@dnachbaur dnachbaur commented Aug 7, 2017

  • Throw on failed connection to server in stream ctor; refactor test deflect servers
  • Transform error message printing into exceptions
  • Catch errors regarding invalid JPEG quality values
  • Allow uncompressed small tile sending
  • Move sendSizeHints and sendData also to Observer

@dnachbaur dnachbaur requested a review from rdumusc August 7, 2017 16:12
Copy link

@rdumusc rdumusc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good in general!


try
{
future.waitForFinished();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we shouldn't wait for the result. The sending should start while the compression is in progress (see comments below).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course. I just focused on getting the exception from the async execution. Too bad

std::stringstream msg;
msg << "libjpeg-turbo image conversion failure: " << tjGetErrorStr()
<< std::endl;
throw std::runtime_error(msg.str());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK but the header should mention that the function can throw.

@dnachbaur
Copy link
Contributor Author

I kept the empty bytearray for indicating errors and check it accordingly.

// Note: the following send tests only work as the small segment send does not
// need the sendWorker thread to be present. So fortunate for us we can skip
// setting up a stream server.
BOOST_AUTO_TEST_CASE(testErrorOnUncompressedRGBA)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, this was indeed missing! Let's be fully complete and split this in three test cases:

  • testSendUncompressedRGBA
  • testErrorOnUnsupportedUncompressedFormats
  • testErrorOnNullUncompressedImage


deflect::ImageWrapper bigImage(nullptr, 1000, 1000, deflect::ARGB);
bigImage.compressionPolicy = deflect::COMPRESSION_ON;
BOOST_CHECK(!stream.send(bigImage).get());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I that the only line we are truly testing? The amount of boilerplate code in this test suite is starting to be worrying, we should look for a way to mock the server / connection or at least reuse a shared Fixture.

* @param sourceImage The source image containing uncompressed image data.
* @param imageRegion The region of the image to be compressed. Must not
* exceed image dimensions.
* @return compressed image if successful, otherwise QByteArray.isEmpty()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, this was missing

@bbpbuildbot
Copy link

Build finished.

return QByteArray();
std::stringstream msg;
msg << "libjpeg-turbo image conversion failure: " << tjGetErrorStr();
throw std::invalid_argument(msg.str());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say this is more a runtime_error at this point

* @return compressed image if successful, otherwise QByteArray.isEmpty()
* @return compressed image
* @throw std::invalid_argument if sourceImage.data is nullptr or
* tjCompress2 failed
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't mention tjCompress2 in the doc, it's an implementation detail and has the potential to become outdated

*
* @param image The image to be compressed
* @return the compressed segment
* @throw std::runtime_error if image is too big
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too big -> invalid_argument?

break;
}
if (request.promise)
request.promise->set_value(true);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this works, does it pass unit tests? you have changed the logic and doing set_value() for each task, which should fail at the second set (and be caught again by the catch (...)). Recommendation: Keep the logic as it was before, with the try/catch surrounding the entire for-loop.

<< image.compressionQuality << std::endl;
return make_ready_future(false);
return make_exception_future<bool>(
std::make_exception_ptr(std::invalid_argument(msg.str())));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move std::make_exception_ptr inside make_exception_future to avoid repeating it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is make_exception_future<bool>(std::current_exception()); in StreamSendWorker which wouldn't work then

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we could have two, or an overload for Exception=std::exception_ptr, something like:

template <typename T>
std::future<T> make_exception_future(std::exception_ptr&& e)
{
    std::promise<T> promise;
    promise.set_exception(std::move(e));
    return promise.get_future();
}
template <typename T, typename Exception>
std::future<T> make_exception_future(Exception&& e)
{
    return make_exception_future(std::make_exception_ptr(std::move(e)));
}


Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would work. Looks nice, thx!

deflect::Stream stream("id", "dummyhost");
std::vector<unsigned char> pixels(4 * 4 * 4);

std::vector<deflect::PixelFormat> unsupportedUncompressedFormats = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name it allFormats here? I think you can even use auto for the variable type (init list).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping?

Copy link

@rdumusc rdumusc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This improves the readability quite a bit, good job!

BOOST_CHECK_THROW(deflect::Stream("id", "localhost"), std::runtime_error);
}

BOOST_AUTO_TEST_CASE(testDefaultConstructorReadsEnvironmentVariables)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test case got lost, but I still valid

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It cannot be replicated if a server is used that does not run on port 1701, which shouldn't be hardcoded in a unit test. DEFLECT_PORT as an env variable can be the only solution then.

serverThread.wait();
processServerMessage();

BOOST_CHECK_EQUAL(openedStreams, 0);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no longer checked?

Copy link
Contributor Author

@dnachbaur dnachbaur Aug 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't fully done yet yesterday, you reviewed too early :) I have not adapted all tests in here yet

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be checked again

@dnachbaur dnachbaur force-pushed the master branch 4 times, most recently from bb78046 to ee4128c Compare August 9, 2017 10:12
{
public:
/** The default communication port */
static const unsigned short defaultPortNumber;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use this constant also in the 2 constructors with params (Observer + Stream)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

return make_exception_future<bool>(std::make_exception_ptr(
std::invalid_argument("Pending finish, no send allowed")));
return make_exception_future<bool>(
std::invalid_argument("Pending finish, no send allowed"));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::runtime_error here? Does not depend on the arguments

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

deflect::Stream stream("id", "dummyhost");
std::vector<unsigned char> pixels(4 * 4 * 4);

std::vector<deflect::PixelFormat> unsupportedUncompressedFormats = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping?

_thread.wait();
}

void DeflectServer::processServerMessage()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently this is waitForMessage(), no processing happens here


#include <QThread>

class MinimalDeflectServer
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to suggest letting DeflectServer derive from MinimalDeflectServer, but realized they are not the same, because this one is in fact a wrapper for the MockServer. We should find clearer names...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we should treat as good now and merge this :)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK :-)


#include <QThread>

class MinimalDeflectServer
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK :-)

@dnachbaur dnachbaur merged commit 6111f35 into BlueBrain:master Aug 9, 2017
rdumusc pushed a commit to rdumusc/Deflect that referenced this pull request Aug 30, 2017
Also report stream connection errors in the GUI instead of cerr.
rdumusc pushed a commit to rdumusc/Deflect that referenced this pull request Aug 30, 2017
Also report stream connection errors in the GUI instead of cerr.
rdumusc pushed a commit to rdumusc/Deflect that referenced this pull request Aug 30, 2017
This bug was introduced in BlueBrain#177 and could result in the global
QThreadPool threads being locked forever.
rdumusc pushed a commit that referenced this pull request Aug 30, 2017
This bug was introduced in #177 and could result in the global
QThreadPool threads being locked forever.
rdumusc pushed a commit to rdumusc/Deflect that referenced this pull request Aug 30, 2017
Also report stream connection errors in the GUI instead of cerr.
rdumusc pushed a commit that referenced this pull request Aug 30, 2017
Also report stream connection errors in the GUI instead of cerr.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants