Example #1
0
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
}
Example #2
0
File: main.go Project: elos/gaia
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 ==")
}
Example #3
0
// --- '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")
	}
}
Example #4
0
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")
	}
}
Example #5
0
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)
}
Example #6
0
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")
}