Skip to content

Add TestHarness, and assorted API breaking changes#1487

Merged
SimonSapin merged 28 commits intomainfrom
simon/test-harness
Aug 12, 2022
Merged

Add TestHarness, and assorted API breaking changes#1487
SimonSapin merged 28 commits intomainfrom
simon/test-harness

Conversation

@SimonSapin
Copy link
Contributor

@SimonSapin SimonSapin commented Aug 9, 2022

This PR makes a number of changes, many of them breaking. Each commit should be self-contained, though. The highlights are:

  • A new TestHarness API that replaces both PluginTestHarness (which is removed) and PluggableRouterServiceBuilder (which becomes private)
  • The above allows a number of other items to be made private, as they are no longer needed outside of the crate or appear in public signatures
  • The services module was also made private. It is replaced in the public API by a new stages module that contains sub-modules for each pipeline stage (query_planner, execution, etc) which in turn contain items like Request, BoxService, etc.
  • Some other drive-by API changes, for polish towards 1.0

For more details, see NEXT_CHANGELOG.md, apollo-router/src/test_harness.rs, and apollo-router/src/stages.rs. Much of the other changes are very mechanical.

Many choices proposed in this PR are opinionated but everything is open to discussion.

It should probably have been multiple smaller PRs. I got a bit carried away, sorry. For review I suggest going commit-by-commit.

@SimonSapin
Copy link
Contributor Author

SimonSapin commented Aug 9, 2022

For now CI will fail for (at least) two reasons:

@o0Ignition0o
Copy link
Contributor

Not sure if it's in the scope of this pr, but it would be great if we tested our plugins against a yaml! configuration instead of

        let config = serde_json::json!({
            "plugins": {
                "my_example.catch_query_planner_error": {
                    "enabled": true ,
                }
            }
        });
        apollo_router::TestHarness::builder()
            .configuration_json(config)
            .unwrap()
            .build()
            .await
            .unwrap();
    }

This would allow us to catch yml related issues earlier

@o0Ignition0o
Copy link
Contributor

o0Ignition0o commented Aug 11, 2022

                    let query_planner_response: Result<query_planner::Response, BoxError> =
                        query_planner_future.await;

@SimonSapin you spoiled me! I was expecting query_planner::Result to be available :D

@o0Ignition0o
Copy link
Contributor

Any chance we can fix the requirement of an alias while we're at it ?

use apollo_router::layers::ServiceExt;
use tower::{ServiceExt as _};

@SimonSapin
Copy link
Contributor Author

We could definitely add Result aliases!

Renaming ServiceExt too, but this PR is already big, let's do additional changes separately 😅

@SimonSapin
Copy link
Contributor Author

SimonSapin commented Aug 11, 2022

We could have a convenience builder method for TestHarness that accepts YAML, but it would have to be as a &str (so typically in a Rust string literal without syntax highlighting). serde_yaml doesn't have a macro like serde_json::json! because YAML syntax is too different from Rust syntax. json! actually takes Rust tokens as inputs, I'm sure there are edge cases where the syntax is not quite the same. It just looks close enough.

@SimonSapin SimonSapin force-pushed the simon/test-harness branch 2 times, most recently from 501574b to fe7b712 Compare August 12, 2022 12:57
@SimonSapin SimonSapin marked this pull request as ready for review August 12, 2022 12:57
@SimonSapin SimonSapin requested review from BrynCooke, Geal and o0Ignition0o and removed request for StephenBarlow August 12, 2022 13:03
Copy link
Contributor

@o0Ignition0o o0Ignition0o left a comment

Choose a reason for hiding this comment

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

LGTM!

I'd like to take a moment to acknowledge the HUGE amount of work you had to do to come up with such a big, and so well documented PR.

This one touches everything, and the same level of care and attention to detail has been given to each file, and each function.

I know I have suffered review fatigue while reading this, so I can't imagine the amount of work and concentration preparing such a changeset required. And I won't even mention the number of rebases and merge conflicts you had to go through.

Again kudos for the very nice modules and functions documentation. This is really great work!

Copy link
Contributor

Choose a reason for hiding this comment

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

tremendous effort on the changelog, that's really GREAT WORK 🎉

NIT: you can now update the PR #

Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting!

Comment on lines 108 to 118
Copy link
Contributor

Choose a reason for hiding this comment

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

great indent catch!

Copy link
Contributor

Choose a reason for hiding this comment

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

🤩

Copy link
Contributor

Choose a reason for hiding this comment

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

oh that s a leftover from the apollo-router apollo-router-core split!

Copy link
Contributor

Choose a reason for hiding this comment

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

cool!

//! Utilities which make it easy to test with [`crate::plugin`].

mod mock;
#[macro_use]
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need this ? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because we removed #[macro_export] elsewhere

Comment on lines +25 to +26
/// On the subgraph side, this test harness never makes network requests to subgraphs
/// unless [`with_subgraph_network_requests`][Self::with_subgraph_network_requests] is called.
Copy link
Contributor

Choose a reason for hiding this comment

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

neat!

Comment on lines +97 to +102
*body = stream
.map(move |mut resp| {
resp.data = mock_data.clone();
resp
})
.boxed();
Copy link
Contributor

Choose a reason for hiding this comment

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

is this why we need futures::StreamExt?

This feels a bit inconvenient, I m not sure I would assume plugin writers to be able to wield this, especially when learning rust :/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this was an ugly way to get this test to compile. I’ve added a helper in #1525

Comment on lines +379 to +411
/// Returns a builder to start an HTTP server in a separate Tokio task.
///
/// Builder methods:
///
/// * `.schema(impl Into<`[`SchemaSource`]`>)`
/// Required.
/// Specifies where to find the supergraph schema definition.
/// Some sources support hot-reloading.
///
/// * `.configuration(impl Into<`[`ConfigurationSource`]`>)`
/// Optional.
/// Specifies where to find the router configuration.
/// If not provided, the default configuration as with an empty YAML file.
///
/// * `.shutdown(impl Into<`[`ShutdownSource`]`>)`
/// Optional.
/// Specifies when the server should gracefully shut down.
/// If not provided, the default is [`ShutdownSource::CtrlC`].
///
/// * `.start()`
/// Finishes the builder,
/// starts an HTTP server in a separate Tokio task,
/// and returns a `RouterHttpServer` handle.
///
/// The server handle can be used in multiple ways.
/// As a [`Future`], it resolves to `Result<(), `[`ApolloRouterError`]`>`
/// either when the server has finished gracefully shutting down
/// or when it encounters a fatal error that prevents it from starting.
///
/// If the handle is dropped before being awaited as a future,
/// a graceful shutdown is triggered.
/// In order to wait until shutdown finishes,
/// use the [`shutdown`][Self::shutdown] method instead.
Copy link
Contributor

Choose a reason for hiding this comment

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

wow 🤩

@SimonSapin SimonSapin merged commit 622d946 into main Aug 12, 2022
@SimonSapin SimonSapin deleted the simon/test-harness branch August 12, 2022 16:22
@o0Ignition0o
Copy link
Contributor

@SimonSapin I didn't see you enabled automerge, let's followup on the comment's I ve written next week!

SimonSapin added a commit that referenced this pull request Aug 17, 2022
SimonSapin added a commit that referenced this pull request Aug 17, 2022
@Geal Geal mentioned this pull request Aug 22, 2022
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.

6 participants