// This example demonstrates how to use ConfigState.Printf to display a variable // with a format string and inline formatting. func ExampleConfigState_Printf() { // See the top-level Dump example for details on the types used in this // example. // Create two ConfigState instances and modify the method handling of the // first ConfigState only. scs := spew.NewDefaultConfig() scs2 := spew.NewDefaultConfig() scs.DisableMethods = true // Alternatively // scs := spew.ConfigState{Indent: " ", DisableMethods: true} // scs2 := spew.ConfigState{Indent: " "} // This is of type Flag which implements a Stringer and has raw value 1. f := flagTwo // Dump using the ConfigState instances. scs.Printf("f: %v\n", f) scs2.Printf("f: %v\n", f) // Output: // f: 1 // f: flagTwo }
func main() { flag.Parse() if len(flag.Args()) != 1 { log.Fatal("Usage: go run goprint.go path") } bpkg, err := build.Default.Import(flag.Args()[0], ".", 0) if err != nil { log.Fatal(err) } fset := token.NewFileSet() files := make(map[string]*ast.File) for _, fname := range bpkg.GoFiles { p, err := ioutil.ReadFile(filepath.Join(bpkg.SrcRoot, bpkg.ImportPath, fname)) if err != nil { log.Fatal(err) } file, err := parser.ParseFile(fset, fname, p, parser.ParseComments) if err != nil { log.Fatal(err) } files[fname] = file } c := spew.NewDefaultConfig() c.DisableMethods = true apkg, _ := ast.NewPackage(fset, files, importer, nil) c.Dump(apkg) ast.Print(fset, apkg) dpkg := doc.New(apkg, bpkg.ImportPath, 0) c.Dump(dpkg) }
func initSpewTests() { // Config states with various settings. scsDefault := spew.NewDefaultConfig() scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true} scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true} scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1} // Variables for tests on types which implement Stringer interface with and // without a pointer receiver. ts := stringer("test") tps := pstringer("test") // depthTester is used to test max depth handling for structs, array, slices // and maps. type depthTester struct { ic indirCir1 arr [1]string slice []string m map[string]int } dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"}, map[string]int{"one": 1}} spewTests = []spewTest{ {scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"}, {scsDefault, fCSFprint, "", int16(32767), "32767"}, {scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"}, {scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"}, {scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"}, {scsDefault, fCSPrintln, "", uint8(255), "255\n"}, {scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"}, {scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"}, {scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"}, {scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"}, {scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"}, {scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"}, {scsDefault, fFprint, "", float32(3.14), "3.14"}, {scsDefault, fFprintln, "", float64(6.28), "6.28\n"}, {scsDefault, fPrint, "", true, "true"}, {scsDefault, fPrintln, "", false, "false\n"}, {scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"}, {scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"}, {scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"}, {scsNoMethods, fCSFprint, "", ts, "test"}, {scsNoMethods, fCSFprint, "", &ts, "<*>test"}, {scsNoMethods, fCSFprint, "", tps, "test"}, {scsNoMethods, fCSFprint, "", &tps, "<*>test"}, {scsNoPmethods, fCSFprint, "", ts, "stringer test"}, {scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"}, {scsNoPmethods, fCSFprint, "", tps, "test"}, {scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"}, {scsMaxDepth, fCSFprint, "", dt, "{{<max>} [<max>] [<max>] map[<max>]}"}, {scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" + " ic: (spew_test.indirCir1) {\n <max depth reached>\n },\n" + " arr: ([1]string) {\n <max depth reached>\n },\n" + " slice: ([]string) {\n <max depth reached>\n },\n" + " m: (map[string]int) {\n <max depth reached>\n }\n}\n"}, } }
func main() { defer glog.Flush() diffConfig := &dm.DifferencerConfig{} diffConfig.CreateFlags(flag.CommandLine) flag.Parse() // Scan the arguments list goioutil.InitGOMAXPROCS() cfg := spew.NewDefaultConfig() cfg.SortKeys = true cfg.Dump("Spew config:\n", cfg) cmd := filepath.Base(os.Args[0]) glog.V(1).Infoln("cmd =", cmd) ctrl := GoRtnCntrl{ stopCh: make(chan bool), wg: &sync.WaitGroup{}, } var stats dm.LeadingWhitespaceStatistics fileCh := make(chan *dm.File, runtime.NumCPU()) ctrl.wg.Add(1) go collectStats(fileCh, &stats, ctrl) textFileCh := make(chan string, runtime.NumCPU()) ctrl.wg.Add(1) go readAllFiles(runtime.NumCPU(), textFileCh, fileCh, ctrl) ftiCtrl := ctrl ftiCtrl.wg = &sync.WaitGroup{} ftiMgr := MakeFileTypeInfoManager(ftiCtrl) ctrl.wg.Add(1) expandArgsToTextFiles(flag.Args(), textFileCh, runtime.NumCPU(), ftiMgr, ctrl) // Wait for the main pipeline to complete. ctrl.wg.Wait() close(ctrl.stopCh) // Wait for the file type info manager to shutdown. ftiCtrl.wg.Wait() fmt.Println("Non-text extensions discovered:") cfg.Dump(ftiMgr.nonTextTypes) fmt.Println("Text extensions discovered:") cfg.Dump(ftiMgr.textTypes) fmt.Println() fmt.Println() stats.ComputeFractions() fmt.Println("Whitespace info:") cfg.Dump(stats) }
func TestSyncDB(t *testing.T) { spew := spew.NewDefaultConfig() spew.MaxDepth = 2 checkSyncDB := func(cloudMachines []provider.Machine, databaseMachines []db.Machine, expectedBoot, expectedStop []provider.Machine) { _, bootResult, stopResult := syncDB(cloudMachines, databaseMachines) if !emptySlices(bootResult, expectedBoot) && !reflect.DeepEqual(bootResult, expectedBoot) { t.Error(spew.Sprintf( "booted wrong machines. Expected %v, got %v.", expectedBoot, bootResult)) } if !emptySlices(stopResult, expectedStop) && !reflect.DeepEqual( stopResult, expectedStop) { t.Error(spew.Sprintf( "stopped wrong machines. Expected %v, got %v.", expectedStop, stopResult)) } } var noMachines []provider.Machine dbNoSize := db.Machine{Provider: FakeAmazon} cmNoSize := provider.Machine{Provider: FakeAmazon} dbLarge := db.Machine{Provider: FakeAmazon, Size: "m4.large"} cmLarge := provider.Machine{Provider: FakeAmazon, Size: "m4.large"} // Test boot with no size checkSyncDB(noMachines, []db.Machine{dbNoSize}, []provider.Machine{cmNoSize}, noMachines) // Test boot with size checkSyncDB(noMachines, []db.Machine{dbLarge}, []provider.Machine{cmLarge}, noMachines) // Test mixed boot checkSyncDB(noMachines, []db.Machine{dbNoSize, dbLarge}, []provider.Machine{ cmNoSize, cmLarge}, noMachines) // Test partial boot checkSyncDB([]provider.Machine{cmNoSize}, []db.Machine{dbNoSize, dbLarge}, []provider.Machine{cmLarge}, noMachines) // Test stop checkSyncDB([]provider.Machine{cmNoSize}, []db.Machine{}, noMachines, []provider.Machine{cmNoSize}) // Test partial stop checkSyncDB([]provider.Machine{cmNoSize, cmLarge}, []db.Machine{}, noMachines, []provider.Machine{cmNoSize, cmLarge}) }
func dumpTIDM(t *tidm.TIDM) error { dumpFile, err := os.Create("tidm_dump") if err != nil { return fmt.Errorf("Error creating dumpfile: %s", err) } // write spew dump io.WriteString(dumpFile, "spew.Dump:\n==========\n") cs := spew.NewDefaultConfig() cs.Indent = " " cs.Fdump(dumpFile, t) io.WriteString(dumpFile, "\n\n\n\n") // write json io.WriteString(dumpFile, "tidm-json:\n==========\n") enc := json.NewEncoder(dumpFile) err = enc.Encode(t) if err != nil { return fmt.Errorf("Error encoding tidm-json to dumpfile: %s", err) } // all done return nil }
func testIDOnlyRefresh(c TestCase, opts terraform.ContextOpts, step TestStep, r *terraform.ResourceState) error { // TODO: We guard by this right now so master doesn't explode. We // need to remove this eventually to make this part of the normal tests. if os.Getenv("TF_ACC_IDONLY") == "" { return nil } name := fmt.Sprintf("%s.foo", r.Type) // Build the state. The state is just the resource with an ID. There // are no attributes. We only set what is needed to perform a refresh. state := terraform.NewState() state.RootModule().Resources[name] = &terraform.ResourceState{ Type: r.Type, Primary: &terraform.InstanceState{ ID: r.Primary.ID, }, } // Create the config module. We use the full config because Refresh // doesn't have access to it and we may need things like provider // configurations. The initial implementation of id-only checks used // an empty config module, but that caused the aforementioned problems. mod, err := testModule(opts, step) if err != nil { return err } // Initialize the context opts.Module = mod opts.State = state ctx := terraform.NewContext(&opts) if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 { if len(es) > 0 { estrs := make([]string, len(es)) for i, e := range es { estrs[i] = e.Error() } return fmt.Errorf( "Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v", ws, estrs) } log.Printf("[WARN] Config warnings: %#v", ws) } // Refresh! state, err = ctx.Refresh() if err != nil { return fmt.Errorf("Error refreshing: %s", err) } // Verify attribute equivalence. actualR := state.RootModule().Resources[name] if actualR == nil { return fmt.Errorf("Resource gone!") } if actualR.Primary == nil { return fmt.Errorf("Resource has no primary instance") } actual := actualR.Primary.Attributes expected := r.Primary.Attributes // Remove fields we're ignoring for _, v := range c.IDRefreshIgnore { delete(actual, v) delete(expected, v) } if !reflect.DeepEqual(actual, expected) { // Determine only the different attributes for k, v := range expected { if av, ok := actual[k]; ok && v == av { delete(expected, k) delete(actual, k) } } spewConf := spew.NewDefaultConfig() spewConf.SortKeys = true return fmt.Errorf( "Attributes not equivalent. Difference is shown below. Top is actual, bottom is expected."+ "\n\n%s\n\n%s", spewConf.Sdump(actual), spewConf.Sdump(expected)) } return nil }
func initSpewTests() { // Config states with various settings. scsDefault := spew.NewDefaultConfig() scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true} scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true} scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1} scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true} scsNoPtrAddr := &spew.ConfigState{DisablePointerAddresses: true} scsNoCap := &spew.ConfigState{DisableCapacities: true} // Variables for tests on types which implement Stringer interface with and // without a pointer receiver. ts := stringer("test") tps := pstringer("test") type ptrTester struct { s *struct{} } tptr := &ptrTester{s: &struct{}{}} // depthTester is used to test max depth handling for structs, array, slices // and maps. type depthTester struct { ic indirCir1 arr [1]string slice []string m map[string]int } dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"}, map[string]int{"one": 1}} // Variable for tests on types which implement error interface. te := customError(10) spewTests = []spewTest{ {scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"}, {scsDefault, fCSFprint, "", int16(32767), "32767"}, {scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"}, {scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"}, {scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"}, {scsDefault, fCSPrintln, "", uint8(255), "255\n"}, {scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"}, {scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"}, {scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"}, {scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"}, {scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"}, {scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"}, {scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"}, {scsDefault, fFprint, "", float32(3.14), "3.14"}, {scsDefault, fFprintln, "", float64(6.28), "6.28\n"}, {scsDefault, fPrint, "", true, "true"}, {scsDefault, fPrintln, "", false, "false\n"}, {scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"}, {scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"}, {scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"}, {scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"}, {scsNoMethods, fCSFprint, "", ts, "test"}, {scsNoMethods, fCSFprint, "", &ts, "<*>test"}, {scsNoMethods, fCSFprint, "", tps, "test"}, {scsNoMethods, fCSFprint, "", &tps, "<*>test"}, {scsNoPmethods, fCSFprint, "", ts, "stringer test"}, {scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"}, {scsNoPmethods, fCSFprint, "", tps, "test"}, {scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"}, {scsMaxDepth, fCSFprint, "", dt, "{{<max>} [<max>] [<max>] map[<max>]}"}, {scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" + " ic: (spew_test.indirCir1) {\n <max depth reached>\n },\n" + " arr: ([1]string) (len=1 cap=1) {\n <max depth reached>\n },\n" + " slice: ([]string) (len=1 cap=1) {\n <max depth reached>\n },\n" + " m: (map[string]int) (len=1) {\n <max depth reached>\n }\n}\n"}, {scsContinue, fCSFprint, "", ts, "(stringer test) test"}, {scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " + "(len=4) (stringer test) \"test\"\n"}, {scsContinue, fCSFprint, "", te, "(error: 10) 10"}, {scsContinue, fCSFdump, "", te, "(spew_test.customError) " + "(error: 10) 10\n"}, {scsNoPtrAddr, fCSFprint, "", tptr, "<*>{<*>{}}"}, {scsNoPtrAddr, fCSSdump, "", tptr, "(*spew_test.ptrTester)({\ns: (*struct {})({\n})\n})\n"}, {scsNoCap, fCSSdump, "", make([]string, 0, 10), "([]string) {\n}\n"}, {scsNoCap, fCSSdump, "", make([]string, 1, 10), "([]string) (len=1) {\n(string) \"\"\n}\n"}, } }
// testStepImportState runs an imort state test step func testStepImportState( opts terraform.ContextOpts, state *terraform.State, step TestStep) (*terraform.State, error) { // Determine the ID to import importId := step.ImportStateId if importId == "" { resource, err := testResource(step, state) if err != nil { return state, err } importId = resource.Primary.ID } // Setup the context. We initialize with an empty state. We use the // full config for provider configurations. mod, err := testModule(opts, step) if err != nil { return state, err } opts.Module = mod opts.State = terraform.NewState() ctx, err := terraform.NewContext(&opts) if err != nil { return state, err } // Do the import! newState, err := ctx.Import(&terraform.ImportOpts{ // Set the module so that any provider config is loaded Module: mod, Targets: []*terraform.ImportTarget{ &terraform.ImportTarget{ Addr: step.ResourceName, ID: importId, }, }, }) if err != nil { log.Printf("[ERROR] Test: ImportState failure: %s", err) return state, err } // Go through the new state and verify if step.ImportStateCheck != nil { var states []*terraform.InstanceState for _, r := range newState.RootModule().Resources { if r.Primary != nil { states = append(states, r.Primary) } } if err := step.ImportStateCheck(states); err != nil { return state, err } } // Verify that all the states match if step.ImportStateVerify { new := newState.RootModule().Resources old := state.RootModule().Resources for _, r := range new { // Find the existing resource var oldR *terraform.ResourceState for _, r2 := range old { if r2.Primary != nil && r2.Primary.ID == r.Primary.ID { oldR = r2 break } } if oldR == nil { return state, fmt.Errorf( "Failed state verification, resource with ID %s not found", r.Primary.ID) } // Compare their attributes actual := make(map[string]string) for k, v := range r.Primary.Attributes { actual[k] = v } expected := make(map[string]string) for k, v := range oldR.Primary.Attributes { expected[k] = v } // Remove fields we're ignoring for _, v := range step.ImportStateVerifyIgnore { for k, _ := range actual { if strings.HasPrefix(k, v) { delete(actual, k) } } for k, _ := range expected { if strings.HasPrefix(k, v) { delete(expected, k) } } } if !reflect.DeepEqual(actual, expected) { // Determine only the different attributes for k, v := range expected { if av, ok := actual[k]; ok && v == av { delete(expected, k) delete(actual, k) } } spewConf := spew.NewDefaultConfig() spewConf.SortKeys = true return state, fmt.Errorf( "ImportStateVerify attributes not equivalent. Difference is shown below. Top is actual, bottom is expected."+ "\n\n%s\n\n%s", spewConf.Sdump(actual), spewConf.Sdump(expected)) } } } // Return the old state (non-imported) so we don't change anything. return state, nil }
func TestACLs(t *testing.T) { spew := spew.NewDefaultConfig() spew.MaxDepth = 2 conn := db.New() code := ` (define Namespace "Namespace") (define MasterCount 1) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (role "Worker"))) (define AdminACL (list "1.2.3.4/32" "local"))` myIP = func() (string, error) { return "5.6.7.8", nil } UpdatePolicy(conn, prog(t, code)) err := conn.Transact(func(view db.Database) error { cluster, err := view.GetCluster() if err != nil { return err } if !reflect.DeepEqual(cluster.ACLs, []string{"1.2.3.4/32", "5.6.7.8/32"}) { return fmt.Errorf("bad ACLs: %s", spew.Sdump(cluster.ACLs)) } return nil }) if err != nil { t.Error(err.Error()) } myIP = func() (string, error) { return "", errors.New("") } UpdatePolicy(conn, prog(t, code)) err = conn.Transact(func(view db.Database) error { cluster, err := view.GetCluster() if err != nil { return err } if !reflect.DeepEqual(cluster.ACLs, []string{"1.2.3.4/32"}) { return fmt.Errorf("bad ACLs: %s", spew.Sdump(cluster.ACLs)) } return nil }) if err != nil { t.Error(err.Error()) } // Test allow traffic between machines conn.Transact(func(view db.Database) error { machines := view.SelectFromMachine(nil) if len(machines) == 0 { return errors.New("expected machines in database") } machines[0].PublicIP = "8.8.8.8" view.Commit(machines[0]) return nil }) UpdatePolicy(conn, prog(t, code)) err = conn.Transact(func(view db.Database) error { cluster, err := view.GetCluster() if err != nil { return err } if !reflect.DeepEqual(cluster.ACLs, []string{"1.2.3.4/32", "8.8.8.8/32"}) { return fmt.Errorf("bad ACLs: %s", spew.Sdump(cluster.ACLs)) } return nil }) if err != nil { t.Error(err.Error()) } }
func TestSort(t *testing.T) { spew := spew.NewDefaultConfig() spew.MaxDepth = 2 conn := db.New() UpdatePolicy(conn, prog(t, ` (define Namespace "Namespace") (define MasterCount 3) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (size "m4.large") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (size "m4.large") (role "Worker"))) (define AdminACL (list))`)) err := conn.Transact(func(view db.Database) error { machines := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) if len(machines) != 3 { return fmt.Errorf("bad machines: %s", spew.Sdump(machines)) } machines[2].PublicIP = "a" machines[2].PrivateIP = "b" view.Commit(machines[2]) machines[1].PrivateIP = "c" view.Commit(machines[1]) return nil }) if err != nil { t.Error(err.Error()) } UpdatePolicy(conn, prog(t, ` (define Namespace "Namespace") (define MasterCount 2) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (size "m4.large") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (size "m4.large") (role "Worker"))) (define AdminACL (list))`)) err = conn.Transact(func(view db.Database) error { machines := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) if len(machines) != 2 { return fmt.Errorf("bad machines: %s", spew.Sdump(machines)) } for _, m := range machines { if m.PublicIP == "" && m.PrivateIP == "" { return fmt.Errorf("bad machine: %s", spew.Sdump(machines)) } } return nil }) if err != nil { t.Error(err.Error()) } UpdatePolicy(conn, prog(t, ` (define Namespace "Namespace") (define MasterCount 1) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (size "m4.large") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (size "m4.large") (role "Worker"))) (define AdminACL (list))`)) err = conn.Transact(func(view db.Database) error { machines := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) if len(machines) != 1 { return fmt.Errorf("bad machines: %s", spew.Sdump(machines)) } for _, m := range machines { if m.PublicIP == "" || m.PrivateIP == "" { return fmt.Errorf("bad machine: %s", spew.Sdump(machines)) } } return nil }) if err != nil { t.Error(err.Error()) } }
func TestContainer(t *testing.T) { spew := spew.NewDefaultConfig() spew.MaxDepth = 2 conn := db.New() check := func(code string, red, blue, yellow int) error { UpdatePolicy(conn, prog(t, code)) return conn.Transact(func(view db.Database) error { var redCount, blueCount, yellowCount int containers := view.SelectFromContainer(nil) for _, c := range containers { if len(c.Labels) != 1 { err := spew.Sprintf("two many labels: %s", c) return errors.New(err) } switch c.Labels[0] { case "Red": redCount++ case "Blue": blueCount++ case "Yellow": yellowCount++ default: err := spew.Sprintf("unkonwn label: %s", c) return errors.New(err) } } if red != redCount || blue != blueCount || yellow != yellowCount { return errors.New( spew.Sprintf("bad containers: %s", containers)) } return nil }) } code := ` (define Namespace "Namespace") (define MasterCount 1) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (role "Worker"))) (label "Red" (makeList 2 (docker "alpine"))) (label "Blue" (makeList 2 (docker "alpine")))` check(code, 2, 2, 0) code = ` (define Namespace "Namespace") (define MasterCount 1) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (role "Worker"))) (label "Red" (makeList 3 (docker "alpine")))` check(code, 3, 0, 0) code = ` (define Namespace "Namespace") (define MasterCount 1) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (role "Worker"))) (label "Red" (makeList 1 (docker "alpine"))) (label "Blue" (makeList 5 (docker "alpine"))) (label "Yellow" (makeList 10 (docker "alpine")))` check(code, 1, 5, 10) code = ` (define Namespace "Namespace") (define MasterCount 1) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (role "Worker"))) (label "Red" (makeList 30 (docker "alpine"))) (label "Blue" (makeList 4 (docker "alpine"))) (label "Yellow" (makeList 7 (docker "alpine")))` check(code, 30, 4, 7) code = ` (define Namespace "Namespace") (define MasterCount 1) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (role "Worker")))` check(code, 0, 0, 0) }
func TestEngine(t *testing.T) { spew := spew.NewDefaultConfig() spew.MaxDepth = 2 conn := db.New() code := ` (define Namespace "Namespace") (define MasterCount 2) (define WorkerCount 3) (makeList MasterCount (machine (provider "Amazon") (size "m4.large") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (size "m4.large") (role "Worker"))) (define AdminACL (list "1.2.3.4/32"))` UpdatePolicy(conn, prog(t, code)) err := conn.Transact(func(view db.Database) error { cluster, err := view.GetCluster() masters := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) workers := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Worker }) if err != nil { return err } else if len(cluster.ACLs) != 1 { return fmt.Errorf("bad cluster: %s", spew.Sdump(cluster)) } if len(masters) != 2 { return fmt.Errorf("bad masters: %s", spew.Sdump(masters)) } if len(workers) != 3 { return fmt.Errorf("bad workers: %s", spew.Sdump(workers)) } return nil }) if err != nil { t.Error(err.Error()) } /* Verify master increase. */ code = ` (define Namespace "Namespace") (define MasterCount 4) (define WorkerCount 5) (makeList MasterCount (machine (provider "Amazon") (size "m4.large") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (size "m4.large") (role "Worker"))) (define AdminACL (list "1.2.3.4/32"))` UpdatePolicy(conn, prog(t, code)) err = conn.Transact(func(view db.Database) error { masters := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) workers := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Worker }) if len(masters) != 4 { return fmt.Errorf("bad masters: %s", spew.Sdump(masters)) } if len(workers) != 5 { return fmt.Errorf("bad workers: %s", spew.Sdump(workers)) } return nil }) if err != nil { t.Error(err.Error()) } /* Verify that external writes stick around. */ err = conn.Transact(func(view db.Database) error { masters := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) workers := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Worker }) for _, master := range masters { master.CloudID = "1" master.PublicIP = "2" master.PrivateIP = "3" view.Commit(master) } for _, worker := range workers { worker.CloudID = "1" worker.PublicIP = "2" worker.PrivateIP = "3" view.Commit(worker) } return nil }) /* Also verify that masters and workers decrease properly. */ code = ` (define Namespace "Namespace") (define MasterCount 1) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (size "m4.large") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (size "m4.large") (role "Worker"))) (define AdminACL (list "1.2.3.4/32"))` UpdatePolicy(conn, prog(t, code)) err = conn.Transact(func(view db.Database) error { masters := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) workers := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Worker }) if len(masters) != 1 || masters[0].CloudID != "1" || masters[0].PublicIP != "2" || masters[0].PrivateIP != "3" { return fmt.Errorf("bad masters: %s", spew.Sdump(masters)) } if len(workers) != 1 || workers[0].CloudID != "1" || workers[0].PublicIP != "2" || workers[0].PrivateIP != "3" { return fmt.Errorf("bad workers: %s", spew.Sdump(workers)) } return nil }) if err != nil { t.Error(err.Error()) } /* Empty Namespace does nothing. */ code = ` (define MasterCount 1) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (size "m4.large") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (size "m4.large") (role "Worker"))) (define AdminACL (list "1.2.3.4/32"))` UpdatePolicy(conn, prog(t, code)) err = conn.Transact(func(view db.Database) error { masters := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) workers := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Worker }) if len(masters) != 1 || masters[0].CloudID != "1" || masters[0].PublicIP != "2" || masters[0].PrivateIP != "3" { return fmt.Errorf("bad masters: %s", spew.Sdump(masters)) } if len(workers) != 1 || workers[0].CloudID != "1" || workers[0].PublicIP != "2" || workers[0].PrivateIP != "3" { return fmt.Errorf("bad workers: %s", spew.Sdump(workers)) } return nil }) if err != nil { t.Error(err.Error()) } /* Verify things go to zero. */ code = ` (define Namespace "Namespace") (define MasterCount 0) (define WorkerCount 1) (makeList MasterCount (machine (provider "Amazon") (size "m4.large") (role "Master"))) (makeList WorkerCount (machine (provider "Amazon") (size "m4.large") (role "Worker"))) (define AdminACL (list "1.2.3.4/32"))` UpdatePolicy(conn, prog(t, code)) err = conn.Transact(func(view db.Database) error { masters := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) workers := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Worker }) if len(masters) != 0 { return fmt.Errorf("bad masters: %s", spew.Sdump(masters)) } if len(workers) != 0 { return fmt.Errorf("bad workers: %s", spew.Sdump(workers)) } return nil }) if err != nil { t.Error(err.Error()) } // This function checks whether there is a one-to-one mapping for each machine // in `slice` to a provider in `providers`. providersInSlice := func(slice db.MachineSlice, providers db.ProviderSlice) bool { lKey := func(left interface{}) interface{} { return left.(db.Machine).Provider } rKey := func(right interface{}) interface{} { return right.(db.Provider) } _, l, r := join.HashJoin(slice, providers, lKey, rKey) return len(l) == 0 && len(r) == 0 } /* Test mixed providers. */ code = ` (define Namespace "Namespace") (list (machine (provider "Amazon") (size "m4.large") (role "Master")) (machine (provider "Vagrant") (size "v.large") (role "Master"))) (list (machine (provider "Azure") (size "a.large") (role "Worker")) (machine (provider "Google") (size "g.large") (role "Worker"))) (define AdminACL (list "1.2.3.4/32"))` UpdatePolicy(conn, prog(t, code)) err = conn.Transact(func(view db.Database) error { masters := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) workers := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Worker }) if !providersInSlice(masters, db.ProviderSlice{db.Amazon, db.Vagrant}) { return fmt.Errorf("bad masters: %s", spew.Sdump(masters)) } if !providersInSlice(workers, db.ProviderSlice{db.Azure, db.Google}) { return fmt.Errorf("bad workers: %s", spew.Sdump(workers)) } return nil }) if err != nil { t.Error(err.Error()) } /* Test that machines with different providers don't match. */ code = ` (define Namespace "Namespace") (list (machine (provider "Amazon") (size "m4.large") (role "Master")) (machine (provider "Azure") (size "a.large") (role "Master"))) (list (machine (provider "Amazon") (size "m4.large") (role "Worker"))) (define AdminACL (list "1.2.3.4/32"))` UpdatePolicy(conn, prog(t, code)) err = conn.Transact(func(view db.Database) error { masters := view.SelectFromMachine(func(m db.Machine) bool { return m.Role == db.Master }) if !providersInSlice(masters, db.ProviderSlice{db.Amazon, db.Azure}) { return fmt.Errorf("bad masters: %s", spew.Sdump(masters)) } return nil }) if err != nil { t.Error(err.Error()) } }
func TestSync(t *testing.T) { spew := spew.NewDefaultConfig() spew.MaxDepth = 2 checkSync := func(clst cluster, provider db.Provider, expectedBoot []bootRequest, expectedStop []string) { clst.sync() providerInst := clst.providers[provider].(*fakeProvider) bootResult := providerInst.bootRequests stopResult := providerInst.stopRequests providerInst.clearLogs() if !emptySlices(bootResult, expectedBoot) && !reflect.DeepEqual(bootResult, expectedBoot) { t.Error(spew.Sprintf( "booted wrong machines. Expected %s, got %s.", expectedBoot, bootResult)) } if !emptySlices(stopResult, expectedStop) && !reflect.DeepEqual(stopResult, expectedStop) { t.Error(spew.Sprintf( "stopped wrong machines. Expected %s, got %s.", expectedStop, stopResult)) } } var noStops []string var noBoots []bootRequest amazonLargeBoot := bootRequest{size: "m4.large", cloudConfig: amazonCloudConfig} amazonXLargeBoot := bootRequest{size: "m4.xlarge", cloudConfig: amazonCloudConfig} vagrantLargeBoot := bootRequest{size: "vagrant.large", cloudConfig: vagrantCloudConfig} // Test initial boot clst := newTestCluster() clst.conn.Transact(func(view db.Database) error { m := view.InsertMachine() m.Role = db.Master m.Provider = FakeAmazon m.Size = "m4.large" view.Commit(m) return nil }) checkSync(clst, FakeAmazon, []bootRequest{amazonLargeBoot}, noStops) // Test adding a machine with the same provider clst.conn.Transact(func(view db.Database) error { m := view.InsertMachine() m.Role = db.Master m.Provider = FakeAmazon m.Size = "m4.xlarge" view.Commit(m) return nil }) checkSync(clst, FakeAmazon, []bootRequest{amazonXLargeBoot}, noStops) // Test adding a machine with a different provider clst.conn.Transact(func(view db.Database) error { m := view.InsertMachine() m.Role = db.Master m.Provider = FakeVagrant m.Size = "vagrant.large" view.Commit(m) return nil }) checkSync(clst, FakeVagrant, []bootRequest{vagrantLargeBoot}, noStops) // Test removing a machine var toRemove db.Machine clst.conn.Transact(func(view db.Database) error { toRemove = view.SelectFromMachine(func(m db.Machine) bool { return m.Provider == FakeAmazon && m.Size == "m4.xlarge" })[0] view.Remove(toRemove) return nil }) checkSync(clst, FakeAmazon, noBoots, []string{toRemove.CloudID}) // Test removing and adding a machine clst.conn.Transact(func(view db.Database) error { toRemove = view.SelectFromMachine(func(m db.Machine) bool { return m.Provider == FakeAmazon && m.Size == "m4.large" })[0] view.Remove(toRemove) m := view.InsertMachine() m.Role = db.Worker m.Provider = FakeAmazon m.Size = "m4.xlarge" view.Commit(m) return nil }) checkSync(clst, FakeAmazon, []bootRequest{amazonXLargeBoot}, []string{toRemove.CloudID}) }
func GenerateGo(t *tidm.TIDM) { cs := spew.NewDefaultConfig() cs.Indent = " " fmt.Println("Dumping TIDM") cs.Dump(t) }