func testInstance(t *testing.T, ctx context.Context) (data.DB, *gaia.Gaia, *httptest.Server) { db := mem.NewDB() g := gaia.New( ctx, &gaia.Middleware{}, &gaia.Services{ Logger: services.NewTestLogger(t), DB: db, SMSCommandSessions: services.NewSMSMux(), WebCommandSessions: services.NewWebMux(), }, ) s := httptest.NewServer(g) return db, g, s }
func main() { flag.Parse() var db data.DB var err error log.Printf("== Setting Up Database ==") log.Printf("\tDatabase Type: %s", *dbtype) switch *dbtype { case "mem": db = mem.NewDB() case "mongo": db, err = models.MongoDB(*dbaddr) if err != nil { log.Fatal(err) } log.Printf("\tConnected to mongo@%s", *dbaddr) default: log.Fatal("Unrecognized database type: '%s'", *dbtype) } log.Printf("== Set up Database ==") // DB CLIENT conn, err := grpc.Dial(":3334", grpc.WithInsecure()) if err != nil { log.Fatalf("failed to dial: %v", err) } defer conn.Close() adbc := access.NewDBClient(conn) // AUTH CLIENT conn, err = grpc.Dial(":3333", grpc.WithInsecure()) if err != nil { log.Fatalf("failed to dial: %v", err) } defer conn.Close() ac := auth.NewAuthClient(conn) // WEBUI SERVER lis, err := net.Listen("tcp", ":1113") if err != nil { log.Fatalf("failed to listen on :1113: %v", err) } g := grpc.NewServer() records.RegisterWebUIServer(g, records.Logged(records.NewWebUI(adbc, ac))) go g.Serve(lis) // WEB UI CLIENT conn, err = grpc.Dial(":1113", grpc.WithInsecure()) if err != nil { log.Fatalf("failed to dial: %v", err) } defer conn.Close() webuiclient := records.NewWebUIClient(conn) // calendar WEBUI SERVER lis, err = net.Listen("tcp", ":1114") if err != nil { log.Fatalf("failed to listen on :1114: %v", err) } g = grpc.NewServer() cal.RegisterWebUIServer(g, cal.NewWebUI(adbc, ac)) go g.Serve(lis) // cal WEB UI CLIENT conn, err = grpc.Dial(":1114", grpc.WithInsecure()) if err != nil { log.Fatalf("failed to dial: %v", err) } defer conn.Close() calwebui := cal.NewWebUIClient(conn) if _, _, err := user.Create(db, "u", "p"); err != nil { log.Fatal("user.Create error: %s", err) } background := context.Background() log.Printf("== Connecting to Twilio ==") twilioClient := twilio.NewClient(TwilioAccountSid, TwilioAuthToken, nil) log.Printf("== Connected to Twilio ==") log.Printf("== Starting SMS Command Sessions ==") smsMux := services.NewSMSMux() go smsMux.Start( background, db, services.SMSFromTwilio(twilioClient, TwilioFromNumber), ) log.Printf("== Started SMS Command Sessions ==") log.Printf("== Initiliazing Gaia Core ==") ga := gaia.New( context.Background(), new(gaia.Middleware), &gaia.Services{ AppFileSystem: http.Dir(*appdir), SMSCommandSessions: smsMux, DB: db, Logger: services.NewLogger(os.Stderr), WebUIClient: webuiclient, CalWebUIClient: calwebui, }, ) log.Printf("== Initiliazed Gaia Core ==") log.Printf("== Starting Agents ===") user.Map(db, func(db data.DB, u *models.User) error { go agents.LocationAgent(background, db, u) go agents.TaskAgent(background, db, u) go agents.WebSensorsAgent(background, db, u) return nil }) log.Printf("== Started Agents ===") log.Printf("== Starting HTTP Server ==") host := fmt.Sprintf("%s:%d", *addr, *port) log.Printf("\tServing on %s", host) if *certFile != "" && *keyFile != "" { if *port != 443 { log.Print("WARNING: serving HTTPS on a port that isn't 443") } if err = http.ListenAndServeTLS(host, *certFile, *keyFile, ga); err != nil { log.Fatal(err) } } else { log.Print("NOT SERVING SECURELY") if *port != 80 { log.Print("WARNING: serving HTTP on a port that isn't 80") } if err = http.ListenAndServe(host, ga); err != nil { log.Fatal(err) } } log.Printf("== Started HTTP Server ==") }
// --- 'elos setup' (context: need a new account) {{{ func TestSetupNewUser(t *testing.T) { f, err := ioutil.TempFile("", "conf") if err != nil { t.Fatal(err) } defer f.Close() db := mem.NewDB() dbc, closers, err := access.NewTestDB(db) if err != nil { t.Fatalf("access.NewTestDB error: %v", err) } defer func(cs []io.Closer) { for _, c := range cs { c.Close() } }(closers) authc, closers, err := auth.NewTestAuth(db) if err != nil { t.Fatalf("access.NewTestDB error: %v", err) } defer func(cs []io.Closer) { for _, c := range cs { c.Close() } }(closers) webui, conn, err := records.WebUIBothLocal(dbc, authc) if err != nil { t.Fatalf("records.WebUIBothLocal error: %v", err) } defer conn.Close() g := gaia.New( context.Background(), &gaia.Middleware{}, &gaia.Services{ SMSCommandSessions: services.NewSMSMux(), Logger: services.NewTestLogger(t), DB: db, WebUIClient: webui, }, ) s := httptest.NewServer(g) defer s.Close() ui, conf, c := newMockSetupCommand(t) conf.Path = f.Name() // no already account, then username input and password input ui.InputReader = bytes.NewBufferString(fmt.Sprintf("%s\nn\npublic\nprivate\n", s.URL)) t.Log("running: `elos setup`") code := c.Run([]string{}) t.Log("command `setup` terminated") t.Log("Reading outputs") errput := ui.ErrorWriter.String() output := ui.OutputWriter.String() t.Logf("Error output:\n%s", errput) t.Logf("Output:\n%s", output) // verify there were no errors if errput != "" { t.Fatalf("Expected no error output, got: %s", errput) } // verify success if code != 0 { t.Fatalf("Expected successful exit code along with empty error output.") } // verify some of the output if !strings.Contains(output, "account") { t.Fatalf("Output should have contained a 'account' for saying something about an account") } i, err := db.Query(data.Kind(models.Kind_CREDENTIAL.String())).Select(data.AttrMap{ "public": "public", "private": "private", }).Execute() if err != nil { t.Fatal(err) } cred := new(models.Credential) if ok := i.Next(cred); !ok { t.Fatal("no credentials found") } if got, want := cred.OwnerId, "1"; got != want { t.Fatalf("cred.OwnerId: got %q, want %q", got, want) } // verify conf was changed if got, want := conf.UserID, "1"; got != want { t.Fatalf("conf.UserID: got %q, want %q", got, want) } if conf.PublicCredential != "public" { t.Fatalf("public credential should be: public") } if conf.PrivateCredential != "private" { t.Fatalf("private credential should be: private") } }
func TestCommandSMS(t *testing.T) { db := mem.NewDB() sms := newMockSMS() mux := services.NewSMSMux() ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() go mux.Start(ctx, db, sms) ctx, cancelContext := context.WithCancel(context.Background()) defer cancelContext() g := gaia.New( ctx, &gaia.Middleware{}, &gaia.Services{ Logger: services.NewTestLogger(t), DB: db, SMSCommandSessions: mux, WebCommandSessions: services.NewWebMux(), }, ) s := httptest.NewServer(g) defer s.Close() u, _ := testUser(t, db) t.Log("Creating profile") p := models.NewProfile() p.SetID(db.NewID()) phone := "650 123 4567" p.Phone = phone p.SetOwner(u) if err := db.Save(p); err != nil { t.Fatal(err) } t.Log("Created") messageBody := "todo" params := url.Values{} params.Set("To", phone) // /command/ ignores this, twilio sends it though params.Set("From", phone) params.Set("Body", messageBody) url := s.URL + "/command/sms/?" + params.Encode() t.Logf("Constructed URL: %s", url) req, err := http.NewRequest("POST", url, nil) if err != nil { t.Fatal(err) } resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { t.Fatal(err) } t.Logf("Code: %d", resp.StatusCode) t.Logf("Body:\n%s", body) if resp.StatusCode != http.StatusNoContent { t.Fatalf("Expected status code of %d", http.StatusNoContent) } select { case m := <-sms.bus: t.Logf("Message:\n%+v", m) if !strings.Contains(m.body, "elos") { t.Fatal("The message should have almost certainly contained the word elos") } case <-time.After(1 * time.Second): t.Fatal("Timed out waiting for sms message") } }
func TestCommandSMSInput(t *testing.T) { db := mem.NewDB() sms := newMockSMS() mux := services.NewSMSMux() ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() go mux.Start(ctx, db, sms) ctx, cancelContext := context.WithCancel(context.Background()) defer cancelContext() g := gaia.New( ctx, &gaia.Middleware{}, &gaia.Services{ Logger: services.NewTestLogger(t), DB: db, SMSCommandSessions: mux, WebCommandSessions: services.NewWebMux(), }, ) s := httptest.NewServer(g) defer s.Close() u, _ := testUser(t, db) t.Log("Creating profile") p := models.NewProfile() p.SetID(db.NewID()) phone := "650 123 4567" p.Phone = phone p.SetOwner(u) if err := db.Save(p); err != nil { t.Fatal(err) } t.Log("Created") messageBody := "todo new" fakeSMS(t, s, phone, phone, messageBody) select { case m := <-sms.bus: t.Logf("Message:\n%+v", m) if !strings.Contains(m.body, "Name") { t.Fatal("The message should have asked for name of task") } case <-time.After(1 * time.Second): t.Fatal("Timed out waiting for sms message") } taskName := "task name" // for the name fakeSMS(t, s, phone, phone, taskName) select { case m := <-sms.bus: t.Logf("Message:\n%+v", m) if !strings.Contains(m.body, "deadline") { t.Fatal("The message should have asked if it had a deadline") } case <-time.After(1 * time.Second): t.Fatal("Timed out waiting for sms message") } fakeSMS(t, s, phone, phone, "n") // no deadline select { case m := <-sms.bus: t.Logf("Message:\n%+v", m) if !strings.Contains(m.body, "prerequisites") { t.Fatal("The message should have asked if it had a prereqs") } case <-time.After(1 * time.Second): t.Fatal("Timed out waiting for sms message") } fakeSMS(t, s, phone, phone, "n") // no prereqs select { case m := <-sms.bus: t.Logf("Message:\n%+v", m) if !strings.Contains(m.body, "created") { t.Fatal("Should have indicated task was created") } case <-time.After(1 * time.Second): t.Fatal("Timed out waiting for sms message") } task := models.NewTask() // ensure the task exists if err := db.PopulateByField("name", taskName, task); err != nil { t.Fatal(err) } t.Logf("Task:\n%+v", task) }
func TestCommandWeb(t *testing.T) { db := mem.NewDB() sms := newMockSMS() smsMux := services.NewSMSMux() webMux := services.NewWebMux() ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() go smsMux.Start(ctx, db, sms) go webMux.Start(ctx, db) ctx, cancelContext := context.WithCancel(context.Background()) defer cancelContext() g := gaia.New( ctx, &gaia.Middleware{}, &gaia.Services{ Logger: services.NewTestLogger(t), DB: db, SMSCommandSessions: smsMux, WebCommandSessions: webMux, }, ) s := httptest.NewServer(g) defer s.Close() _, cred := testUser(t, db) serverURL := s.URL origin := serverURL wsURL := strings.Replace(serverURL, "http", "ws", 1) params := url.Values{} params.Set("public", cred.Public) params.Set("private", cred.Private) wsURL += "/command/web/?" + params.Encode() t.Logf("Constructed URL: %s", wsURL) t.Log("Opening websocket") ws, err := websocket.Dial(wsURL, "", origin) if err != nil { t.Fatal(err) } defer ws.Close() t.Log("Websocket openened") messageBody := "todo" // Sending a message t.Logf("Sending message: %s", messageBody) websocket.Message.Send(ws, messageBody) t.Logf("Sent") t.Log("Recieving a message") var received string websocket.Message.Receive(ws, &received) t.Logf("Recieved message: %s", received) t.Log("Verifying the response contained the word 'elos'") if !strings.Contains(received, "elos") { t.Fatal("The message should have almost certainly contained the word elos") } t.Log("Verified") }