Merge branch 'docs-for-process-trackers' of ssh://github.com/tinygrasshopper/gomega into tinygrasshopper-docs-for-process-trackers
diff --git a/_config.yml b/_config.yml
index 71cbd2a..48c3f66 100644
--- a/_config.yml
+++ b/_config.yml
@@ -1,5 +1,5 @@
 baseurl: /gomega
 safe: true
 lsi: false
-highlighter: pygments
+highlighter: rouge
 markdown: kramdown
diff --git a/_includes/gomega_sidebar.html b/_includes/gomega_sidebar.html
index 9c6f55b..e7e05f9 100644
--- a/_includes/gomega_sidebar.html
+++ b/_includes/gomega_sidebar.html
@@ -58,7 +58,7 @@
                         <a href="#beequivalenttoexpected-interface"><code>BeEquivalentTo(...)</code></a>
                     </li>
                     <li>
-                        <a href="#beidenticaltoexpected-interface"><code>BeIdenticalToTo(...)</code></a>
+                        <a href="#beidenticaltoexpected-interface"><code>BeIdenticalTo(...)</code></a>
                     </li>
                     <li>
                         <a href="#beassignabletotypeofexpected-interface"><code>BeAssignableToTypeOf(...)</code></a>
@@ -136,7 +136,7 @@
             </li>
 
             <li>
-                <a href="#working-with-strings-and-json">Working with Strings and JSON</a>
+                <a href="#working-with-strings-json-and-yaml">Working with Strings, JSON and YAML</a>
                 <ul class="nav">
                     <li>
                         <a href="#containsubstringsubstr-string-args-interface"><code>ContainSubstring(...)</code></a>
@@ -153,6 +153,9 @@
                     <li>
                         <a href="#matchjsonjson-interface"><code>MatchJSON(...)</code></a>
                     </li>
+                    <li>
+                        <a href="#matchyamlyaml-interface"><code>MatchYAML(...)</code></a>
+                    </li>
                 </ul>
             </li>
 
@@ -249,4 +252,8 @@
         <a href="#gexec-testing-external-processes"><code>gexec</code>: Testing External Processes
         </a>
     </li>
+    <li>
+        <a href="#gstruct-testing-complex-data-types"><code>gstruct</code>: Testing Complex Data Types
+        </a>
+    </li>
 </ul>
diff --git a/index.md b/index.md
index 83fe1ce..29dd6e6 100644
--- a/index.md
+++ b/index.md
@@ -94,7 +94,7 @@
 
 This will only pass if the return value of `DoSomethingHard()` is `("foo", nil)`.
 
