ci: add acceptance test
This commit is contained in:
3
.github/workflows/main.yml
vendored
3
.github/workflows/main.yml
vendored
@@ -22,3 +22,6 @@ jobs:
|
|||||||
- name: Testing
|
- name: Testing
|
||||||
run: go test ./...
|
run: go test ./...
|
||||||
|
|
||||||
|
- name: Acceptance test
|
||||||
|
run: make
|
||||||
|
|
||||||
|
|||||||
27
Dockerfile
Normal file
27
Dockerfile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
FROM golang:1.12-alpine as builder
|
||||||
|
|
||||||
|
# Remove the cache to avoid warning message during `apk info`
|
||||||
|
RUN rm -rf /var/cache/apk/* && \
|
||||||
|
rm -rf /tmp/*
|
||||||
|
|
||||||
|
RUN apk update
|
||||||
|
|
||||||
|
# GO and PATH env variables already set in golang image
|
||||||
|
# to reduce download time
|
||||||
|
RUN apk --no-cache add -U make git musl-dev gcc
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN GO111MODULE=on make local-build
|
||||||
|
|
||||||
|
# final stage
|
||||||
|
FROM alpine:3.7
|
||||||
|
RUN apk --no-cache add ca-certificates
|
||||||
|
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /go/bin/HamsterTycoon .
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
ENTRYPOINT ["/app/HamsterTycoon"]
|
||||||
|
CMD ["serve", "--logformat", "json", "--loglevel", "debug"]
|
||||||
105
Makefile
Normal file
105
Makefile
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# Set an output prefix, which is the local directory if not specified
|
||||||
|
PREFIX?=$(shell pwd)
|
||||||
|
.DEFAULT_GOAL := build
|
||||||
|
|
||||||
|
# Version tag
|
||||||
|
VERSION := 1.0
|
||||||
|
|
||||||
|
# Setup name variables for the package/tool
|
||||||
|
NAME := hamster-tycoon
|
||||||
|
BIN_NAME := HamsterTycoon
|
||||||
|
PKG := github.com/kratisto/hamster-tycoon
|
||||||
|
|
||||||
|
DOCKER_IMAGE_NAME := $(NAME)
|
||||||
|
# GO env vars
|
||||||
|
ifeq ($(GOPATH),)
|
||||||
|
GOPATH:=~/go
|
||||||
|
endif
|
||||||
|
GO=$(firstword $(subst :, ,$(GOPATH)))
|
||||||
|
|
||||||
|
.PHONY: ensure-vendor
|
||||||
|
ensure-vendor: ## Get all vendor dependencies
|
||||||
|
@echo "+ $@"
|
||||||
|
dep ensure
|
||||||
|
|
||||||
|
.PHONY: update-vendor
|
||||||
|
update-vendor: ## Get all vendor dependencies
|
||||||
|
@echo "+ $@"
|
||||||
|
dep ensure -update
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean: local-clean ## Clean your generated files
|
||||||
|
@echo "+ $@"
|
||||||
|
docker image rm poketools:$(VERSION) || true
|
||||||
|
|
||||||
|
.PHONY: local-build
|
||||||
|
local-build: local-clean local-format ## Build locally the binary
|
||||||
|
@echo "+ $@"
|
||||||
|
GO111MODULE=on go build -o $(GO)/bin/$(BIN_NAME) .
|
||||||
|
|
||||||
|
.PHONY: local-clean
|
||||||
|
local-clean: ## Cleanup locally any build binaries or packages
|
||||||
|
@echo "+ $@"
|
||||||
|
@$(RM) $(BIN_NAME)
|
||||||
|
|
||||||
|
.PHONY: local-format
|
||||||
|
local-format: ## format locally all files
|
||||||
|
@echo "+ $@"
|
||||||
|
gofmt -s -l -w .
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build: sources-image ## Build the docker image with application binary
|
||||||
|
@echo "+ $@"
|
||||||
|
docker build --no-cache \
|
||||||
|
-f containers/Dockerfile \
|
||||||
|
--build-arg SOURCES_IMAGE=$(NAME)-sources:$(VERSION) \
|
||||||
|
-t poketools:$(VERSION) .
|
||||||
|
|
||||||
|
GIT_CREDENTIALS?=$(shell cat ~/.git-credentials 2> /dev/null)
|
||||||
|
.PHONY: sources-image
|
||||||
|
sources-image: ## Generate a Docker image with only the sources
|
||||||
|
@echo "+ $@"
|
||||||
|
docker build -t $(NAME)-sources:$(VERSION) -f containers/Dockerfile.sources .
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: local-run-dependencies
|
||||||
|
local-run-dependencies: ## Run the dependencies of the server (launch the containers/docker-compose.local.yml)
|
||||||
|
@echo "+ $@"
|
||||||
|
@docker-compose -p $(DOCKER_IMAGE_NAME)-uuid -f containers/docker-compose.local.yml down || true;
|
||||||
|
@docker-compose -p $(DOCKER_IMAGE_NAME)-uuid -f containers/docker-compose.local.yml pull;
|
||||||
|
@docker-compose -p $(DOCKER_IMAGE_NAME)-uuid -f containers/docker-compose.local.yml up -d --build
|
||||||
|
|
||||||
|
.PHONY: local-run-golang
|
||||||
|
local-run-golang: ## Build the server and run it
|
||||||
|
@echo "+ $@"
|
||||||
|
BUILD_GOLANG_CMD=local-build \
|
||||||
|
LAUNCH_GOLANG_CMD="$(GO)/bin/$(BIN_NAME)" \
|
||||||
|
$(MAKE) local-launch-golang
|
||||||
|
|
||||||
|
.PHONY: local-launch-golang
|
||||||
|
local-launch-golang: ## Build the server and run it
|
||||||
|
@echo "+ $@"
|
||||||
|
PID=`ps -ax | egrep "\b$(BIN_NAME)"| cut -d " " -f 1`; \
|
||||||
|
kill $$PID || true
|
||||||
|
$(MAKE) $(BUILD_GOLANG_CMD)
|
||||||
|
DB_PORT=`docker-compose -p $(DOCKER_IMAGE_NAME)-uuid -f containers/docker-compose.local.yml port database 5432 | cut -f2 -d':'`; \
|
||||||
|
$(LAUNCH_GOLANG_CMD) serve --loglevel debug --logformat text --postgreshost localhost:$$DB_PORT
|
||||||
|
|
||||||
|
.PHONY: local-run
|
||||||
|
local-run: local-run-dependencies local-run-golang ## Run the server with its dependencies
|
||||||
|
|
||||||
|
.PHONY: local-run-app
|
||||||
|
local-run-app: ## Run the app of the server (launch the containers/docker-compose.yml)
|
||||||
|
@echo "+ $@"
|
||||||
|
@docker-compose -p $(DOCKER_IMAGE_NAME)-uuid -f containers/docker-compose.yml down || true;
|
||||||
|
@docker-compose -p $(DOCKER_IMAGE_NAME)-uuid -f containers/docker-compose.yml pull;
|
||||||
|
@docker-compose -p $(DOCKER_IMAGE_NAME)-uuid -f containers/docker-compose.yml up -d --build
|
||||||
|
|
||||||
|
.PHONY: bdd-test
|
||||||
|
bdd-test: local-run-app
|
||||||
|
go get github.com/DATA-DOG/godog/cmd/godog
|
||||||
|
DB_PORT=`docker-compose -p $(DOCKER_IMAGE_NAME)-uuid -f containers/docker-compose.yml port database 5432 | cut -f2 -d':'`;
|
||||||
|
API_PORT=`docker-compose -p $(DOCKER_IMAGE_NAME)-uuid -f containers/docker-compose.yml port api 8080 | cut -f2 -d':'`;
|
||||||
|
$GOPATH/bin/godog
|
||||||
|
|
||||||
|
|
||||||
8
containers/docker-compose.yml
Normal file
8
containers/docker-compose.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
version: "2.1"
|
||||||
|
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
build: ../.
|
||||||
|
ports:
|
||||||
|
- 8080
|
||||||
|
|
||||||
2
go.mod
2
go.mod
@@ -1,3 +1,5 @@
|
|||||||
module hamster-tycoon
|
module hamster-tycoon
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
|
require github.com/DATA-DOG/godog v0.7.13
|
||||||
|
|||||||
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
github.com/DATA-DOG/godog v0.7.13 h1:JmgpKcra7Vf3yzI9vPsWyoQRx13tyKziHtXWDCUUgok=
|
||||||
|
github.com/DATA-DOG/godog v0.7.13/go.mod h1:z2OZ6a3X0/YAKVqLfVzYBwFt3j6uSt3Xrqa7XTtcQE0=
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package hamster_tycoon
|
package hamster_tycoon
|
||||||
|
|
||||||
|
|
||||||
type Cage struct {
|
type Cage struct {
|
||||||
Hamsters []*Hamster
|
Hamsters []*Hamster
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package hamster_tycoon
|
package hamster_tycoon
|
||||||
|
|
||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
Cages []*Cage
|
Cages []*Cage
|
||||||
SelledHamster []*Hamster
|
SelledHamster []*Hamster
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -15,44 +15,43 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TotalGestationPeriod = 15
|
TotalGestationPeriod = 15
|
||||||
MinChild = 5
|
MinChild = 5
|
||||||
MaxCild = 9
|
MaxCild = 9
|
||||||
GestationCooldown = (3*7) + 2
|
GestationCooldown = (3 * 7) + 2
|
||||||
GestationMinAge = 10*6
|
GestationMinAge = 10 * 6
|
||||||
MaxAge = 365*2
|
MaxAge = 365 * 2
|
||||||
GestationLuck = 70
|
GestationLuck = 70
|
||||||
FEMALE = "F"
|
FEMALE = "F"
|
||||||
MALE = "M"
|
MALE = "M"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var GlobalHamsterNumber = 1
|
var GlobalHamsterNumber = 1
|
||||||
|
|
||||||
type Hamster struct {
|
type Hamster struct {
|
||||||
Name string
|
Name string
|
||||||
Number int
|
Number int
|
||||||
Sexe string
|
Sexe string
|
||||||
Age int
|
Age int
|
||||||
Father *Hamster
|
Father *Hamster
|
||||||
Mother *Hamster
|
Mother *Hamster
|
||||||
HungerLevel int8
|
HungerLevel int8
|
||||||
ThirstLevel int8
|
ThirstLevel int8
|
||||||
Weight float64
|
Weight float64
|
||||||
Height float64
|
Height float64
|
||||||
Alive bool
|
Alive bool
|
||||||
Selled bool
|
Selled bool
|
||||||
Gestation bool
|
Gestation bool
|
||||||
GestationPeriod int8
|
GestationPeriod int8
|
||||||
GestationCooldown int8
|
GestationCooldown int8
|
||||||
Child []*Hamster
|
Child []*Hamster
|
||||||
}
|
}
|
||||||
|
|
||||||
func(h *Hamster) Die(){
|
func (h *Hamster) Die() {
|
||||||
h.Alive = false
|
h.Alive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hamster) Fuck(another *Hamster) (bool,error){
|
func (h *Hamster) Fuck(another *Hamster) (bool, error) {
|
||||||
if h.Sexe == another.Sexe {
|
if h.Sexe == another.Sexe {
|
||||||
return false, errors.New("can't fuck together")
|
return false, errors.New("can't fuck together")
|
||||||
}
|
}
|
||||||
@@ -61,10 +60,16 @@ func (h *Hamster) Fuck(another *Hamster) (bool,error){
|
|||||||
return false, errors.New("one of the hamster is too young")
|
return false, errors.New("one of the hamster is too young")
|
||||||
}
|
}
|
||||||
|
|
||||||
rand := randNumber(1,100)
|
rand := randNumber(1, 100)
|
||||||
|
|
||||||
if rand <= GestationLuck {
|
if rand <= GestationLuck {
|
||||||
female := func() *Hamster{if h.Sexe == FEMALE {return h } else {return another}}()
|
female := func() *Hamster {
|
||||||
|
if h.Sexe == FEMALE {
|
||||||
|
return h
|
||||||
|
} else {
|
||||||
|
return another
|
||||||
|
}
|
||||||
|
}()
|
||||||
female.Gestation = true
|
female.Gestation = true
|
||||||
female.GestationPeriod = 0
|
female.GestationPeriod = 0
|
||||||
female.GestationCooldown = TotalGestationPeriod + GestationCooldown
|
female.GestationCooldown = TotalGestationPeriod + GestationCooldown
|
||||||
@@ -72,7 +77,7 @@ func (h *Hamster) Fuck(another *Hamster) (bool,error){
|
|||||||
return rand <= GestationLuck, nil
|
return rand <= GestationLuck, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Born(father *Hamster, mother *Hamster)([]*Hamster,error){
|
func Born(father *Hamster, mother *Hamster) ([]*Hamster, error) {
|
||||||
if !mother.Alive || mother.Selled {
|
if !mother.Alive || mother.Selled {
|
||||||
return nil, errors.New("the mother is not here")
|
return nil, errors.New("the mother is not here")
|
||||||
}
|
}
|
||||||
@@ -85,43 +90,43 @@ func Born(father *Hamster, mother *Hamster)([]*Hamster,error){
|
|||||||
mother.GestationPeriod = 0
|
mother.GestationPeriod = 0
|
||||||
|
|
||||||
numberOfChild := randNumberChild()
|
numberOfChild := randNumberChild()
|
||||||
child := make([]*Hamster,numberOfChild)
|
child := make([]*Hamster, numberOfChild)
|
||||||
for i := 1; i <= numberOfChild; i++{
|
for i := 1; i <= numberOfChild; i++ {
|
||||||
child[i] = &Hamster{
|
child[i] = &Hamster{
|
||||||
Name: fmt.Sprintf("Hamster %d",GlobalHamsterNumber),
|
Name: fmt.Sprintf("Hamster %d", GlobalHamsterNumber),
|
||||||
Number: GlobalHamsterNumber,
|
Number: GlobalHamsterNumber,
|
||||||
Age : 1,
|
Age: 1,
|
||||||
Sexe: randSexe(),
|
Sexe: randSexe(),
|
||||||
Father: father,
|
Father: father,
|
||||||
Mother: mother,
|
Mother: mother,
|
||||||
HungerLevel: Full,
|
HungerLevel: Full,
|
||||||
ThirstLevel: Full,
|
ThirstLevel: Full,
|
||||||
Alive: true,
|
Alive: true,
|
||||||
Selled: false,
|
Selled: false,
|
||||||
Gestation: false,
|
Gestation: false,
|
||||||
GestationPeriod: 0,
|
GestationPeriod: 0,
|
||||||
GestationCooldown: 30,
|
GestationCooldown: 30,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mother.Child = append(mother.Child, child...)
|
mother.Child = append(mother.Child, child...)
|
||||||
father.Child = append(father.Child, child...)
|
father.Child = append(father.Child, child...)
|
||||||
return child,nil
|
return child, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func randNumberChild() int {
|
func randNumberChild() int {
|
||||||
return randNumber(MinChild,MaxCild)
|
return randNumber(MinChild, MaxCild)
|
||||||
}
|
}
|
||||||
|
|
||||||
func randSexe() string {
|
func randSexe() string {
|
||||||
return func () string{
|
return func() string {
|
||||||
if randNumber(1,2) == 2 {
|
if randNumber(1, 2) == 2 {
|
||||||
return MALE
|
return MALE
|
||||||
} else {
|
} else {
|
||||||
return FEMALE
|
return FEMALE
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func randNumber(min int ,max int) int {
|
func randNumber(min int, max int) int {
|
||||||
return min + rand.Intn(max-min)
|
return min + rand.Intn(max-min)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
|
|
||||||
func TestDie(t *testing.T) {
|
func TestDie(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
caseName string
|
caseName string
|
||||||
hamster *Hamster
|
hamster *Hamster
|
||||||
expectedAlive bool
|
expectedAlive bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -39,41 +39,41 @@ func TestDie(t *testing.T) {
|
|||||||
|
|
||||||
func TestFuck(t *testing.T) {
|
func TestFuck(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
caseName string
|
caseName string
|
||||||
hamster1 *Hamster
|
hamster1 *Hamster
|
||||||
hamster2 *Hamster
|
hamster2 *Hamster
|
||||||
expectedResult bool
|
expectedResult bool
|
||||||
expectedError error
|
expectedError error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
caseName: "Hamster 1 too young",
|
caseName: "Hamster 1 too young",
|
||||||
hamster1: &Hamster{
|
hamster1: &Hamster{
|
||||||
Alive: true,
|
Alive: true,
|
||||||
Sexe: MALE,
|
Sexe: MALE,
|
||||||
Age: GestationMinAge - 1,
|
Age: GestationMinAge - 1,
|
||||||
},
|
},
|
||||||
hamster2: &Hamster{
|
hamster2: &Hamster{
|
||||||
Alive: true,
|
Alive: true,
|
||||||
Sexe: FEMALE,
|
Sexe: FEMALE,
|
||||||
Age: GestationMinAge + 1,
|
Age: GestationMinAge + 1,
|
||||||
},
|
},
|
||||||
expectedResult: false,
|
expectedResult: false,
|
||||||
expectedError: errors.New("one of the hamster is too young"),
|
expectedError: errors.New("one of the hamster is too young"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
caseName: "Hamster 2 too young",
|
caseName: "Hamster 2 too young",
|
||||||
hamster1: &Hamster{
|
hamster1: &Hamster{
|
||||||
Alive: false,
|
Alive: false,
|
||||||
Sexe: MALE,
|
Sexe: MALE,
|
||||||
Age: GestationMinAge + 1,
|
Age: GestationMinAge + 1,
|
||||||
},
|
},
|
||||||
hamster2: &Hamster{
|
hamster2: &Hamster{
|
||||||
Alive: true,
|
Alive: true,
|
||||||
Sexe: FEMALE,
|
Sexe: FEMALE,
|
||||||
Age: GestationMinAge - 1,
|
Age: GestationMinAge - 1,
|
||||||
},
|
},
|
||||||
expectedResult: false,
|
expectedResult: false,
|
||||||
expectedError: errors.New("one of the hamster is too young"),
|
expectedError: errors.New("one of the hamster is too young"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
main.go
6
main.go
@@ -1,4 +1,5 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@@ -9,4 +10,9 @@ func main() {
|
|||||||
rand.Seed(time.Now().UTC().UnixNano())
|
rand.Seed(time.Now().UTC().UnixNano())
|
||||||
|
|
||||||
fmt.Print("hello")
|
fmt.Print("hello")
|
||||||
|
|
||||||
|
for {
|
||||||
|
fmt.Println("Infinite Loop 1")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user