[fidl][rust][transitional] Test method soft transitions

This tests three versions of interface implementations against three
versions of a FIDL library. It does that by declaring the
implementations in macros that take the name of the FIDL library module
as an argument.

The code isn't meant to actually be run - it's just to test that it
compiles correctly.

TEST=built with //garnet/packages/tests/all

Change-Id: I55bd40469c12fba8faec8a4a404fa6602ccf49ad
diff --git a/tests/fidl-changes/BUILD.gn b/tests/fidl-changes/BUILD.gn
index 4725b54..b3cb0ed 100644
--- a/tests/fidl-changes/BUILD.gn
+++ b/tests/fidl-changes/BUILD.gn
@@ -9,6 +9,7 @@
     ":cpp",
     ":fidl.test.after",
     ":fidl.test.before",
+    "rust",
   ]
 }
 
diff --git a/tests/fidl-changes/rust/BUILD.gn b/tests/fidl-changes/rust/BUILD.gn
new file mode 100644
index 0000000..067a354
--- /dev/null
+++ b/tests/fidl-changes/rust/BUILD.gn
@@ -0,0 +1,22 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/rust/rustc_binary.gni")
+
+rustc_binary("rust") {
+  name = "rust_fidl_changes_test"
+  edition = "2018"
+
+  deps = [
+    "//garnet/tests/fidl-changes:fidl.test.before-rustc",
+    "//garnet/tests/fidl-changes:fidl.test.during-rustc",
+    "//garnet/tests/fidl-changes:fidl.test.after-rustc",
+    "//garnet/public/lib/fidl/rust/fidl",
+    "//garnet/public/rust/fuchsia-app",
+    "//garnet/public/rust/fuchsia-async",
+    "//garnet/public/rust/fuchsia-zircon",
+    "//third_party/rust-crates/rustc_deps:failure",
+    "//third_party/rust-crates/rustc_deps:futures-preview",
+  ]
+}
diff --git a/tests/fidl-changes/rust/src/after.rs b/tests/fidl-changes/rust/src/after.rs
new file mode 100644
index 0000000..5b069d4
--- /dev/null
+++ b/tests/fidl-changes/rust/src/after.rs
@@ -0,0 +1,52 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This builds the version of the implementations after the change is completed against a specified FIDL library.
+macro_rules! after_impl {
+    ($name:ident, $fidl_library:ident) => {
+        struct $name();
+        impl $name {
+            async fn add_method_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::AddMethodRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    match req {
+                        $fidl_library::AddMethodRequest::ExistingMethod { .. } => {}
+                        $fidl_library::AddMethodRequest::NewMethod { .. } => {}
+                    }
+                }
+                Ok(())
+            }
+
+            async fn remove_method_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::RemoveMethodRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    match req {
+                        $fidl_library::RemoveMethodRequest::ExistingMethod { .. } => {}
+                    }
+                }
+                Ok(())
+            }
+
+            async fn add_event_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::AddEventRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    match req {
+                        $fidl_library::AddEventRequest::ExistingMethod { .. } => {}
+                    }
+                }
+                Ok(())
+            }
+
+            async fn remove_event_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::RemoveEventRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    match req {
+                        $fidl_library::RemoveEventRequest::ExistingMethod { .. } => {}
+                    }
+                }
+                Ok(())
+            }
+        }
+    };
+}
diff --git a/tests/fidl-changes/rust/src/before.rs b/tests/fidl-changes/rust/src/before.rs
new file mode 100644
index 0000000..1b519a2
--- /dev/null
+++ b/tests/fidl-changes/rust/src/before.rs
@@ -0,0 +1,52 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This builds the version of the implementations before the change is begun against a specified FIDL library.
+macro_rules! before_impl {
+    ($name:ident, $fidl_library:ident) => {
+        struct $name();
+        impl $name {
+            async fn add_method_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::AddMethodRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    match req {
+                        $fidl_library::AddMethodRequest::ExistingMethod { .. } => {}
+                    }
+                }
+                Ok(())
+            }
+
+            async fn remove_method_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::RemoveMethodRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    match req {
+                        $fidl_library::RemoveMethodRequest::ExistingMethod { .. } => {}
+                        $fidl_library::RemoveMethodRequest::OldMethod { .. } => {}
+                    }
+                }
+                Ok(())
+            }
+
+            async fn add_event_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::AddEventRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    match req {
+                        $fidl_library::AddEventRequest::ExistingMethod { .. } => {}
+                    }
+                }
+                Ok(())
+            }
+
+            async fn remove_event_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::RemoveEventRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    match req {
+                        $fidl_library::RemoveEventRequest::ExistingMethod { .. } => {}
+                    }
+                }
+                Ok(())
+            }
+        }
+    };
+}
diff --git a/tests/fidl-changes/rust/src/during.rs b/tests/fidl-changes/rust/src/during.rs
new file mode 100644
index 0000000..cf3b462
--- /dev/null
+++ b/tests/fidl-changes/rust/src/during.rs
@@ -0,0 +1,59 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This builds the version of the implementations with the change pre-flighting against a specified FIDL library.
+macro_rules! during_impl {
+    ($name:ident, $fidl_library:ident) => {
+        struct $name();
+        impl $name {
+            async fn add_method_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::AddMethodRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    #![allow(unreachable_patterns)]
+                    match req {
+                        $fidl_library::AddMethodRequest::ExistingMethod { .. } => {}
+                        _ => {}
+                    }
+                }
+                Ok(())
+            }
+
+            async fn remove_method_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::RemoveMethodRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    #![allow(unreachable_patterns)]
+                    match req {
+                        $fidl_library::RemoveMethodRequest::ExistingMethod { .. } => {}
+                        _ => {}
+                    }
+                }
+                Ok(())
+            }
+
+            async fn add_event_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::AddEventRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    #![allow(unreachable_patterns)]
+                    match req {
+                        $fidl_library::AddEventRequest::ExistingMethod { .. } => {}
+                        _ => {}
+                    }
+                }
+                Ok(())
+            }
+
+            async fn remove_event_service(chan: fasync::Channel) -> Result<(), fidl::Error> {
+                let mut stream = $fidl_library::RemoveEventRequestStream::from_channel(chan);
+                while let Some(req) = await!(stream.try_next())? {
+                    #![allow(unreachable_patterns)]
+                    match req {
+                        $fidl_library::RemoveEventRequest::ExistingMethod { .. } => {}
+                        _ => {}
+                    }
+                }
+                Ok(())
+            }
+        }
+    };
+}
diff --git a/tests/fidl-changes/rust/src/main.rs b/tests/fidl-changes/rust/src/main.rs
new file mode 100644
index 0000000..4c0282e
--- /dev/null
+++ b/tests/fidl-changes/rust/src/main.rs
@@ -0,0 +1,33 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#![feature(futures_api, async_await, await_macro)]
+#![allow(dead_code)]
+
+use fidl::endpoints::RequestStream;
+use fidl_fidl_test_after as after_fidl;
+use fidl_fidl_test_before as before_fidl;
+use fidl_fidl_test_during as during_fidl;
+use fuchsia_async as fasync;
+use futures::prelude::*;
+
+#[macro_use]
+mod before;
+#[macro_use]
+mod during;
+#[macro_use]
+mod after;
+
+// Test that the original code compiles against the original library.
+before_impl!(BeforeBefore, before_fidl);
+// Test that the pre-flighted code compiles against the original library.
+during_impl!(DuringBefore, before_fidl);
+// Test that the pre-flighted code compiles against the transitional library.
+during_impl!(DuringDuring, during_fidl);
+// Test that the pre-flighted code compiles against the final library.
+during_impl!(DuringAfter, after_fidl);
+// Test that the final code compiles against the final library.
+after_impl!(AfterAfter, after_fidl);
+
+fn main() {}