-Additionally, if you call a function with a single `error` return value you can use the `Succeed` matcher to asser the function has returned without error.  So for a function of the form:
+Additionally, if you call a function with a single `error` return value you can use the `Succeed` matcher to assert the function has returned without error.  So for a function of the form:
 
     func DoSomethingSimple() error {
         ...
@@ -280,7 +280,7 @@
 
 This makes your tests more expressive and reduces boilerplate.  However, when an assertion in the helper fails the line numbers provided by Gomega are unhelpful.  Instead of pointing you to the line in your test that failed, they point you the line in the helper.
 
-To get around this, Gomega provides versions of `Expect`, `Eventually` and `Consistently` named `ExpectWithOffset`, `EventuallyWithOffset` and `ConsistentlyWithOffset` that allow you to specify an *offset* in the callstack.  The offset is the first argument to these functions.
+To get around this, Gomega provides versions of `Expect`, `Eventually` and `Consistently` named `ExpectWithOffset`, `EventuallyWithOffset` and `ConsistentlyWithOffset` that allow you to specify an *offset* in the call stack.  The offset is the first argument to these functions.
 
 With this, we can rewrite our helper as:
 
@@ -302,6 +302,8 @@
 
 Gomega comes with a bunch of `GomegaMatcher`s.  They're all documented here.  If there's one you'd like to see written either [send a pull request or open an issue](http://github.com/onsi/gomega).
 
+A number of community-supported matchers have appeared as well.  A list is maintained on the Gomega [wiki](https://github.com/onsi/gomega/wiki).
+
 These docs only go over the positive assertion case (`Should`), the negative case (`ShouldNot`) is simply the negation of the positive case.  They also use the `Ω` notation, but - as mentioned above - the `Expect` notation is equivalent.
 
 ### Asserting Equivalence
@@ -473,7 +475,7 @@
 
 Of course, this could have been written as `receivedBagel := <-bagelChan` - however using `Receive` makes it easy to avoid hanging the test suite should nothing ever come down the channel.
 
-Finally, `Receive` *never* blocks.  `Eventually(c).Should(Receive())` repeatedly polls `c` in a non-blocking fashion.  That means that you cannot use this pattern to verify that a *non-blocking send* has occured on the channel - [more details at this GitHub issue](https://github.com/onsi/gomega/issues/82).
+Finally, `Receive` *never* blocks.  `Eventually(c).Should(Receive())` repeatedly polls `c` in a non-blocking fashion.  That means that you cannot use this pattern to verify that a *non-blocking send* has occurred on the channel - [more details at this GitHub issue](https://github.com/onsi/gomega/issues/82).
 
 #### BeSent(value interface{})
 
@@ -517,7 +519,7 @@
 
 `ACTUAL` must be a string representing the filepath.
 
-### Working with Strings and JSON
+### Working with Strings, JSON and YAML
 
 #### ContainSubstring(substr string, args ...interface{})
 
@@ -575,6 +577,14 @@
 
 It is an error for either `ACTUAL` or `EXPECTED` to be invalid JSON.
 
+#### MatchYAML(yaml interface{})
+
+    Ω(ACTUAL).Should(MatchYAML(EXPECTED))
+
+Both `ACTUAL` and `EXPECTED` must be a `string`, `[]byte` or a `Stringer`.  `MatchYAML` succeeds if both `ACTUAL` and `EXPECTED` are YAML representations of the same object.  This is verified by parsing both `ACTUAL` and `EXPECTED` and then asserting equality on the resulting objects with `reflect.DeepEqual`.  By doing this `MatchYAML` avoids any issues related to white space, formatting, and key-ordering.
+
+It is an error for either `ACTUAL` or `EXPECTED` to be invalid YAML.
+
 ### Working with Collections
 
 #### BeEmpty()
@@ -615,7 +625,7 @@
     Ω(ACTUAL).Should(
         ConsistOf([]SOME_TYPE{ELEMENT1, ELEMENT2, ELEMENT3, ...}))
 
-succeeds if `ACTUAL` contains preciely the elements passed into the matcher. The ordering of the elements does not matter.
+succeeds if `ACTUAL` contains precisely the elements passed into the matcher. The ordering of the elements does not matter.
 
 By default `ConsistOf()` uses `Equal()` to match the elements, however custom matchers can be passed in instead.  Here are some examples:
 
@@ -871,7 +881,7 @@
 
 Let's break this down:
 
-- Most matchers have a constructor function that returns an instance of the matcher.  In this case we've created `RepresentJSONifiedObject`.  Where possible, your constructor function should take explicit types or interfaces.  For our usecase, however, we need to accept any possible expected type so `RepresentJSONifiedObject` takes an argument with the generic `interface{}` type.
+- Most matchers have a constructor function that returns an instance of the matcher.  In this case we've created `RepresentJSONifiedObject`.  Where possible, your constructor function should take explicit types or interfaces.  For our use case, however, we need to accept any possible expected type so `RepresentJSONifiedObject` takes an argument with the generic `interface{}` type.
 - The constructor function then initializes and returns an instance of our matcher: the `representJSONMatcher`.  These rarely need to be exported outside of your matcher package.
 - The `representJSONMatcher` must satisfy the `GomegaMatcher` interface.  It does this by implementing the `Match`, `FailureMessage`, and `NegatedFailureMessage` method:
     - If the `GomegaMatcher` receives invalid inputs `Match` returns a non-nil error explaining the problems with the input.  This allows Gomega to fail the assertion whether the assertion is for the positive or negative case.
@@ -882,7 +892,7 @@
     - It is guaranteed that `FailureMessage` and `NegatedFailureMessage` will only be called *after* `Match`, so you can save off any state you need to compute the messages in `Match`.
 - Finally, it is common for matchers to make extensive use of the `reflect` library to interpret the generic inputs they receive.  In this case, the `representJSONMatcher` goes through some `reflect` gymnastics to create a pointer to a new object with the same type as the `expected` object, read and decode JSON from `actual` into that pointer, and then deference the pointer and compare the result to the `expected` object.
 
-You might testdrive this matcher while writing it using Ginkgo.  Your test might look like:
+You might test drive this matcher while writing it using Ginkgo.  Your test might look like:
 
     package json_response_matcher_test
 
@@ -988,7 +998,7 @@
 
     Eventually(myChannel).Should(Receive(Equal("bar")))
 
-`Eventually` will repeatedly invoke the `Receive` matcher against `myChannel` until the match succeeds.  However, if the channel becomes *closed* there is *no way* for the match to ever succeed.  Allowing `Eventually` to conitnue polling is inefficient and slows the test suite down.
+`Eventually` will repeatedly invoke the `Receive` matcher against `myChannel` until the match succeeds.  However, if the channel becomes *closed* there is *no way* for the match to ever succeed.  Allowing `Eventually` to continue polling is inefficient and slows the test suite down.
 
 To get around this, a matcher can optionally implement:
 
@@ -1004,7 +1014,7 @@
 
 `Eventually` will not block for 30 seconds but will return (and fail, correctly) as soon as the mismatched exit code arrives!
 
-> Note: `Eventually` and `Consistently` only excercise the `MatchMayChangeInTheFuture` method *if* they are passed a bare value.  If they are passed functions to be polled it is not possible to guarantee that the return value of the function will not change between polling intervals.  In this case, `MatchMayChangeInTheFuture` is not called and the polling continues until either a match is found or the timeout elapses.
+> Note: `Eventually` and `Consistently` only exercise the `MatchMayChangeInTheFuture` method *if* they are passed a bare value.  If they are passed functions to be polled it is not possible to guarantee that the return value of the function will not change between polling intervals.  In this case, `MatchMayChangeInTheFuture` is not called and the polling continues until either a match is found or the timeout elapses.
 
 ### Contributing to Gomega
 
@@ -1012,7 +1022,7 @@
 
 When adding a new matcher please mimic the style use in Gomega's current matchers: you should use the `format` package to format your output, put the matcher and its tests in the `matchers` package, and the constructor in the `matchers.go` file in the top-level package.
 
-## `ghttp`: Testing HTTP CLients
+## `ghttp`: Testing HTTP Clients
 The `ghttp` package provides support for testing http *clients*.  The typical pattern in Go for testing http clients entails spinning up an `httptest.Server` using the `net/http/httptest` package and attaching test-specific handlers that perform assertions.
 
 `ghttp` provides `ghttp.Server` - a wrapper around `httptest.Server` that allows you to easily build up a stack of test handlers.  These handlers make assertions against the incoming request and return a pre-fabricated response.  `ghttp` provides a number of prebuilt handlers that cover the most common assertions.  You can combine these handlers to build out full-fledged assertions that test multiple aspects of the incoming requests.
@@ -1403,7 +1413,7 @@
 
 To bring it all together: there are three ways to instruct a `ghttp` server to handle requests: you can map routes to handlers using `RouteToHandler`, you can append handlers via `AppendHandlers`, and you can `AllowUnhandledRequests` and specify an `UnhandledRequestStatusCode`.
 
-When a `ghttp` server receives a request it first checks against the set of handlers registred via `RouteToHandler` if there is no such handler it proceeds to pop an `AppendHandlers` handler off the stack, if the stack of ordered handlers is empty, it will check whether `AllowUnhandledRequests` is `true` or `false`.  If `false` the test fails.  If `true`, a response is sent with `UnhandledRequestStatusCode`.
+When a `ghttp` server receives a request it first checks against the set of handlers registered via `RouteToHandler` if there is no such handler it proceeds to pop an `AppendHandlers` handler off the stack, if the stack of ordered handlers is empty, it will check whether `AllowUnhandledRequests` is `true` or `false`.  If `false` the test fails.  If `true`, a response is sent with `UnhandledRequestStatusCode`.
 
 ## `gbytes`: Testing Streaming Buffers
 
@@ -1436,7 +1446,7 @@
         })
     })
 
