mirror of
https://github.com/anyproto/anytype-heart.git
synced 2025-06-07 21:37:04 +09:00
GO-511 Smoke test
This commit is contained in:
parent
abf5bda3a3
commit
737ff8857b
5 changed files with 227 additions and 84 deletions
1
.dockerignore
Normal file
1
.dockerignore
Normal file
|
@ -0,0 +1 @@
|
|||
Dockerfile
|
26
Dockerfile
26
Dockerfile
|
@ -1,21 +1,27 @@
|
|||
FROM golang:1.16-buster AS builder
|
||||
FROM golang:1.18 AS builder
|
||||
MAINTAINER Anytype <dev@anytype.io>
|
||||
|
||||
# This is (in large part) copied (with love) from
|
||||
# https://hub.docker.com/r/ipfs/go-ipfs/dockerfile
|
||||
|
||||
ENV SRC_DIR /anytype
|
||||
ENV BUILD_DIR /tmp
|
||||
WORKDIR /anytype
|
||||
|
||||
# Download packages first so they can be cached.
|
||||
COPY go.mod go.sum $SRC_DIR/
|
||||
RUN cd $SRC_DIR \
|
||||
&& go mod download
|
||||
COPY go.mod go.sum /
|
||||
RUN go mod download
|
||||
|
||||
COPY . $SRC_DIR
|
||||
COPY . .
|
||||
|
||||
# Install the binary
|
||||
RUN cd $SRC_DIR \
|
||||
&& go build -v -o $BUILD_DIR/server ./cmd/grpcserver/grpc.go
|
||||
RUN go build -o server ./cmd/grpcserver/grpc.go
|
||||
|
||||
ENTRYPOINT ["/tmp/server"]
|
||||
FROM ubuntu
|
||||
|
||||
# TODO: more fine-grained dependencies
|
||||
RUN apt update && apt install -y curl
|
||||
COPY --from=builder /anytype/server .
|
||||
EXPOSE 31007
|
||||
EXPOSE 31008
|
||||
ENV ANYTYPE_GRPC_ADDR=:31007
|
||||
ENV ANYTYPE_GRPCWEB_ADDR=:31008
|
||||
CMD ["./server"]
|
||||
|
|
|
@ -1,77 +1,8 @@
|
|||
version: "3"
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
test:
|
||||
container_name: test
|
||||
image: docker.pkg.github.com/anytypeio/python-anytype-testing/tests:latest
|
||||
volumes:
|
||||
- ./allure-results:/app/allure-results
|
||||
- shared-temp:/tmp/shared
|
||||
links:
|
||||
- middleware-node-a
|
||||
- middleware-node-b
|
||||
- middleware-node-base
|
||||
environment:
|
||||
TEST_MIDDLEWARE_NODE_A_ADDRESS_HOST: middleware-node-a
|
||||
TEST_MIDDLEWARE_NODE_A_ADDRESS_PORT: 31007
|
||||
TEST_MIDDLEWARE_NODE_A_ADDRESS_GATEWAY_PORT: 32007
|
||||
TEST_MIDDLEWARE_NODE_B_ADDRESS_HOST: middleware-node-b
|
||||
TEST_MIDDLEWARE_NODE_B_ADDRESS_PORT: 41007
|
||||
TEST_MIDDLEWARE_NODE_B_ADDRESS_GATEWAY_PORT: 42007
|
||||
TEST_MIDDLEWARE_NODE_BASE_ADDRESS_HOST: middleware-node-base
|
||||
TEST_MIDDLEWARE_NODE_BASE_ADDRESS_PORT: 51007
|
||||
TEST_MIDDLEWARE_NODE_BASE_ADDRESS_GATEWAY_PORT: 52007
|
||||
command: bash -c "make test"
|
||||
|
||||
middleware-node-a:
|
||||
stop_grace_period: 1s
|
||||
stop_signal: SIGABRT
|
||||
image: docker.pkg.github.com/anytypeio/go-anytype-middleware/server:${TAG}
|
||||
environment:
|
||||
ANYTYPE_GRPC_ADDR: "0.0.0.0:31007"
|
||||
ANYTYPE_GATEWAY_ADDR: "0.0.0.0:32007"
|
||||
ANYTYPE_LOG_LEVEL: "anytype-mw-app=DEBUG;grpc=DEBUG;anytype-gateway=DEBUG"
|
||||
ANYTYPE_LOG_NOGELF: 1
|
||||
ANYTYPE_GRPC_LOG: 3
|
||||
# local tracing
|
||||
#ANYTYPE_GRPC_TRACE: 3
|
||||
#JAEGER_AGENT_HOST: "docker.for.mac.localhost"
|
||||
#JAEGER_SERVICE_NAME: "mw-a"
|
||||
volumes:
|
||||
- shared-temp:/tmp/shared
|
||||
middleware-node-b:
|
||||
stop_grace_period: 1s
|
||||
stop_signal: SIGABRT
|
||||
image: docker.pkg.github.com/anytypeio/go-anytype-middleware/server:${TAG}
|
||||
environment:
|
||||
ANYTYPE_GRPC_ADDR: "0.0.0.0:41007"
|
||||
ANYTYPE_GATEWAY_ADDR: "0.0.0.0:42007"
|
||||
ANYTYPE_LOG_LEVEL: "anytype-mw-app=DEBUG;grpc=DEBUG;anytype-gateway=DEBUG"
|
||||
ANYTYPE_LOG_NOGELF: 1
|
||||
ANYTYPE_GRPC_LOG: 3
|
||||
# local tracing
|
||||
#ANYTYPE_GRPC_TRACE: 3
|
||||
#JAEGER_AGENT_HOST: "docker.for.mac.localhost"
|
||||
#JAEGER_SERVICE_NAME: "mw-b"
|
||||
#JAEGER_SERVICE_NAME: "mw-b"
|
||||
volumes:
|
||||
- shared-temp:/tmp/shared
|
||||
middleware-node-base:
|
||||
stop_grace_period: 1s
|
||||
stop_signal: SIGABRT
|
||||
image: docker.pkg.github.com/anytypeio/go-anytype-middleware/server:${BASE_TAG}
|
||||
environment:
|
||||
ANYTYPE_GRPC_ADDR: "0.0.0.0:51007"
|
||||
ANYTYPE_GATEWAY_ADDR: "0.0.0.0:52007"
|
||||
ANYTYPE_LOG_LEVEL: "anytype-mw-app=DEBUG;grpc=DEBUG;anytype-gateway=DEBUG"
|
||||
ANYTYPE_LOG_NOGELF: 1
|
||||
ANYTYPE_GRPC_LOG: 3
|
||||
# local tracing
|
||||
#ANYTYPE_GRPC_TRACE: 3
|
||||
#JAEGER_AGENT_HOST: "docker.for.mac.localhost"
|
||||
#JAEGER_SERVICE_NAME: "mw-b"
|
||||
#JAEGER_SERVICE_NAME: "mw-b"
|
||||
volumes:
|
||||
- shared-temp:/tmp/shared
|
||||
volumes:
|
||||
shared-temp:
|
||||
build: .
|
||||
ports:
|
||||
- "31007:31007"
|
||||
- "31008:31008"
|
141
test/basic_test.go
Normal file
141
test/basic_test.go
Normal file
|
@ -0,0 +1,141 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb/service"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
|
||||
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
|
||||
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
func TestBasic(t *testing.T) {
|
||||
conn, err := grpc.Dial("127.0.0.1:31007", grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
require.NoError(t, err)
|
||||
|
||||
c := service.NewClientCommandsClient(conn)
|
||||
|
||||
const mnemonic = "lamp crane identify video setup cactus hat icon guard develop alert solar"
|
||||
const rootPath = "/var/anytype"
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("WalletRecover", func(t *testing.T) {
|
||||
resp, err := c.WalletRecover(ctx, &pb.RpcWalletRecoverRequest{
|
||||
Mnemonic: mnemonic,
|
||||
RootPath: rootPath,
|
||||
})
|
||||
assert.NoError(t, json.NewEncoder(os.Stdout).Encode(resp))
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
var tok string
|
||||
t.Run("WalletCreateSession", func(t *testing.T) {
|
||||
resp, err := c.WalletCreateSession(ctx, &pb.RpcWalletCreateSessionRequest{
|
||||
Mnemonic: mnemonic,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
tok = resp.Token
|
||||
})
|
||||
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, "token", tok)
|
||||
|
||||
stream, err := c.ListenSessionEvents(ctx, &pb.StreamRequest{Token: tok})
|
||||
require.NoError(t, err)
|
||||
|
||||
er := startEventReceiver(ctx, stream)
|
||||
|
||||
t.Run("AccountRecover", func(t *testing.T) {
|
||||
resp, err := c.AccountRecover(ctx, &pb.RpcAccountRecoverRequest{})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, json.NewEncoder(os.Stdout).Encode(resp))
|
||||
})
|
||||
|
||||
t.Run("AccountSelect", func(t *testing.T) {
|
||||
var id string
|
||||
// TODO: log waiting for event?
|
||||
waitEvent(er, func(a *pb.EventMessageValueOfAccountShow) {
|
||||
id = a.AccountShow.Account.Id
|
||||
})
|
||||
|
||||
resp, err := c.AccountSelect(ctx, &pb.RpcAccountSelectRequest{
|
||||
Id: id,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, json.NewEncoder(os.Stdout).Encode(resp))
|
||||
})
|
||||
|
||||
t.Run("ObjectSearch", func(t *testing.T) {
|
||||
resp, err := c.ObjectSearch(ctx, &pb.RpcObjectSearchRequest{
|
||||
Keys: []string{"id", "type", "name"},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, resp.Records)
|
||||
})
|
||||
|
||||
t.Run("ObjectSearchSubscribe", func(t *testing.T) {
|
||||
resp, err := c.ObjectSearchSubscribe(ctx, &pb.RpcObjectSearchSubscribeRequest{
|
||||
SubId: "recent",
|
||||
Filters: []*model.BlockContentDataviewFilter{
|
||||
{
|
||||
RelationKey: bundle.RelationKeyLastOpenedDate.String(),
|
||||
Condition: model.BlockContentDataviewFilter_Greater,
|
||||
},
|
||||
},
|
||||
Keys: []string{"id", "lastOpenedDate"},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, resp.Records)
|
||||
})
|
||||
|
||||
var objId string
|
||||
t.Run("BlockLinkCreateWithObject", func(t *testing.T) {
|
||||
resp, err := c.BlockLinkCreateWithObject(ctx, &pb.RpcBlockLinkCreateWithObjectRequest{
|
||||
InternalFlags: []*model.InternalFlag{
|
||||
{
|
||||
Value: model.InternalFlag_editorDeleteEmpty,
|
||||
},
|
||||
{
|
||||
Value: model.InternalFlag_editorSelectType,
|
||||
},
|
||||
},
|
||||
Details: &types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
bundle.RelationKeyType.String(): pbtypes.String(bundle.TypeKeyNote.URL()),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, resp.TargetId)
|
||||
objId = resp.TargetId
|
||||
})
|
||||
|
||||
t.Run("ObjectOpen", func(t *testing.T) {
|
||||
resp, err := c.ObjectOpen(ctx, &pb.RpcObjectOpenRequest{
|
||||
ObjectId: objId,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp.ObjectView)
|
||||
|
||||
waitEvent(er, func(sa *pb.EventMessageValueOfSubscriptionAdd) {
|
||||
require.Equal(t, sa.SubscriptionAdd.Id, objId)
|
||||
})
|
||||
waitEvent(er, func(sa *pb.EventMessageValueOfObjectDetailsSet) {
|
||||
require.Equal(t, sa.ObjectDetailsSet.Id, objId)
|
||||
require.Contains(t, sa.ObjectDetailsSet.Details.Fields, bundle.RelationKeyLastOpenedDate.String())
|
||||
})
|
||||
})
|
||||
}
|
64
test/events.go
Normal file
64
test/events.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/anytypeio/go-anytype-middleware/pb"
|
||||
"github.com/anytypeio/go-anytype-middleware/pb/service"
|
||||
)
|
||||
|
||||
type eventReceiver struct {
|
||||
lock *sync.Mutex
|
||||
events []*pb.EventMessage
|
||||
// events chan<- *pb.EventMessage
|
||||
}
|
||||
|
||||
func startEventReceiver(ctx context.Context, c service.ClientCommands_ListenSessionEventsClient) *eventReceiver {
|
||||
er := &eventReceiver{
|
||||
lock: &sync.Mutex{},
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
ev, err := c.Recv()
|
||||
if err != nil {
|
||||
fmt.Println("receive error:", err)
|
||||
continue
|
||||
}
|
||||
er.lock.Lock()
|
||||
for _, m := range ev.Messages {
|
||||
er.events = append(er.events, m)
|
||||
}
|
||||
er.lock.Unlock()
|
||||
}
|
||||
}
|
||||
}()
|
||||
return er
|
||||
}
|
||||
|
||||
func waitEvent[t pb.IsEventMessageValue](er *eventReceiver, fn func(x t)) {
|
||||
for {
|
||||
er.lock.Lock()
|
||||
for i := len(er.events) - 1; i >= 0; i-- {
|
||||
m := er.events[i]
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
if v, ok := m.Value.(t); ok {
|
||||
fn(v)
|
||||
er.events[i] = nil
|
||||
er.lock.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
er.lock.Unlock()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue