Adding tests, fixing older tests.
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index ba125d9..de76d80 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -8,10 +8,39 @@
 use crate::gen::Opt;
 use proc_macro2::TokenStream;
 
-pub use crate::gen::{Error, Result, GeneratedCode};
+pub use crate::gen::{Error, GeneratedCode, Result};
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
 pub fn generate_header_and_cc(rust_source: TokenStream) -> Result<GeneratedCode> {
     gen::do_generate_from_tokens(rust_source, Opt::default())
 }
+
+#[cfg(test)]
+mod test {
+    use quote::quote;
+
+    #[test]
+    fn test_positive() {
+        let rs = quote! {
+            #[cxx::bridge]
+            mod ffi {
+                extern "C" {
+                    fn in_C();
+                }
+                extern "Rust" {
+                    fn in_rs();
+                }
+            }
+        };
+        let code = crate::generate_header_and_cc(rs).unwrap();
+        assert!(code.cxx.len() > 0);
+        assert!(code.header.len() > 0);
+    }
+
+    #[test]
+    fn test_negative() {
+        let rs = quote! {};
+        assert!(crate::generate_header_and_cc(rs).is_err())
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index acc7669..3139ed3 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -59,7 +59,7 @@
 ) -> std::result::Result<GeneratedCode, Error> {
     let syntax = syn::parse2::<File>(tokens)?;
     match generate(syntax, opt, true, true) {
-        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx } ),
+        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }),
         Err(err) => Err(err),
         _ => panic!("Unexpected generation"),
     }
@@ -70,14 +70,18 @@
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
     };
-    let syntax = match syn::parse_file(&source) {
+    match generate_from_string(&source, opt, header) {
         Ok(out) => out,
-        Err(err) => format_err(path, "", Error::Syn(err)),
-    };
-    match generate(syntax, opt, header, !header) {
-        Ok((Some(hdr), None)) => hdr,
-        Ok((None, Some(cxx))) => cxx,
         Err(err) => format_err(path, &source, err),
+    }
+}
+
+fn generate_from_string(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
+    let syntax = syn::parse_file(&source).map_err(Error::Syn)?;
+    let results = generate(syntax, opt, header, !header)?;
+    match results {
+        (Some(hdr), None) => Ok(hdr),
+        (None, Some(cxx)) => Ok(cxx),
         _ => panic!("Unexpected generation"),
     }
 }
diff --git a/gen/src/tests.rs b/gen/src/tests.rs
index 0e7a910..7621643 100644
--- a/gen/src/tests.rs
+++ b/gen/src/tests.rs
@@ -1,4 +1,4 @@
-use crate::gen::{generate, Opt};
+use crate::gen::{generate_from_string, Opt};
 
 const CPP_EXAMPLE: &'static str = r#"
     #[cxx::bridge]
@@ -15,7 +15,7 @@
         include: Vec::new(),
         cxx_impl_annotations: None,
     };
-    let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, opts, false).unwrap();
     let output = std::str::from_utf8(&output).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
@@ -28,7 +28,7 @@
         include: Vec::new(),
         cxx_impl_annotations: Some("ANNOTATION".to_string()),
     };
-    let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, opts, false).unwrap();
     let output = std::str::from_utf8(&output).unwrap();
     assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
 }