diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8e3f801ec69915648eae7c6afaec81d0abca38f0..2fad5fb0b20734ce9c8011ae63e8fc48bde2d361 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ Unit tests: script: - "ln -s $(pwd) $GOPATH/src/dfss" - "./build/deps.sh" - - "cd $GOPATH/src/dfss && rm -rf gui && go install ./..." + - "cd $GOPATH/src/dfss && make install" - "go test -coverprofile auth.part -v dfss/auth" - "go test -coverprofile mgdb.part -v dfss/mgdb" - "go test -coverprofile mails.part -v dfss/mails" @@ -32,7 +32,6 @@ Unit tests: - "go test -coverprofile dfssp_contract.part -v dfss/dfssp/contract" - "go test -coverprofile dfssp_templates.part -v dfss/dfssp/templates" - "go test -coverprofile dfssp_common.part -v dfss/dfssp/common" - - "go test -coverprofile dfssd.part -v dfss/dfssd" - "go test -coverprofile dfssc_common.part -v dfss/dfssc/common" - "go test -coverprofile dfssc_security.part -v dfss/dfssc/security" - "go test -coverprofile dfssc_user.part -v dfss/dfssc/user" @@ -53,7 +52,7 @@ Integration tests: script: - "ln -s -f $(pwd) $GOPATH/src/dfss" - "./build/deps.sh" - - "cd $GOPATH/src/dfss && rm -rf gui && go install ./..." + - "cd $GOPATH/src/dfss && make install" - "go test -v dfss/tests" Code lint: @@ -68,9 +67,9 @@ Code lint: - "ln -s $(pwd) $GOPATH/src/dfss" - "go get github.com/alecthomas/gometalinter" - "./build/deps.sh" - - "cd $GOPATH/src/dfss && rm -rf gui && go install ./..." + - "cd $GOPATH/src/dfss && make install_all" - "gometalinter --install" - - "gometalinter -t --deadline=600s -j1 --skip=api --skip=fixtures --disable=aligncheck ./..." + - "gometalinter -t --deadline=600s -j1 --skip=api --skip=fixtures --skip=gui --skip=dfssd --disable=aligncheck ./..." Deploy: stage: deploy diff --git a/Makefile b/Makefile index 1c30301a408eae5a3c2a29bf9015603c11202060..df3784056634b8b21589d9a5817e9f486301b59e 100644 --- a/Makefile +++ b/Makefile @@ -7,18 +7,20 @@ endif .PHONY: install: nocache - go install . go install ./dfssc - go install ./dfssd go install ./dfssp go install ./dfsst -release: clean build_all package - -clean: - rm -rf release +# install_all installs everything, including libraries. It's mandatory for linter, but should be improved in the future. +install_all: install + git stash + rm -rf gui + rm -rf dfssd/gui + rm -f dfssd/main.go + go install ./... + git reset --hard -# GUI Build (Docker required) +release: clean build_all package # prepare_gui builds a new container from the goqt image, adding DFSS dependencies for faster builds. # call it once or after dependency addition. @@ -35,11 +37,24 @@ gui: nocache docker run --rm -v ${PWD}:/go/src/dfss -w /go/src/dfss/gui dfss:builder \ go build -ldflags "-r ." -o ../bin/gui -# Release internals +# dfssd builds the demonstrator into a docker container, outputing the result in bin/ directory +dfssd: nocache + docker run --rm -v ${PWD}:/go/src/dfss -w /go/src/dfss/dfssd/gui dfss:builder \ + ../../bin/goqt_rcc -go gui -o application.qrc.go application.qrc + docker run --rm -v ${PWD}:/go/src/dfss -w /go/src/dfss/dfssd dfss:builder \ + go build -ldflags "-r ." -o ../bin/dfssd + +protobuf: + cd .. && \ + protoc --go_out=plugins=grpc:. dfss/dfssc/api/client.proto && \ + protoc --go_out=plugins=grpc:. dfss/dfssd/api/demonstrator.proto && \ + protoc --go_out=plugins=grpc:. dfss/dfssp/api/platform.proto && \ + protoc --go_out=plugins=grpc:. dfss/dfsst/api/resolution.proto +# Release internals build_all: go get github.com/mitchellh/gox - gox -os "linux darwin windows" -parallel 1 -output "release/dfss_${VERSION}_{{.OS}}_{{.Arch}}/{{.Dir}}" dfss/dfssc dfss/dfssd dfss/dfssp dfss/dfsst + gox -os "linux darwin windows" -parallel 1 -output "release/dfss_${VERSION}_{{.OS}}_{{.Arch}}/{{.Dir}}" dfss/dfssc dfss/dfssp dfss/dfsst package: echo "$(VERSION) $(REVISION)" > build/embed/VERSION @@ -50,11 +65,7 @@ deploy: mkdir -p /deploy/$(VERSION) cp release/*.tar.gz /deploy/$(VERSION)/ -protobuf: - cd .. && \ - protoc --go_out=plugins=grpc:. dfss/dfssc/api/client.proto && \ - protoc --go_out=plugins=grpc:. dfss/dfssd/api/demonstrator.proto && \ - protoc --go_out=plugins=grpc:. dfss/dfssp/api/platform.proto && \ - protoc --go_out=plugins=grpc:. dfss/dfsst/api/resolution.proto +clean: + rm -rf release nocache: diff --git a/dfssd/dfssd_test.go b/dfssd/dfssd_test.go deleted file mode 100644 index 8fc005aa75d711b07269fc6c5124ef1f372045ce..0000000000000000000000000000000000000000 --- a/dfssd/dfssd_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - dapi "dfss/dfssd/api" - "testing" -) - -// Test for a client-server dialing -// -// Cannot add output statement because output includes timestamp -func TestServerAndClient(t *testing.T) { - - // Start a server - go func() { - err := listen("localhost:3000") - if err != nil { - t.Error("Unable to start server") - } - }() - - // Start a client - go func() { - defer dapi.DClose() - // this one fails silently, so you can't really test it - dapi.DLog("This is a log message from a client") - }() - - // Start another client - go func() { - defer dapi.DClose() - // this one fails silently, so you can't really test it - dapi.DLog("This is a log message from another client") - }() -} diff --git a/dfssd/gui/application.qrc b/dfssd/gui/application.qrc new file mode 100644 index 0000000000000000000000000000000000000000..65c5cfcd87581ab614c456eab60d777c2a797f3e --- /dev/null +++ b/dfssd/gui/application.qrc @@ -0,0 +1,5 @@ + + + widget.ui + + diff --git a/dfssd/gui/widget.ui b/dfssd/gui/widget.ui new file mode 100644 index 0000000000000000000000000000000000000000..207beb568fed08a8a802062dd6ca8d661e5b5d13 --- /dev/null +++ b/dfssd/gui/widget.ui @@ -0,0 +1,187 @@ + + + CalculatorForm + + + true + + + + 0 + 0 + 751 + 595 + + + + + 0 + 0 + + + + Calculator Builder + + + + 9 + + + 6 + + + + + + + + 700 + 300 + + + + + + + + 5 + + + 5 + + + + + + 0 + 0 + + + + Play + + + true + + + + + + + + 0 + 0 + + + + Replay + + + + + + + + 0 + 0 + + + + Quantum: + + + + + + + + 0 + 0 + + + + us + + + 1 + + + 1000000 + + + 100 + + + 1000 + + + + + + + + 0 + 0 + + + + Speed: + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QSlider::TicksBothSides + + + 5 + + + + + + + + + + 16777215 + 200 + + + + + Courier + 10 + + + + Qt::ScrollBarAlwaysOn + + + false + + + true + + + false + + + + + + + + + + diff --git a/dfssd/gui/window.go b/dfssd/gui/window.go new file mode 100644 index 0000000000000000000000000000000000000000..a4aa9aef09f945dad9f18e5102442c1b07e91574 --- /dev/null +++ b/dfssd/gui/window.go @@ -0,0 +1,54 @@ +package gui + +import ( + "dfss" + "github.com/visualfc/goqt/ui" +) + +type Window struct { + *ui.QMainWindow + + logField *ui.QTextEdit +} + +func NewWindow() *Window { + file := ui.NewFileWithName(":/widget.ui") + loader := ui.NewUiLoader() + widget := loader.Load(file) + + // Init main window + window := ui.NewMainWindow() + window.SetCentralWidget(widget) + window.SetWindowTitle("DFSS Demonstrator v" + dfss.Version) + + w := &Window{ + QMainWindow: window, + } + + // Load dynamic elements from driver + w.logField = ui.NewTextEditFromDriver(widget.FindChild("logField")) + + // Add actions + w.addActions() + + w.StatusBar().ShowMessage("Ready") + return w +} + +func (w *Window) Log(str string) { + w.logField.Append(str) + w.logField.EnsureCursorVisible() +} + +func (w *Window) addActions() { + openAct := ui.NewActionWithTextParent("&Open", w) + openAct.SetShortcuts(ui.QKeySequence_Open) + openAct.SetStatusTip("Open a demonstration file") + + saveAct := ui.NewActionWithTextParent("&Save", w) + saveAct.SetShortcuts(ui.QKeySequence_Save) + saveAct.SetStatusTip("Save a demonstration file") + + w.MenuBar().AddAction(openAct) + w.MenuBar().AddAction(saveAct) +} diff --git a/dfssd/main.go b/dfssd/main.go index 4517b7d6cd3f6adf6e910cbac42119f291e29c47..6be4fd8864356e8922d66042b64f76a018a189d6 100644 --- a/dfssd/main.go +++ b/dfssd/main.go @@ -1,20 +1,25 @@ package main import ( - "dfss" "flag" "fmt" "os" "runtime" + "strconv" + + "dfss" + "dfss/dfssd/server" + "dfss/dfssd/gui" + "github.com/visualfc/goqt/ui" ) var ( - verbose bool + port int ) func init() { - flag.BoolVar(&verbose, "v", false, "Print verbose messages") + flag.IntVar(&port, "p", 3000, "Network port used") flag.Usage = func() { fmt.Println("DFSS demonstrator v" + dfss.Version) @@ -26,7 +31,8 @@ func init() { fmt.Println("\nThe commands are:") fmt.Println(" help print this help") fmt.Println(" version print dfss client version") - fmt.Println(" start start demonstrator server") + fmt.Println(" nogui start demonstrator server without GUI") + fmt.Println(" gui start demonstrator server with GUI") fmt.Println("\nFlags:") flag.PrintDefaults() @@ -40,14 +46,28 @@ func main() { command := flag.Arg(0) switch command { + case "help": + flag.Usage() case "version": fmt.Println("v"+dfss.Version, runtime.GOOS, runtime.GOARCH) - case "start": - err := listen("localhost:3000") + case "nogui": + lfn := func(str string) { + fmt.Println(str) + } + err := server.Listen("0.0.0.0:" + strconv.Itoa(port), lfn) if err != nil { os.Exit(1) } default: - flag.Usage() + ui.Run(func() { + window := gui.NewWindow() + go func() { + err := server.Listen("0.0.0.0:" + strconv.Itoa(port), window.Log) + if err != nil { + window.Log("!! " + err.Error()) + } + }() + window.Show() + }) } } diff --git a/dfssd/server.go b/dfssd/server/server.go similarity index 66% rename from dfssd/server.go rename to dfssd/server/server.go index b400d6c542bb425872fb885eeec03858a74c0531..cf0a4841de5c62bb2ae692fc1ea2996986eaf6c1 100644 --- a/dfssd/server.go +++ b/dfssd/server/server.go @@ -1,41 +1,40 @@ -package main +package server import ( - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/grpclog" - "log" "net" api "dfss/dfssd/api" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/grpclog" ) -type server struct{} +type Server struct{} // Sendlog Handler // // Handle incoming log messages -func (s *server) SendLog(ctx context.Context, in *api.Log) (*api.Ack, error) { +func (s *Server) SendLog(ctx context.Context, in *api.Log) (*api.Ack, error) { addMessage(in) return &api.Ack{}, nil } // Listen with gRPG service -func listen(addrPort string) error { +func Listen(addrPort string, lfn func(string)) error { // open tcp socket lis, err := net.Listen("tcp", addrPort) if err != nil { grpclog.Fatalf("Failed to open tcp socket: %v", err) return err } - log.Printf("Server listening on %s", addrPort) + lfn("Server listening on " + addrPort) // log display manager - go displayHandler() + go displayHandler(lfn) // bootstrap gRPC service ! grpcServer := grpc.NewServer() - api.RegisterDemonstratorServer(grpcServer, &server{}) + api.RegisterDemonstratorServer(grpcServer, &Server{}) err = grpcServer.Serve(lis) return err diff --git a/dfssd/storage.go b/dfssd/server/storage.go similarity index 85% rename from dfssd/storage.go rename to dfssd/server/storage.go index 3e67fbba351d523c0f92a38fc1d6ef6d924adcba..b2e4e0c5da45ee901a89eb44ebfd35124ce93f69 100644 --- a/dfssd/storage.go +++ b/dfssd/server/storage.go @@ -1,7 +1,7 @@ -package main +package server import ( - "log" + "fmt" "sort" "sync" "time" @@ -23,7 +23,7 @@ func addMessage(msg *api.Log) { } // display logs that are more than since (ms) old -func display(since int64) { +func display(since int64, lfn func(string)) { var out []*api.Log // sorted messages to display var recycled []*api.Log // messages too recent to be displayed @@ -45,15 +45,15 @@ func display(since int64) { sort.Sort(ByTimestamp(out)) for _, v := range out { - log.Printf("[%d] %s:: %s", v.Timestamp, v.Identifier, v.Log) + lfn(fmt.Sprintf("[%d] %s:: %s", v.Timestamp, v.Identifier, v.Log)) } } // refresh every second -func displayHandler() { +func displayHandler(lfn func(string)) { ticker := time.NewTicker(time.Second) for range ticker.C { - display(1000) + display(1000, lfn) } }