-These assertions will only pass if the strings passed to `Say` (which are interpreted as regular expressions - make sure to escape characters appropriately!) appear in the buffer.  An opaque read cursor (that you cannot access or modify) is fastforwarded as succesful assertions are made. So, for example:
+These assertions will only pass if the strings passed to `Say` (which are interpreted as regular expressions - make sure to escape characters appropriately!) appear in the buffer.  An opaque read cursor (that you cannot access or modify) is fast-forwarded as successful assertions are made. So, for example:
 
     Eventually(buffer).Should(gbytes.Say(`reticulating splines`))
     Consistently(buffer).ShouldNot(gbytes.Say(`reticulating splines`))
@@ -1469,11 +1479,11 @@
         buffer.CancelDetects()
     }
 
-`buffer.Detect` takes a string (interpreted as a regular expression) and returns a channel that will fire *once* if the requested string is detected.  Upon detection, the buffer's opaque read cursor is fastforwarded so subsequent uses of `gbytes.Say` will pick up from where the succeeding `Detect` left off.  You *must* call `buffer.CancelDetects()` to clean up afterwards (`buffer` spawns one goroutine per call to `Detect`).
+`buffer.Detect` takes a string (interpreted as a regular expression) and returns a channel that will fire *once* if the requested string is detected.  Upon detection, the buffer's opaque read cursor is fast-forwarded so subsequent uses of `gbytes.Say` will pick up from where the succeeding `Detect` left off.  You *must* call `buffer.CancelDetects()` to clean up afterwards (`buffer` spawns one goroutine per call to `Detect`).
 
 ## `gexec`: Testing External Processes
 
