Skip to content

Commit fa920f9

Browse files
committed
started working on e2e tests
1 parent a2bf460 commit fa920f9

File tree

3 files changed

+151
-1
lines changed

3 files changed

+151
-1
lines changed

Makefile

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,26 @@ BACKEND_NAME ?= llocalsearch-backend
33
FRONTEND_NAME ?= llocalsearch-frontend
44
GIT_HASH := $(shell git rev-parse --short HEAD)
55

6+
PHONY: e2e-backend
7+
e2e-backend:
8+
(cd ./backend && ginkgo -v -r ./...)
9+
610
# dev run commands
711
PHONY: build-dev
812
build-dev:
913
docker-compose -f ./docker-compose.dev.yaml build
1014

1115
PHONY: dev
1216
dev: build-dev
13-
docker-compose -f ./docker-compose.dev.yaml up
17+
docker-compose -f ./docker-compose.dev.yaml up $(ARGS)
18+
19+
PHONY: dev-bg
20+
dev-bg: build-dev
21+
docker-compose -f ./docker-compose.dev.yaml up -d
22+
23+
PHONY: dev-bg-stop
24+
dev-bg-stop:
25+
docker-compose -f ./docker-compose.dev.yaml down
1426

1527
# normal hosting commands
1628
PHONY: run

backend/e2e/e2e_suite_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package e2e_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestE2e(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "E2e Suite")
13+
}

backend/e2e/simple_question_test.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package e2e_test
2+
3+
import (
4+
"bufio"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
"net/url"
10+
"os"
11+
"os/exec"
12+
"strings"
13+
14+
"github.com/nilsherzig/LLocalSearch/utils"
15+
. "github.com/onsi/ginkgo/v2"
16+
. "github.com/onsi/gomega"
17+
)
18+
19+
var _ = Describe("Main", Ordered, func() {
20+
Describe("tests one shot questions with known answers", func() {
21+
// BeforeAll(func() {
22+
// cmd := exec.Command("make", "dev-bg")
23+
// _, err := Run(cmd)
24+
// if err != nil {
25+
// if exitErr, ok := err.(*exec.ExitError); ok {
26+
// GinkgoWriter.Printf("Stderr: %s\n", string(exitErr.Stderr))
27+
// }
28+
// }
29+
//
30+
// Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("start command '%s' failed", cmd.String()))
31+
//
32+
// DeferCleanup(func() {
33+
// cmd := exec.Command("make", "dev-bg-stop")
34+
// _, err := Run(cmd)
35+
// Expect(err).NotTo(HaveOccurred())
36+
// })
37+
// })
38+
39+
It("should be able to get the modellist endpoint", func() {
40+
Eventually(func() error {
41+
req, err := http.NewRequest("GET", "http://localhost:3000/api/models", nil)
42+
Expect(err).ToNot(HaveOccurred())
43+
44+
resp, err := http.DefaultClient.Do(req)
45+
if err != nil {
46+
return err
47+
}
48+
if resp.StatusCode != http.StatusOK {
49+
return fmt.Errorf("status code not 200")
50+
}
51+
return nil
52+
}, "2m", "5s").Should(Not(HaveOccurred()))
53+
54+
})
55+
56+
defaultModel := "adrienbrault/nous-hermes2pro:Q8_0"
57+
// defaultModel = "command-r:35b-v0.1-q4_0"
58+
59+
sessionString := "default"
60+
61+
DescribeTable("questions and answers", func(prompt string, answerSubstring string, modelname string) {
62+
requestUrl := fmt.Sprintf("http://localhost:3000/api/stream?prompt=%s&session=%s&modelname=%s", url.QueryEscape(prompt), url.QueryEscape(sessionString), url.QueryEscape(modelname))
63+
resp, err := http.Get(requestUrl)
64+
Expect(err).ToNot(HaveOccurred(), "stream request failed")
65+
Expect(resp.StatusCode).To(Equal(http.StatusOK), "stream request http status code not 200")
66+
67+
reader := bufio.NewReader(resp.Body)
68+
inner:
69+
for {
70+
line, err := reader.ReadString('\n')
71+
if err == io.EOF {
72+
break
73+
}
74+
line = strings.TrimLeft(line, "data: ")
75+
var streamElem utils.HttpJsonStreamElement
76+
err = json.Unmarshal([]byte(line), &streamElem)
77+
if err != nil {
78+
continue
79+
}
80+
// TOOD Needed for follow-up quesions
81+
// if streamElem.Session != sessionString {
82+
// sessionString = streamElem.Session
83+
// continue
84+
// }
85+
if streamElem.StepType == utils.StepHandleAgentFinish {
86+
GinkgoWriter.Printf("line: %s\n", line)
87+
Expect(streamElem.Message).To(ContainSubstring(answerSubstring), "answer substring not found in response")
88+
break inner
89+
}
90+
}
91+
},
92+
Entry("German quesion", "Wann beginnt das Sommersemester an der Hochschule Stralsund?", "März", defaultModel),
93+
Entry("Fact 1 question", "how much do OpenAI and Microsoft plan to spend on their new datacenter?", "$100 billion", defaultModel),
94+
Entry("Fact 2", "how much does Obsidian sync cost?", "$4", defaultModel),
95+
)
96+
})
97+
})
98+
99+
func Run(cmd *exec.Cmd) ([]byte, error) {
100+
dir, _ := GetProjectDir()
101+
cmd.Dir = dir
102+
103+
if err := os.Chdir(cmd.Dir); err != nil {
104+
fmt.Fprintf(GinkgoWriter, "chdir dir: %s\n", err)
105+
}
106+
107+
cmd.Env = append(os.Environ(), "GO111MODULE=on")
108+
command := strings.Join(cmd.Args, " ")
109+
fmt.Fprintf(GinkgoWriter, "running: %s\n", command)
110+
output, err := cmd.CombinedOutput()
111+
if err != nil {
112+
return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output))
113+
}
114+
115+
return output, nil
116+
}
117+
118+
func GetProjectDir() (string, error) {
119+
wd, err := os.Getwd()
120+
if err != nil {
121+
return wd, err
122+
}
123+
wd = strings.Replace(wd, "/backend/e2e", "", -1)
124+
return wd, nil
125+
}

0 commit comments

Comments
 (0)