// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ package display import ( "io" "net" "os" "reflect" "sync" "testing" "gopl.io/ch7/eval" ) // NOTE: we can't use !+..!- comments to excerpt these tests // into the book because it defeats the Example mechanism, // which requires the // Output comment to be at the end // of the function. func Example_expr() { e, _ := eval.Parse("sqrt(A / pi)") Display("e", e) // Output: // Display e (eval.call): // e.fn = "sqrt" // e.args[0].type = eval.binary // e.args[0].value.op = 47 // e.args[0].value.x.type = eval.Var // e.args[0].value.x.value = "A" // e.args[0].value.y.type = eval.Var // e.args[0].value.y.value = "pi" } func Example_slice() { Display("slice", []*int{new(int), nil}) // Output: // Display slice ([]*int): // (*slice[0]) = 0 // slice[1] = nil } func Example_nilInterface() { var w io.Writer Display("w", w) // Output: // Display w (): // w = invalid } func Example_ptrToInterface() { var w io.Writer Display("&w", &w) // Output: // Display &w (*io.Writer): // (*&w) = nil } func Example_struct() { Display("x", struct{ x interface{} }{3}) // Output: // Display x (struct { x interface {} }): // x.x.type = int // x.x.value = 3 } func Example_interface() { var i interface{} = 3 Display("i", i) // Output: // Display i (int): // i = 3 } func Example_ptrToInterface2() { var i interface{} = 3 Display("&i", &i) // Output: // Display &i (*interface {}): // (*&i).type = int // (*&i).value = 3 } func Example_array() { Display("x", [1]interface{}{3}) // Output: // Display x ([1]interface {}): // x[0].type = int // x[0].value = 3 } func Example_movie() { //!+movie type Movie struct { Title, Subtitle string Year int Color bool Actor map[string]string Oscars []string Sequel *string } //!-movie //!+strangelove strangelove := Movie{ Title: "Dr. Strangelove", Subtitle: "How I Learned to Stop Worrying and Love the Bomb", Year: 1964, Color: false, Actor: map[string]string{ "Dr. Strangelove": "Peter Sellers", "Grp. Capt. Lionel Mandrake": "Peter Sellers", "Pres. Merkin Muffley": "Peter Sellers", "Gen. Buck Turgidson": "George C. Scott", "Brig. Gen. Jack D. Ripper": "Sterling Hayden", `Maj. T.J. "King" Kong`: "Slim Pickens", }, Oscars: []string{ "Best Actor (Nomin.)", "Best Adapted Screenplay (Nomin.)", "Best Director (Nomin.)", "Best Picture (Nomin.)", }, } //!-strangelove Display("strangelove", strangelove) // We don't use an Output: comment since displaying // a map is nondeterministic. /* //!+output Display strangelove (display.Movie): strangelove.Title = "Dr. Strangelove" strangelove.Subtitle = "How I Learned to Stop Worrying and Love the Bomb" strangelove.Year = 1964 strangelove.Color = false strangelove.Actor["Gen. Buck Turgidson"] = "George C. Scott" strangelove.Actor["Brig. Gen. Jack D. Ripper"] = "Sterling Hayden" strangelove.Actor["Maj. T.J. \"King\" Kong"] = "Slim Pickens" strangelove.Actor["Dr. Strangelove"] = "Peter Sellers" strangelove.Actor["Grp. Capt. Lionel Mandrake"] = "Peter Sellers" strangelove.Actor["Pres. Merkin Muffley"] = "Peter Sellers" strangelove.Oscars[0] = "Best Actor (Nomin.)" strangelove.Oscars[1] = "Best Adapted Screenplay (Nomin.)" strangelove.Oscars[2] = "Best Director (Nomin.)" strangelove.Oscars[3] = "Best Picture (Nomin.)" strangelove.Sequel = nil //!-output */ } // This test ensures that the program terminates without crashing. func Test(t *testing.T) { // Some other values (YMMV) Display("os.Stderr", os.Stderr) // Output: // Display os.Stderr (*os.File): // (*(*os.Stderr).file).fd = 2 // (*(*os.Stderr).file).name = "/dev/stderr" // (*(*os.Stderr).file).nepipe = 0 var w io.Writer = os.Stderr Display("&w", &w) // Output: // Display &w (*io.Writer): // (*&w).type = *os.File // (*(*(*&w).value).file).fd = 2 // (*(*(*&w).value).file).name = "/dev/stderr" // (*(*(*&w).value).file).nepipe = 0 var locker sync.Locker = new(sync.Mutex) Display("(&locker)", &locker) // Output: // Display (&locker) (*sync.Locker): // (*(&locker)).type = *sync.Mutex // (*(*(&locker)).value).state = 0 // (*(*(&locker)).value).sema = 0 Display("locker", locker) // Output: // Display locker (*sync.Mutex): // (*locker).state = 0 // (*locker).sema = 0 // (*(&locker)) = nil locker = nil Display("(&locker)", &locker) // Output: // Display (&locker) (*sync.Locker): // (*(&locker)) = nil ips, _ := net.LookupHost("golang.org") Display("ips", ips) // Output: // Display ips ([]string): // ips[0] = "173.194.68.141" // ips[1] = "2607:f8b0:400d:c06::8d" // Even metarecursion! (YMMV) Display("rV", reflect.ValueOf(os.Stderr)) // Output: // Display rV (reflect.Value): // (*rV.typ).size = 8 // (*rV.typ).ptrdata = 8 // (*rV.typ).hash = 871609668 // (*rV.typ)._ = 0 // ... // a pointer that points to itself type P *P var p P p = &p if false { Display("p", p) // Output: // Display p (display.P): // ...stuck, no output... } // a map that contains itself type M map[string]M m := make(M) m[""] = m if false { Display("m", m) // Output: // Display m (display.M): // ...stuck, no output... } // a slice that contains itself type S []S s := make(S, 1) s[0] = s if false { Display("s", s) // Output: // Display s (display.S): // ...stuck, no output... } // a linked list that eats its own tail type Cycle struct { Value int Tail *Cycle } var c Cycle c = Cycle{42, &c} if false { Display("c", c) // Output: // Display c (display.Cycle): // c.Value = 42 // (*c.Tail).Value = 42 // (*(*c.Tail).Tail).Value = 42 // ...ad infinitum... } }