func main() { // initialize logger log := logger.Logger() defer log.Close() defer log.Flush() // parse input parameters parseFlags(log) // check whether this is an interactive session isIntSess, err := svc.IsAnInteractiveSession() if err != nil { log.Warnf("Failed to determine if we are running in an interactive session: %v", err) } // isIntSess is false by default (after declaration), this fits the use // case that agent is running as Windows service most of times switch isIntSess { case true: run(log) case false: svc.Run(serviceName, &amazonSSMAgentService{log: log}) } }
// Test provides a testing facility for alternative storage implementations. // The s.setup should return a freshly created and empty storage. Removing the // store from the system is the responsibility of the caller. The test only // guarantees not to panic on recoverable errors and return an error instead. // Test errors are not returned but reported to t. func test(t *testing.T, s testDB) (panicked error) { defer func() { if e := recover(); e != nil { switch x := e.(type) { case error: panicked = x default: panicked = fmt.Errorf("%v", e) } } if panicked != nil { t.Errorf("PANIC: %v\n%s", panicked, debug.Stack()) } }() db, err := s.setup() if err != nil { t.Error(err) return } tctx := NewRWCtx() if !*oSlow { if _, _, err := db.Execute(tctx, txBegin); err != nil { t.Error(err) return nil } } if err = s.mark(); err != nil { t.Error(err) return } defer func() { x := tctx if *oSlow { x = nil } if err = s.teardown(x); err != nil { t.Error(err) } }() chk := func(test int, err error, expErr string, re *regexp.Regexp) (ok bool) { s := err.Error() if re == nil { t.Error("FAIL: ", test, s) return false } if !re.MatchString(s) { t.Error("FAIL: ", test, "error doesn't match:", s, "expected", expErr) return false } return true } var logf *os.File hasLogf := false noErrors := true if _, ok := s.(*memTestDB); ok { if logf, err = ioutil.TempFile("", "ql-test-log-"); err != nil { t.Error(err) return nil } hasLogf = true } else { if logf, err = os.Create(os.DevNull); err != nil { t.Error(err) return nil } } defer func() { if hasLogf && noErrors { func() { if _, err := logf.Seek(0, 0); err != nil { t.Error(err) return } dst, err := os.Create("testdata.log") if err != nil { t.Error(err) return } if _, err := io.Copy(dst, logf); err != nil { t.Error(err) return } if err := dst.Close(); err != nil { t.Error(err) } }() } nm := logf.Name() if err := logf.Close(); err != nil { t.Error(err) } if hasLogf { if err := os.Remove(nm); err != nil { t.Error(err) } } }() log := bufio.NewWriter(logf) defer func() { if err := log.Flush(); err != nil { t.Error(err) } }() max := len(testdata) if n := *oM; n != 0 && n < max { max = n } for itest, test := range testdata[*oN:max] { //dbg("------------------------------------------------------------- ( itest %d ) ----", itest) var re *regexp.Regexp a := strings.Split(test+"|", "|") q, rset := a[0], strings.TrimSpace(a[1]) var expErr string if len(a) < 3 { t.Error(itest, "internal error 066") return } if expErr = a[2]; expErr != "" { re = regexp.MustCompile("(?i:" + strings.TrimSpace(expErr) + ")") } q = strings.Replace(q, "∨", "|", -1) q = strings.Replace(q, "⩖", "||", -1) list, err := Compile(q) if err != nil { if !chk(itest, err, expErr, re) && *oFastFail { return } continue } for _, s := range list.l { if err := testMentionedColumns(s); err != nil { t.Error(itest, err) return } } s1 := list.String() list1, err := Compile(s1) if err != nil { t.Errorf("recreated source does not compile: %v\n---- orig\n%s\n---- recreated\n%s", err, q, s1) if *oFastFail { return } continue } s2 := list1.String() if g, e := s2, s1; g != e { t.Errorf("recreated source is not idempotent\n---- orig\n%s\n---- recreated1\n%s\n---- recreated2\n%s", q, s1, s2) if *oFastFail { return } continue } if !func() (ok bool) { tnl0 := db.tnl defer func() { s3 := list.String() if g, e := s1, s3; g != e { t.Errorf("#%d: execution mutates compiled statement list\n---- orig\n%s----new\n%s", itest, g, e) } if !ok { noErrors = false } if noErrors { hdr := false for _, v := range list.l { s, err := explained(db, v, tctx) if err != nil { t.Error(err) return } if !strings.HasPrefix(s, "┌") { continue } if !hdr { fmt.Fprintf(log, "---- %v\n", itest) hdr = true } fmt.Fprintf(log, "%s\n", v) fmt.Fprintf(log, "%s\n\n", s) } } tnl := db.tnl if tnl != tnl0 { panic(fmt.Errorf("internal error 057: tnl0 %v, tnl %v", tnl0, tnl)) } nfo, err := db.Info() if err != nil { dbg("", err) panic(err) } for _, idx := range nfo.Indices { //dbg("#%d: cleanup index %s", itest, idx.Name) if _, _, err = db.run(tctx, fmt.Sprintf(` BEGIN TRANSACTION; DROP INDEX %s; COMMIT; `, idx.Name)); err != nil { t.Errorf("#%d: cleanup DROP INDEX %s: %v", itest, idx.Name, err) ok = false } } for _, tab := range nfo.Tables { //dbg("#%d: cleanup table %s", itest, tab.Name) if _, _, err = db.run(tctx, fmt.Sprintf(` BEGIN TRANSACTION; DROP table %s; COMMIT; `, tab.Name)); err != nil { t.Errorf("#%d: cleanup DROP TABLE %s: %v", itest, tab.Name, err) ok = false } } db.hasIndex2 = 0 }() if err = s.mark(); err != nil { t.Error(err) return } rs, _, err := db.Execute(tctx, list, int64(30)) if err != nil { return chk(itest, err, expErr, re) } if rs == nil { t.Errorf("FAIL: %d: expected non nil Recordset or error %q", itest, expErr) return } g, err := recSetDump(rs[len(rs)-1]) if err != nil { return chk(itest, err, expErr, re) } if expErr != "" { t.Errorf("FAIL: %d: expected error %q", itest, expErr) return } a = strings.Split(rset, "\n") for i, v := range a { a[i] = strings.TrimSpace(v) } e := strings.Join(a, "\n") if g != e { t.Errorf("FAIL: test # %d\n%s\n---- g\n%s\n---- e\n%s\n----", itest, q, g, e) return } return true }() && *oFastFail { return } } return }