-`gexec` simplifies testing external processes.  It can help you [compile go binaries](#compiling-external-binaries), [start external processes](#starting-external-processes), [send signals and wait for them to exit](#sending-signals-and-waiting-for-the-process-to-exit), make [assertions agains the exit code](#asserting-against-exit-code), and stream output into `gbytes.Buffer`s to allow you [make assertions against output](#making-assertions-against-the-process-output).
+`gexec` simplifies testing external processes.  It can help you [compile go binaries](#compiling-external-binaries), [start external processes](#starting-external-processes), [send signals and wait for them to exit](#sending-signals-and-waiting-for-the-process-to-exit), make [assertions against the exit code](#asserting-against-exit-code), and stream output into `gbytes.Buffer`s to allow you [make assertions against output](#making-assertions-against-the-process-output).
 
 ### Compiling external binaries
 
@@ -1505,7 +1515,7 @@
 
 `gexec.Start` calls `command.Start` for you and forwards the command's `stdout` and `stderr` to `io.Writer`s that you provide. In the code above, we pass in Ginkgo's `GinkgoWriter`.  This makes working with external processes quite convenient: when a test passes no output is printed to screen, however if a test fails then any output generated by the command will be provided.
 
-> If you want to see all your ouput regardless of test status, just run `ginkgo` in verbose mode (`-v`) - now everything written to `GinkgoWriter` makes it onto the screen.
+> If you want to see all your output regardless of test status, just run `ginkgo` in verbose mode (`-v`) - now everything written to `GinkgoWriter` makes it onto the screen.
 
 ### Sending signals and waiting for the process to exit
 
@@ -1563,12 +1573,12 @@
     Eventually(session.Out).Should(gbytes.Say("hello [A-Za-z], nice to meet you"))
     Eventually(session.Err).Should(gbytes.Say("oops!"))
 
-Since `gexec.Session` is a `gbytes.BufferProvider` that provides the `Out` buffer you can write assertions against `stdout` ouptut like so:
+Since `gexec.Session` is a `gbytes.BufferProvider` that provides the `Out` buffer you can write assertions against `stdout` output like so:
 
     Eventually(session).Should(gbytes.Say("hello [A-Za-z], nice to meet you"))
 
 Using the `Say` matcher is convenient when making *ordered* assertions against a stream of data generated by a live process.  Sometimes, however, all you need is to
-wait for the process to exit and then make assertions against the entire contents of its output.  Since `Wait()` returns `session` you can wait for the process to exit, then grab all its stdout as a `[]byte` buffer with a simple oneliner:
+wait for the process to exit and then make assertions against the entire contents of its output.  Since `Wait()` returns `session` you can wait for the process to exit, then grab all its stdout as a `[]byte` buffer with a simple one-liner:
 
     Ω(session.Wait().Out.Contents()).Should(ContainSubstring("finished successfully"))
 
@@ -1603,3 +1613,129 @@
 Due to the global nature of these methods, keep in mind that signaling processes will affect all processes started by `gexec`, in any context. For example if these methods where used in an `AfterEach`, then processes started in `BeforeSuite` would also be signaled.
 
 ---
+
+## `gstruct`: Testing Complex Data Types
+
+`gstruct` simplifies testing large and nested structs and slices. It is used for building up complex matchers that apply different tests to each field or element.
+
+### Testing type `struct`
+
+`gstruct` provides the `FieldsMatcher` through the `MatchAllFields` and `MatchFields` functions for applying a separate matcher to each field of a struct:
+
+    actual := struct{
+        A int
+        B bool
+        C string
+    }{5, true, "foo"}
+    Expect(actual).To(MatchAllFields(Fields{
+        "A": BeNumerically("<", 10),
+        "B": BeTrue(),
+        "C": Equal("foo"),
+    })
+
+`MatchAllFields` requires that every field is matched, and each matcher is mapped to a field. To match a subset or superset of a struct, you should use the `MatchFields` function with the `IgnoreExtras` and `IgnoreMissing` options. `IgnoreExtras` will ignore fields that don't map to a matcher, e.g.
+
+    Expect(actual).To(MatchFields(IgnoreExtras, Fields{
+        "A": BeNumerically("<", 10),
+        "B": BeTrue(),
+        // Ignore lack of "C" in the matcher.
+    })
+
+`IgnoreMissing` will ignore matchers that don't map to a field, e.g.
+
+    Expect(actual).To(MatchFields(IgnoreExtras, Fields{
+        "A": BeNumerically("<", 10),
+        "B": BeTrue(),
+        "C": Equal("foo"),
+        "D": Equal("bar"), // Ignored, since actual.D does not exist.
+    })
+
+The options can be combined with the binary or: `IgnoreMissing|IgnoreExtras`.
+
+### Testing type slice
+
+`gstruct` provides the `ElementsMatcher` through the `MatchAllElements` and `MatchElements` function for applying a separate matcher to each element, identified by an `Identifier` function:
+
+    actual := []string{
+        "A: foo bar baz",
+        "B: once upon a time",
+        "C: the end",
+    }
+    id := func(element interface{}) {
+        return element.(string)[0]
+    }
+    Expect(actual).To(MatchAllElements(id, Elements{
+        "A": Not(BeZero()),
+        "B": MatchRegexp("[A-Z]: [a-z ]+"),
+        "C": ContainSubstring("end"),
+    })
+
+`MatchAllElements` requires that there is a 1:1 mapping from every element to every matcher. To match a subset or superset of elements, you should use the `MatchElements` function with the `IgnoreExtras` and `IgnoreMissing` options. `IgnoreExtras` will ignore elements that don't map to a matcher, e.g.
+
+    Expect(actual).To(MatchElements(IgnoreExtras, Fields{
+        "A": Not(BeZero()),
+        "B": MatchRegexp("[A-Z]: [a-z ]+"),
+        // Ignore lack of "C" in the matcher.
+    })
+
+`IgnoreMissing` will ignore matchers that don't map to an element, e.g.
+
+    Expect(actual).To(MatchFields(IgnoreExtras, Fields{
+        "A": Not(BeZero()),
+        "B": MatchRegexp("[A-Z]: [a-z ]+"),
+        "C": ContainSubstring("end"),
+        "D": Equal("bar"), // Ignored, since actual.D does not exist.
+    })
+
+The options can be combined with the binary or: `IgnoreMissing|IgnoreExtras`.
+
+### Testing pointer values
+
+`gstruct` provides the `PointTo` function to apply a matcher to the value pointed-to. It will fail if the pointer value is `nil`:
+
+    foo := 5
+    Expect(&foo).To(PointTo(Equal(5)))
+    var bar *int
+    Expect(bar).NotTo(PointTo(BeNil()))
+
+### Putting it all together: testing complex structures
+
+The `gsturct` matchers are intended to be composable, and can be combined to apply fuzzy-matching to large and deeply nested structures. The additional `Ignore()` and `Reject()` matchers are provided for ignoring (always succeed) fields and elements, or rejecting (always fail) fields and elements.
+
+Example:
+
+    coreID := func(element interface{}) string {
+        return strconv.Itoa(element.(CoreStats).Index)
+    }
+    Expect(actual).To(MatchAllFields(Fields{
+	    "Name":      Ignore(),
+		"StartTime": BeTemporally(">=", time.Now().Add(-100 * time.Hour)),
+		"CPU": PointTo(MatchAllFields(Fields{
+			"Time":                 BeTemporally(">=", time.Now().Add(-time.Hour)),
+			"UsageNanoCores":       BeNumerically("~", 1E9, 1E8),
+			"UsageCoreNanoSeconds": BeNumerically(">", 1E6),
+            "Cores": MatchElements(coreID, IgnoreExtras, Elements{
+                "0": MatchAllFields(Fields{
+                    Index: Ignore(),
+	                "UsageNanoCores":       BeNumerically("<", 1E9),
+	                "UsageCoreNanoSeconds": BeNumerically(">", 1E5),
+                }),
+                "1": MatchAllFields(Fields{
+                    Index: Ignore(),
+	                "UsageNanoCores":       BeNumerically("<", 1E9),
+	                "UsageCoreNanoSeconds": BeNumerically(">", 1E5),
+                }),
+            }),
+		})),
+		"Memory": PointTo(MatchAllFields(Fields{
+			"Time": BeTemporally(">=", time.Now().Add(-time.Hour)),
+			"AvailableBytes":  BeZero(),
+			"UsageBytes":      BeNumerically(">", 5E6),
+			"WorkingSetBytes": BeNumerically(">", 5E6),
+			"RSSBytes":        BeNumerically("<", 1E9),
+			"PageFaults":      BeNumerically("~", 1000, 100),
+			"MajorPageFaults": BeNumerically("~", 100, 50),
+		})),
+		"Rootfs":             m.Ignore(),
+		"Logs":               m.Ignore(),
+	}))