Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#1849] Exceptions from controllers are not detected in FunctionalTests #1246

Merged
merged 10 commits into from
Jul 31, 2018

Conversation

Fraserhardy
Copy link
Contributor

@Fraserhardy Fraserhardy commented Jul 18, 2018

Lighthouse #1849 from PR #778

Changes have been ported over from an existing PR that became out of date.
This fixes a pretty critical issue where functional tests will pass even if the controller being called throws an exception.

The new changes actually throw the exception up to the tests so that it can be handled within the test. Expected exceptions can be checked for correctly in this way.

Hendrik Schnepel and others added 10 commits December 25, 2015 14:27
# Conflicts:
#	framework/src/play/test/FunctionalTest.java
#	samples-and-tests/just-test-cases/conf/routes
#	samples-and-tests/just-test-cases/test/FunctionalTestTest.java
* master:
  [playframework#1244] doc(release): add documentation for 1.5.1
  [#1896] fix play daemon stacktrace on [re]start-stop
Fixed issue with Static test
@Test

@Test(expected = RenderStatic.class)
Copy link
Contributor Author

@Fraserhardy Fraserhardy Jul 19, 2018

Choose a reason for hiding this comment

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

The changes to how exceptions are thrown back to tests has resulted in RenderStatic.class being thrown back up to the tests in this case.

This change passes the test but I'm not 100% convinced this is the correct approach. Could someone who has more experience in how the static files are handled take a look at this please.

@hsch this PR uses your original changes from an old PR I'm attempting to get merged. Perhaps you could advise? @xael-fry could you take a look too please.

Copy link
Contributor

@asolntsev asolntsev Jul 28, 2018

Choose a reason for hiding this comment

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

@Fraserhardy @hsch Certainly, it's a bad idea to expect RenderStatic.class in this test. But it's not your fault.

There is two problems with this test:

  1. it WAS incorrect before your change. It actually didn't test anything. If only you add a line assertContentEquals("test", response); to this test, it would fail.

  2. Bad design of method play.mvc.Router.Route#matches(java.lang.String, java.lang.String, java.lang.String, java.lang.String): it has side effect. Instead of returning Map<String, String>, it sometimes throws RenderStatic. And PlayHandler handles it as a special case: catches RenderStatic and sends file content asynchronously to the browser. Disgusting. :(

What I suggest is making a similar "special case" in FunctionalTest:

        catch (ExecutionException e) {
          RuntimeException originalException = unwrapOriginalException(e);
          if (originalException instanceof RenderStatic) {
            response.status = 200;
            response.direct = ((RenderStatic) originalException).file;
          }
          else {
              throw originalException;
          }
        }

and adding a method in FuncationalTest:

    public static void assertIsStaticFile(Response response, String filePath) {
        assertIsOk(response);

        String file = (String) response.direct;
        assertEquals(filePath, file);
    }

Finally, this test should be rewritten:

    @Test
    public void testGettingStaticFile() {
	      Response response = GET("/public/session.test?req=1");
	      assertIsStaticFile(response, "public/session.test");
    }

// assertStatus(500, response);
assertTrue(Binary.errorInputStreamClosed);
try {
GET("/binary/getErrorBinary");
Copy link
Contributor

Choose a reason for hiding this comment

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

@Fraserhardy It doesn't seem to be a correct test.
You should restore assertStatus(500, response); instead of expecting Exception.class.


public class TransactionalJPATest extends FunctionalTest {

@Test
@Test(expected = TransactionRequiredException.class)
public void testImport() {
Response response = GET("/Transactional/readOnlyTest");
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did you remove few lines from the previous test? They seem to be reasonable.
Probably you should move them to a separate test method?

assertIsOk(response);	
response = GET("/Transactional/echoHowManyPosts");	
assertIsOk(response);	
assertEquals("There are 0 posts", getContent(response));

&& (executionCause instanceof JavaExecutionException || executionCause instanceof UnexpectedException)) {
final Throwable originalCause = executionCause.getCause();
if (originalCause != null && originalCause instanceof RuntimeException) {
throw (RuntimeException) originalCause;
Copy link
Contributor

Choose a reason for hiding this comment

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

This is bug. Change throw (RuntimeException) originalCause; to return (RuntimeException) originalCause;

@Test

@Test(expected = RenderStatic.class)
Copy link
Contributor

@asolntsev asolntsev Jul 28, 2018

Choose a reason for hiding this comment

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

@Fraserhardy @hsch Certainly, it's a bad idea to expect RenderStatic.class in this test. But it's not your fault.

There is two problems with this test:

  1. it WAS incorrect before your change. It actually didn't test anything. If only you add a line assertContentEquals("test", response); to this test, it would fail.

  2. Bad design of method play.mvc.Router.Route#matches(java.lang.String, java.lang.String, java.lang.String, java.lang.String): it has side effect. Instead of returning Map<String, String>, it sometimes throws RenderStatic. And PlayHandler handles it as a special case: catches RenderStatic and sends file content asynchronously to the browser. Disgusting. :(

What I suggest is making a similar "special case" in FunctionalTest:

        catch (ExecutionException e) {
          RuntimeException originalException = unwrapOriginalException(e);
          if (originalException instanceof RenderStatic) {
            response.status = 200;
            response.direct = ((RenderStatic) originalException).file;
          }
          else {
              throw originalException;
          }
        }

and adding a method in FuncationalTest:

    public static void assertIsStaticFile(Response response, String filePath) {
        assertIsOk(response);

        String file = (String) response.direct;
        assertEquals(filePath, file);
    }

Finally, this test should be rewritten:

    @Test
    public void testGettingStaticFile() {
	      Response response = GET("/public/session.test?req=1");
	      assertIsStaticFile(response, "public/session.test");
    }

asolntsev added a commit to codeborne/play that referenced this pull request Jul 31, 2018
…st RenderStatic in functional tests

P.S. it implements my comments for PR playframework#1246
asolntsev added a commit to codeborne/play that referenced this pull request Jul 31, 2018
P.S. it implements my comments for PR playframework#1246
asolntsev added a commit to codeborne/play that referenced this pull request Jul 31, 2018
…eleted in PR 1246

P.S. it implements my comments for PR playframework#1246
@asolntsev asolntsev merged commit 2410b22 into playframework:master Jul 31, 2018
@asolntsev
Copy link
Contributor

@Fraserhardy @hsch I merged your pull request and then implemented my comments in a separate PR. You can see the final version in master branch now.

@Fraserhardy
Copy link
Contributor Author

@asolntsev Thanks for your help on this. Much appreciated.

@Fraserhardy
Copy link
Contributor Author

@asolntsev Now this has been merged what steps are required to get this into a new version? I know we've just missed 1.5.1. I noticed there are a few vulnerable dependencies that have just been updated too so perhaps another release is due soon.

@asolntsev
Copy link
Contributor

@Fraserhardy Unfortunately, it's not an automated process. Typically @xael-fry does the release. It includes some additional work like preparing a documentation etc.

@xael-fry Where do you plan to make a new release?

@xael-fry
Copy link
Member

@asolntsev In september, but this one should not have been merged, modifications should have been combined in one commit.
I would have to clean it up

@xael-fry xael-fry added this to the 1.5.2 milestone Aug 22, 2018
xael-fry pushed a commit to xael-fry/play that referenced this pull request Aug 23, 2018
… deleted in PR 1246

        P.S. it implements my comments for PR playframework#1246
* [#1849]  improve design of BinaryTest
        P.S. it implements my comments for PR playframework#1246
* [#1849]  add method assertIsStaticFile() and special case allowing to test RenderStatic in functional tests
        P.S. it implements my comments for PR playframework#1246
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.

4 participants