commit
46a0dbbd1a
3
.github/ISSUE_TEMPLATE
vendored
3
.github/ISSUE_TEMPLATE
vendored
@ -1,4 +1,4 @@
|
|||||||
**English Only**. Please use English because other could join the discussion if they got similar issue!
|
**English Only**. Please use English because others could join the discussion if they got similar issue!
|
||||||
|
|
||||||
Please answer these questions before submitting your issue. Thanks!
|
Please answer these questions before submitting your issue. Thanks!
|
||||||
|
|
||||||
@ -12,6 +12,7 @@ Please answer these questions before submitting your issue. Thanks!
|
|||||||
If possible, provide a recipe for reproducing the error.
|
If possible, provide a recipe for reproducing the error.
|
||||||
A complete runnable program is good.
|
A complete runnable program is good.
|
||||||
|
|
||||||
|
If this is ORM issue, please provide the DB schemas.
|
||||||
|
|
||||||
4. What did you expect to see?
|
4. What did you expect to see?
|
||||||
|
|
||||||
|
|||||||
17
.github/dependabot.yml
vendored
Normal file
17
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# To get started with Dependabot version updates, you'll need to specify which
|
||||||
|
# package ecosystems to update and where the package manifests are located.
|
||||||
|
# Please see the documentation for all configuration options:
|
||||||
|
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "gomod"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
43
.github/linters/.golangci.yml
vendored
Normal file
43
.github/linters/.golangci.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
run:
|
||||||
|
timeout: 5m
|
||||||
|
skip-files:
|
||||||
|
- generated.*
|
||||||
|
|
||||||
|
issues:
|
||||||
|
new: true
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- asciicheck
|
||||||
|
- bodyclose
|
||||||
|
- deadcode
|
||||||
|
- depguard
|
||||||
|
- gci
|
||||||
|
- gocritic
|
||||||
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- goimports
|
||||||
|
- goprintffuncname
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- misspell
|
||||||
|
- nilerr
|
||||||
|
- rowserrcheck
|
||||||
|
- staticcheck
|
||||||
|
- structcheck
|
||||||
|
- stylecheck
|
||||||
|
- typecheck
|
||||||
|
- unconvert
|
||||||
|
- unused
|
||||||
|
- unparam
|
||||||
|
- varcheck
|
||||||
|
- whitespace
|
||||||
|
disable:
|
||||||
|
- errcheck
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
gci:
|
||||||
|
local-prefixes: github.com/beego/beego
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/beego/beego
|
||||||
34
.github/workflows/changelog.yml
vendored
Normal file
34
.github/workflows/changelog.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# This action requires that any PR targeting the master branch should touch at
|
||||||
|
# least one CHANGELOG file. If a CHANGELOG entry is not required, add the "Skip
|
||||||
|
# Changelog" label to disable this action.
|
||||||
|
|
||||||
|
name: changelog
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened, labeled, unlabeled]
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
changelog:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: "!contains(github.event.pull_request.labels.*.name, 'Skip Changelog')"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Check for CHANGELOG changes
|
||||||
|
run: |
|
||||||
|
# Only the latest commit of the feature branch is available
|
||||||
|
# automatically. To diff with the base branch, we need to
|
||||||
|
# fetch that too (and we only need its latest commit).
|
||||||
|
git fetch origin ${{ github.base_ref }} --depth=1
|
||||||
|
if [[ $(git diff --name-only FETCH_HEAD | grep CHANGELOG) ]]
|
||||||
|
then
|
||||||
|
echo "A CHANGELOG was modified. Looks good!"
|
||||||
|
else
|
||||||
|
echo "No CHANGELOG was modified."
|
||||||
|
echo "Please add a CHANGELOG entry, or add the \"Skip Changelog\" label if not required."
|
||||||
|
false
|
||||||
|
fi
|
||||||
26
.github/workflows/golangci-lint.yml
vendored
Normal file
26
.github/workflows/golangci-lint.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
name: golangci-lint
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths:
|
||||||
|
- "**/*.go"
|
||||||
|
- ".github/workflows/golangci-lint.yml"
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
paths:
|
||||||
|
- "**/*.go"
|
||||||
|
- ".github/workflows/golangci-lint.yml"
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout codebase
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v2
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
args: --config=.github/linters/.golangci.yml
|
||||||
|
only-new-issues: true
|
||||||
19
.github/workflows/need-feedback.yml
vendored
Normal file
19
.github/workflows/need-feedback.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: need-feeback-issues
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 * * * *" # pick a cron here, this is every 1h
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: luanpotter/changes-requested@master
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# these are optional, if you want to configure:
|
||||||
|
days-until-close: 5
|
||||||
|
trigger-label: status/need-feedback
|
||||||
|
closing-comment: This issue was closed by the need-feedback bot due to without feebacks.
|
||||||
|
dry-run: false
|
||||||
19
.github/workflows/need-translation.yml
vendored
Normal file
19
.github/workflows/need-translation.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: need-translation-issues
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 * * * *" # pick a cron here, this is every 1h
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: luanpotter/changes-requested@master
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# these are optional, if you want to configure:
|
||||||
|
days-until-close: 5
|
||||||
|
trigger-label: status/need-translation
|
||||||
|
closing-comment: This issue was closed by the need-translation bot. Please transalate your issue to English so it could help others.
|
||||||
|
dry-run: false
|
||||||
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v1
|
- uses: actions/stale@v4
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
stale-issue-message: 'This issue is inactive for a long time.'
|
stale-issue-message: 'This issue is inactive for a long time.'
|
||||||
|
|||||||
124
.github/workflows/test.yml
vendored
Normal file
124
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
name: Test
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- develop
|
||||||
|
paths:
|
||||||
|
- "**/*.go"
|
||||||
|
- "go.mod"
|
||||||
|
- "go.sum"
|
||||||
|
- ".github/workflows/test.yml"
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- develop
|
||||||
|
paths:
|
||||||
|
- "**/*.go"
|
||||||
|
- "go.mod"
|
||||||
|
- "go.sum"
|
||||||
|
- ".github/workflows/test.yml"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
go-version: [1.14, 1.15, 1.16]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis:latest
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
memcached:
|
||||||
|
image: memcached:latest
|
||||||
|
ports:
|
||||||
|
- 11211:11211
|
||||||
|
ssdb:
|
||||||
|
image: wendal/ssdb:latest
|
||||||
|
ports:
|
||||||
|
- 8888:8888
|
||||||
|
postgres:
|
||||||
|
image: postgres:latest
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: orm_test
|
||||||
|
ports:
|
||||||
|
- 5432/tcp
|
||||||
|
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go-version }}
|
||||||
|
|
||||||
|
- name: Checkout codebase
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Run etcd
|
||||||
|
env:
|
||||||
|
ETCD_VERSION: v3.4.16
|
||||||
|
run: |
|
||||||
|
rm -rf /tmp/etcd-data.tmp
|
||||||
|
mkdir -p /tmp/etcd-data.tmp
|
||||||
|
docker rmi gcr.io/etcd-development/etcd:${ETCD_VERSION} || true && \
|
||||||
|
docker run -d \
|
||||||
|
-p 2379:2379 \
|
||||||
|
-p 2380:2380 \
|
||||||
|
--mount type=bind,source=/tmp/etcd-data.tmp,destination=/etcd-data \
|
||||||
|
--name etcd-gcr-${ETCD_VERSION} \
|
||||||
|
gcr.io/etcd-development/etcd:${ETCD_VERSION} \
|
||||||
|
/usr/local/bin/etcd \
|
||||||
|
--name s1 \
|
||||||
|
--data-dir /etcd-data \
|
||||||
|
--listen-client-urls http://0.0.0.0:2379 \
|
||||||
|
--advertise-client-urls http://0.0.0.0:2379 \
|
||||||
|
--listen-peer-urls http://0.0.0.0:2380 \
|
||||||
|
--initial-advertise-peer-urls http://0.0.0.0:2380 \
|
||||||
|
--initial-cluster s1=http://0.0.0.0:2380 \
|
||||||
|
--initial-cluster-token tkn \
|
||||||
|
--initial-cluster-state new
|
||||||
|
docker exec etcd-gcr-${ETCD_VERSION} /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.float 1.23"
|
||||||
|
docker exec etcd-gcr-${ETCD_VERSION} /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.bool true"
|
||||||
|
docker exec etcd-gcr-${ETCD_VERSION} /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.int 11"
|
||||||
|
docker exec etcd-gcr-${ETCD_VERSION} /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.string hello"
|
||||||
|
docker exec etcd-gcr-${ETCD_VERSION} /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.serialize.name test"
|
||||||
|
docker exec etcd-gcr-${ETCD_VERSION} /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put sub.sub.key1 sub.sub.key"
|
||||||
|
|
||||||
|
- name: Run ORM tests on sqlite3
|
||||||
|
env:
|
||||||
|
GOPATH: /home/runner/go
|
||||||
|
ORM_DRIVER: sqlite3
|
||||||
|
ORM_SOURCE: /tmp/sqlite3/orm_test.db
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/sqlite3 && touch /tmp/sqlite3/orm_test.db
|
||||||
|
go test -coverprofile=coverage_sqlite3.txt -covermode=atomic $(go list ./... | grep client/orm)
|
||||||
|
|
||||||
|
- name: Run ORM tests on postgres
|
||||||
|
env:
|
||||||
|
GOPATH: /home/runner/go
|
||||||
|
ORM_DRIVER: postgres
|
||||||
|
ORM_SOURCE: host=localhost port=${{ job.services.postgres.ports[5432] }} user=postgres password=postgres dbname=orm_test sslmode=disable
|
||||||
|
run: |
|
||||||
|
go test -coverprofile=coverage_postgres.txt -covermode=atomic $(go list ./... | grep client/orm)
|
||||||
|
|
||||||
|
- name: Run tests on mysql
|
||||||
|
env:
|
||||||
|
GOPATH: /home/runner/go
|
||||||
|
ORM_DRIVER: mysql
|
||||||
|
ORM_SOURCE: root:root@/orm_test?charset=utf8
|
||||||
|
run: |
|
||||||
|
sudo systemctl start mysql
|
||||||
|
mysql -u root -proot -e 'create database orm_test;'
|
||||||
|
go test -coverprofile=coverage.txt -covermode=atomic ./...
|
||||||
|
|
||||||
|
- name: Upload codecov
|
||||||
|
env:
|
||||||
|
CODECOV_TOKEN: 4f4bc484-32a8-43b7-9f48-20966bd48ceb
|
||||||
|
run: bash <(curl -s https://codecov.io/bash)
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
@ -10,3 +10,8 @@ _beeTmp2/
|
|||||||
pkg/_beeTmp/
|
pkg/_beeTmp/
|
||||||
pkg/_beeTmp2/
|
pkg/_beeTmp2/
|
||||||
test/tmp/
|
test/tmp/
|
||||||
|
core/config/env/pkg/
|
||||||
|
|
||||||
|
my save path/
|
||||||
|
|
||||||
|
profile.out
|
||||||
|
|||||||
105
.travis.yml
105
.travis.yml
@ -1,105 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "1.14.x"
|
|
||||||
services:
|
|
||||||
- redis-server
|
|
||||||
- mysql
|
|
||||||
- postgresql
|
|
||||||
- memcached
|
|
||||||
- docker
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- GO_REPO_FULLNAME="github.com/beego/beego/v2"
|
|
||||||
matrix:
|
|
||||||
- ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db
|
|
||||||
- ORM_DRIVER=postgres ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable"
|
|
||||||
- ORM_DRIVER=mysql export ORM_SOURCE="root:@/orm_test?charset=utf8"
|
|
||||||
before_install:
|
|
||||||
# link the local repo with ${GOPATH}/src/<namespace>/<repo>
|
|
||||||
- GO_REPO_NAMESPACE=${GO_REPO_FULLNAME%/*}
|
|
||||||
# relies on GOPATH to contain only one directory...
|
|
||||||
- mkdir -p ${GOPATH}/src/${GO_REPO_NAMESPACE}
|
|
||||||
- ln -sv ${TRAVIS_BUILD_DIR} ${GOPATH}/src/${GO_REPO_FULLNAME}
|
|
||||||
- cd ${GOPATH}/src/${GO_REPO_FULLNAME}
|
|
||||||
# get and build ssdb
|
|
||||||
- git clone git://github.com/ideawu/ssdb.git
|
|
||||||
- cd ssdb
|
|
||||||
- make
|
|
||||||
- cd ..
|
|
||||||
# - prepare etcd
|
|
||||||
# - prepare for etcd unit tests
|
|
||||||
- rm -rf /tmp/etcd-data.tmp
|
|
||||||
- mkdir -p /tmp/etcd-data.tmp
|
|
||||||
- docker rmi gcr.io/etcd-development/etcd:v3.3.25 || true &&
|
|
||||||
docker run -d
|
|
||||||
-p 2379:2379
|
|
||||||
-p 2380:2380
|
|
||||||
--mount type=bind,source=/tmp/etcd-data.tmp,destination=/etcd-data
|
|
||||||
--name etcd-gcr-v3.3.25
|
|
||||||
gcr.io/etcd-development/etcd:v3.3.25
|
|
||||||
/usr/local/bin/etcd
|
|
||||||
--name s1
|
|
||||||
--data-dir /etcd-data
|
|
||||||
--listen-client-urls http://0.0.0.0:2379
|
|
||||||
--advertise-client-urls http://0.0.0.0:2379
|
|
||||||
--listen-peer-urls http://0.0.0.0:2380
|
|
||||||
--initial-advertise-peer-urls http://0.0.0.0:2380
|
|
||||||
--initial-cluster s1=http://0.0.0.0:2380
|
|
||||||
--initial-cluster-token tkn
|
|
||||||
--initial-cluster-state new
|
|
||||||
- docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.float 1.23"
|
|
||||||
- docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.bool true"
|
|
||||||
- docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.int 11"
|
|
||||||
- docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.string hello"
|
|
||||||
- docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put current.serialize.name test"
|
|
||||||
- docker exec etcd-gcr-v3.3.25 /bin/sh -c "ETCDCTL_API=3 /usr/local/bin/etcdctl put sub.sub.key1 sub.sub.key"
|
|
||||||
install:
|
|
||||||
- go get github.com/lib/pq
|
|
||||||
- go get github.com/go-sql-driver/mysql
|
|
||||||
- go get github.com/mattn/go-sqlite3
|
|
||||||
- go get github.com/bradfitz/gomemcache/memcache
|
|
||||||
- go get github.com/gomodule/redigo/redis
|
|
||||||
- go get github.com/beego/x2j
|
|
||||||
- go get github.com/couchbase/go-couchbase
|
|
||||||
- go get github.com/beego/goyaml2
|
|
||||||
- go get gopkg.in/yaml.v2
|
|
||||||
- go get github.com/belogik/goes
|
|
||||||
- go get github.com/ledisdb/ledisdb
|
|
||||||
- go get github.com/ssdb/gossdb/ssdb
|
|
||||||
- go get github.com/cloudflare/golz4
|
|
||||||
- go get github.com/gogo/protobuf/proto
|
|
||||||
- go get github.com/Knetic/govaluate
|
|
||||||
- go get github.com/casbin/casbin
|
|
||||||
- go get github.com/elazarl/go-bindata-assetfs
|
|
||||||
- go get github.com/OwnLocal/goes
|
|
||||||
- go get github.com/shiena/ansicolor
|
|
||||||
- go get -u honnef.co/go/tools/cmd/staticcheck
|
|
||||||
- go get -u github.com/mdempsky/unconvert
|
|
||||||
- go get -u github.com/gordonklaus/ineffassign
|
|
||||||
- go get -u golang.org/x/lint/golint
|
|
||||||
- go get -u github.com/go-redis/redis
|
|
||||||
before_script:
|
|
||||||
|
|
||||||
# -
|
|
||||||
- psql --version
|
|
||||||
# - prepare for orm unit tests
|
|
||||||
- sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi"
|
|
||||||
- sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi"
|
|
||||||
- sh -c "if [ '$ORM_DRIVER' = 'sqlite' ]; then touch $TRAVIS_BUILD_DIR/orm_test.db; fi"
|
|
||||||
- sh -c "go get github.com/golang/lint/golint; golint ./...;"
|
|
||||||
- sh -c "go list ./... | grep -v vendor | xargs go vet -v"
|
|
||||||
- mkdir -p res/var
|
|
||||||
- ./ssdb/ssdb-server ./ssdb/ssdb.conf -d
|
|
||||||
after_script:
|
|
||||||
- killall -w ssdb-server
|
|
||||||
- rm -rf ./res/var/*
|
|
||||||
script:
|
|
||||||
- go test ./...
|
|
||||||
- staticcheck -show-ignored -checks "-ST1017,-U1000,-ST1005,-S1034,-S1012,-SA4006,-SA6005,-SA1019,-SA1024" ./
|
|
||||||
- unconvert $(go list ./... | grep -v /vendor/)
|
|
||||||
- ineffassign .
|
|
||||||
- find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s
|
|
||||||
- golint ./...
|
|
||||||
addons:
|
|
||||||
postgresql: "9.6"
|
|
||||||
83
CHANGELOG.md
83
CHANGELOG.md
@ -1,4 +1,28 @@
|
|||||||
# developing
|
# developing
|
||||||
|
|
||||||
|
- Add a custom option for whether to escape HTML special characters when processing http request parameters. [4701](https://github.com/beego/beego/pull/4701)
|
||||||
|
- Always set the response status in the CustomAbort function. [4686](https://github.com/beego/beego/pull/4686)
|
||||||
|
- Add template functions eq,lt to support uint and int compare. [4607](https://github.com/beego/beego/pull/4607)
|
||||||
|
- Migrate tests to GitHub Actions. [4663](https://github.com/beego/beego/issues/4663)
|
||||||
|
- Add http client and option func. [4455](https://github.com/beego/beego/issues/4455)
|
||||||
|
- Add: Convenient way to generate mock object [4620](https://github.com/beego/beego/issues/4620)
|
||||||
|
- Infra: use dependabot to update dependencies. [4623](https://github.com/beego/beego/pull/4623)
|
||||||
|
- Lint: use golangci-lint. [4619](https://github.com/beego/beego/pull/4619)
|
||||||
|
- Chore: format code. [4615](https://github.com/beego/beego/pull/4615)
|
||||||
|
- Test on Go v1.15.x & v1.16.x. [4614](https://github.com/beego/beego/pull/4614)
|
||||||
|
- Env: non-empty GOBIN & GOPATH. [4613](https://github.com/beego/beego/pull/4613)
|
||||||
|
- Chore: update dependencies. [4611](https://github.com/beego/beego/pull/4611)
|
||||||
|
- Update orm_test.go/TestInsertOrUpdate with table-driven. [4609](https://github.com/beego/beego/pull/4609)
|
||||||
|
- Add: Resp() method for web.Controller. [4588](https://github.com/beego/beego/pull/4588)
|
||||||
|
- Web mock and test support. [4565](https://github.com/beego/beego/pull/4565) [4574](https://github.com/beego/beego/pull/4574)
|
||||||
|
- Error codes definition of cache module. [4493](https://github.com/beego/beego/pull/4493)
|
||||||
|
- Remove generateCommentRoute http hook. Using `bee generate routers` commands instead.[4486](https://github.com/beego/beego/pull/4486) [bee PR 762](https://github.com/beego/bee/pull/762)
|
||||||
|
- Fix: /abc.html/aaa match /abc/aaa. [4459](https://github.com/beego/beego/pull/4459)
|
||||||
|
- ORM mock. [4407](https://github.com/beego/beego/pull/4407)
|
||||||
|
- Add sonar check and ignore test. [4432](https://github.com/beego/beego/pull/4432) [4433](https://github.com/beego/beego/pull/4433)
|
||||||
|
- Update changlog.yml to check every PR to develop branch.[4427](https://github.com/beego/beego/pull/4427)
|
||||||
|
- Fix 4396: Add context.param module into adapter. [4398](https://github.com/beego/beego/pull/4398)
|
||||||
|
- Support `RollbackUnlessCommit` API. [4542](https://github.com/beego/beego/pull/4542)
|
||||||
- Fix 4503 and 4504: Add `when` to `Write([]byte)` method and add `prefix` to `writeMsg`. [4507](https://github.com/beego/beego/pull/4507)
|
- Fix 4503 and 4504: Add `when` to `Write([]byte)` method and add `prefix` to `writeMsg`. [4507](https://github.com/beego/beego/pull/4507)
|
||||||
- Fix 4480: log format incorrect. [4482](https://github.com/beego/beego/pull/4482)
|
- Fix 4480: log format incorrect. [4482](https://github.com/beego/beego/pull/4482)
|
||||||
- Remove `duration` from prometheus labels. [4391](https://github.com/beego/beego/pull/4391)
|
- Remove `duration` from prometheus labels. [4391](https://github.com/beego/beego/pull/4391)
|
||||||
@ -7,6 +31,65 @@
|
|||||||
- Fix 4727: CSS when request URI is invalid. [4729](https://github.com/beego/beego/pull/4729)
|
- Fix 4727: CSS when request URI is invalid. [4729](https://github.com/beego/beego/pull/4729)
|
||||||
- Using fixed name `commentRouter.go` as generated file name. [4385](https://github.com/beego/beego/pull/4385)
|
- Using fixed name `commentRouter.go` as generated file name. [4385](https://github.com/beego/beego/pull/4385)
|
||||||
- Fix 4383: ORM Adapter produces panic when using orm.RegisterModelWithPrefix. [4386](https://github.com/beego/beego/pull/4386)
|
- Fix 4383: ORM Adapter produces panic when using orm.RegisterModelWithPrefix. [4386](https://github.com/beego/beego/pull/4386)
|
||||||
|
- Support 4144: Add new api for order by for supporting multiple way to query [4294](https://github.com/beego/beego/pull/4294)
|
||||||
|
- Support session Filter chain. [4404](https://github.com/beego/beego/pull/4404)
|
||||||
|
- Feature issue #4402 finish router get example. [4416](https://github.com/beego/beego/pull/4416)
|
||||||
|
- Implement context.Context support and deprecate `QueryM2MWithCtx` and `QueryTableWithCtx` [4424](https://github.com/beego/beego/pull/4424)
|
||||||
|
- Finish timeout option for tasks #4441 [4441](https://github.com/beego/beego/pull/4441)
|
||||||
|
- Error Module brief design & using httplib module to validate this design. [4453](https://github.com/beego/beego/pull/4453)
|
||||||
- Fix 4444: panic when 404 not found. [4446](https://github.com/beego/beego/pull/4446)
|
- Fix 4444: panic when 404 not found. [4446](https://github.com/beego/beego/pull/4446)
|
||||||
- Fix 4435: fix panic when controller dir not found. [4452](https://github.com/beego/beego/pull/4452)
|
- Fix 4435: fix panic when controller dir not found. [4452](https://github.com/beego/beego/pull/4452)
|
||||||
- Hotfix:reflect.ValueOf(nil) in getFlatParams [4716](https://github.com/beego/beego/issues/4716)
|
- Hotfix:reflect.ValueOf(nil) in getFlatParams [4716](https://github.com/beego/beego/issues/4716)
|
||||||
|
- Fix 4456: Fix router method expression [4456](https://github.com/beego/beego/pull/4456)
|
||||||
|
- Remove some `go get` lines in `.travis.yml` file [4469](https://github.com/beego/beego/pull/4469)
|
||||||
|
- Fix 4451: support QueryExecutor interface. [4461](https://github.com/beego/beego/pull/4461)
|
||||||
|
- Add some testing scripts [4461](https://github.com/beego/beego/pull/4461)
|
||||||
|
- Refactor httplib: Move debug code to a filter [4440](https://github.com/beego/beego/issues/4440)
|
||||||
|
- fix: code quality issues [4513](https://github.com/beego/beego/pull/4513)
|
||||||
|
- Optimize maligned structs to reduce memory foot-print [4525](https://github.com/beego/beego/pull/4525)
|
||||||
|
- Feat: add token bucket ratelimit filter [4508](https://github.com/beego/beego/pull/4508)
|
||||||
|
- Improve: Avoid ignoring mistakes that need attention [4548](https://github.com/beego/beego/pull/4548)
|
||||||
|
- Integration: DeepSource [4560](https://github.com/beego/beego/pull/4560)
|
||||||
|
- Integration: Remove unnecessary function call [4577](https://github.com/beego/beego/pull/4577)
|
||||||
|
- Feature issue #4402 finish router get example. [4416](https://github.com/beego/beego/pull/4416)
|
||||||
|
- Proposal: Add Bind() method for `web.Controller` [4491](https://github.com/beego/beego/issues/4579)
|
||||||
|
- Optimize AddAutoPrefix: only register one router in case-insensitive mode. [4582](https://github.com/beego/beego/pull/4582)
|
||||||
|
- Init exceptMethod by using reflection. [4583](https://github.com/beego/beego/pull/4583)
|
||||||
|
- Deprecated BeeMap and replace all usage with `sync.map` [4616](https://github.com/beego/beego/pull/4616)
|
||||||
|
- TaskManager support graceful shutdown [4635](https://github.com/beego/beego/pull/4635)
|
||||||
|
- Add comments to `web.Config`, rename `RouterXXX` to `CtrlXXX`, define `HandleFunc` [4714](https://github.com/beego/beego/pull/4714)
|
||||||
|
- Refactor: Move `BindXXX` and `XXXResp` methods to `context.Context`. [4718](https://github.com/beego/beego/pull/4718)
|
||||||
|
- Fix 4728: Print wrong file name. [4737](https://github.com/beego/beego/pull/4737)
|
||||||
|
- fix bug:reflect.ValueOf(nil) in getFlatParams [4715](https://github.com/beego/beego/pull/4715)
|
||||||
|
- Fix 4736: set a fixed value "/" to the "Path" of "_xsrf" cookie. [4736](https://github.com/beego/beego/issues/4735) [4739](https://github.com/beego/beego/issues/4739)
|
||||||
|
- Fix 4734: do not reset id in Delete function. [4738](https://github.com/beego/beego/pull/4738) [4742](https://github.com/beego/beego/pull/4742)
|
||||||
|
- Fix 4699: Remove Remove goyaml2 dependency. [4755](https://github.com/beego/beego/pull/4755)
|
||||||
|
- Fix 4698: Prompt error when config format is incorrect. [4757](https://github.com/beego/beego/pull/4757)
|
||||||
|
- Fix 4674: Tx Orm missing debug log [4756](https://github.com/beego/beego/pull/4756)
|
||||||
|
- Fix 4759: fix numeric notation of permissions [4759](https://github.com/beego/beego/pull/4759)
|
||||||
|
## Fix Sonar
|
||||||
|
|
||||||
|
- [4677](https://github.com/beego/beego/pull/4677)
|
||||||
|
- [4624](https://github.com/beego/beego/pull/4624)
|
||||||
|
- [4608](https://github.com/beego/beego/pull/4608)
|
||||||
|
- [4473](https://github.com/beego/beego/pull/4473)
|
||||||
|
- [4474](https://github.com/beego/beego/pull/4474)
|
||||||
|
- [4479](https://github.com/beego/beego/pull/4479)
|
||||||
|
- [4639](https://github.com/beego/beego/pull/4639)
|
||||||
|
- [4668](https://github.com/beego/beego/pull/4668)
|
||||||
|
|
||||||
|
## Fix lint and format code
|
||||||
|
|
||||||
|
- [4644](https://github.com/beego/beego/pull/4644)
|
||||||
|
- [4645](https://github.com/beego/beego/pull/4645)
|
||||||
|
- [4646](https://github.com/beego/beego/pull/4646)
|
||||||
|
- [4647](https://github.com/beego/beego/pull/4647)
|
||||||
|
- [4648](https://github.com/beego/beego/pull/4648)
|
||||||
|
- [4649](https://github.com/beego/beego/pull/4649)
|
||||||
|
- [4651](https://github.com/beego/beego/pull/4651)
|
||||||
|
- [4652](https://github.com/beego/beego/pull/4652)
|
||||||
|
- [4653](https://github.com/beego/beego/pull/4653)
|
||||||
|
- [4654](https://github.com/beego/beego/pull/4654)
|
||||||
|
- [4655](https://github.com/beego/beego/pull/4655)
|
||||||
|
- [4656](https://github.com/beego/beego/pull/4656)
|
||||||
|
- [4660](https://github.com/beego/beego/pull/4660)
|
||||||
|
|||||||
@ -36,7 +36,7 @@ We provide docker compose file to start all middlewares.
|
|||||||
You can run:
|
You can run:
|
||||||
|
|
||||||
```shell script
|
```shell script
|
||||||
docker-compose -f scripts/test_docker_compose.yml up -d
|
docker-compose -f scripts/test_docker_compose.yaml up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
Unit tests read addresses from environment, here is an example:
|
Unit tests read addresses from environment, here is an example:
|
||||||
@ -53,7 +53,7 @@ export SSDB_ADDR="192.168.0.105:8888"
|
|||||||
|
|
||||||
### Pull requests
|
### Pull requests
|
||||||
|
|
||||||
First of all. beego follow the gitflow. So please send you pull request to **develop-2** branch. We will close the pull
|
First of all. beego follow the gitflow. So please send you pull request to **develop** branch. We will close the pull
|
||||||
request to master branch.
|
request to master branch.
|
||||||
|
|
||||||
We are always happy to receive pull requests, and do our best to review them as fast as possible. Not sure if that typo
|
We are always happy to receive pull requests, and do our best to review them as fast as possible. Not sure if that typo
|
||||||
|
|||||||
5
ERROR_SPECIFICATION.md
Normal file
5
ERROR_SPECIFICATION.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Error Module
|
||||||
|
|
||||||
|
## Module code
|
||||||
|
- httplib 1
|
||||||
|
- cache 2
|
||||||
19
README.md
19
README.md
@ -1,14 +1,12 @@
|
|||||||
# Beego [](https://travis-ci.org/astaxie/beego) [](http://godoc.org/github.com/beego/beego/v2) [](http://golangfoundation.org) [](https://goreportcard.com/report/github.com/beego/beego/v2)
|
# Beego [](https://github.com/beego/beego/actions/workflows/test.yml) [](https://goreportcard.com/report/github.com/beego/beego) [](https://pkg.go.dev/github.com/beego/beego/v2)
|
||||||
|
|
||||||
Beego is used for rapid development of enterprise application in Go, including RESTful APIs, web apps and backend
|
Beego is used for rapid development of enterprise application in Go, including RESTful APIs, web apps and backend services.
|
||||||
services.
|
|
||||||
|
|
||||||
It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific features such as interfaces and struct
|
It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific features such as interfaces and struct embedding.
|
||||||
embedding.
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Beego is compos of four parts:
|
Beego is composed of four parts:
|
||||||
|
|
||||||
1. Base modules: including log module, config module, governor module;
|
1. Base modules: including log module, config module, governor module;
|
||||||
2. Task: is used for running timed tasks or periodic tasks;
|
2. Task: is used for running timed tasks or periodic tasks;
|
||||||
@ -19,7 +17,7 @@ Beego is compos of four parts:
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
[Officail website](http://beego.me)
|
[Official website](http://beego.me)
|
||||||
|
|
||||||
[Example](https://github.com/beego/beego-example)
|
[Example](https://github.com/beego/beego-example)
|
||||||
|
|
||||||
@ -40,7 +38,7 @@ Beego is compos of four parts:
|
|||||||
|
|
||||||
#### Download and install
|
#### Download and install
|
||||||
|
|
||||||
go get github.com/beego/beego/v2@v2.0.0
|
go get github.com/beego/beego/v2@latest
|
||||||
|
|
||||||
#### Create file `hello.go`
|
#### Create file `hello.go`
|
||||||
|
|
||||||
@ -90,12 +88,11 @@ Congratulations! You've just built your first **beego** app.
|
|||||||
## Community
|
## Community
|
||||||
|
|
||||||
* [http://beego.me/community](http://beego.me/community)
|
* [http://beego.me/community](http://beego.me/community)
|
||||||
* Welcome to join us in Slack: [https://beego.slack.com](https://beego.slack.com), you can get invited
|
* Welcome to join us in Slack: [https://beego.slack.com invite](https://join.slack.com/t/beego/shared_invite/zt-fqlfjaxs-_CRmiITCSbEqQG9NeBqXKA),
|
||||||
from [here](https://github.com/beego/beedoc/issues/232)
|
|
||||||
* QQ Group Group ID:523992905
|
* QQ Group Group ID:523992905
|
||||||
* [Contribution Guide](https://github.com/beego/beedoc/blob/master/en-US/intro/contributing.md).
|
* [Contribution Guide](https://github.com/beego/beedoc/blob/master/en-US/intro/contributing.md).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
beego source code is licensed under the Apache Licence, Version 2.0
|
beego source code is licensed under the Apache Licence, Version 2.0
|
||||||
(http://www.apache.org/licenses/LICENSE-2.0.html).
|
([https://www.apache.org/licenses/LICENSE-2.0.html](https://www.apache.org/licenses/LICENSE-2.0.html)).
|
||||||
|
|||||||
@ -22,10 +22,8 @@ import (
|
|||||||
"github.com/beego/beego/v2/server/web/context"
|
"github.com/beego/beego/v2/server/web/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// BeeApp is an application instance
|
||||||
// BeeApp is an application instance
|
var BeeApp *App
|
||||||
BeeApp *App
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// create beego application
|
// create beego application
|
||||||
@ -139,7 +137,7 @@ func RESTRouter(rootpath string, c ControllerInterface) *App {
|
|||||||
|
|
||||||
// AutoRouter adds defined controller handler to BeeApp.
|
// AutoRouter adds defined controller handler to BeeApp.
|
||||||
// it's same to HttpServer.AutoRouter.
|
// it's same to HttpServer.AutoRouter.
|
||||||
// if beego.AddAuto(&MainContorlller{}) and MainController has methods List and Page,
|
// if beego.AddAuto(&MainController{}) and MainController has methods List and Page,
|
||||||
// visit the url /main/list to exec List function or /main/page to exec Page function.
|
// visit the url /main/list to exec List function or /main/page to exec Page function.
|
||||||
func AutoRouter(c ControllerInterface) *App {
|
func AutoRouter(c ControllerInterface) *App {
|
||||||
return (*App)(web.AutoRouter(c))
|
return (*App)(web.AutoRouter(c))
|
||||||
@ -147,7 +145,7 @@ func AutoRouter(c ControllerInterface) *App {
|
|||||||
|
|
||||||
// AutoPrefix adds controller handler to BeeApp with prefix.
|
// AutoPrefix adds controller handler to BeeApp with prefix.
|
||||||
// it's same to HttpServer.AutoRouterWithPrefix.
|
// it's same to HttpServer.AutoRouterWithPrefix.
|
||||||
// if beego.AutoPrefix("/admin",&MainContorlller{}) and MainController has methods List and Page,
|
// if beego.AutoPrefix("/admin",&MainController{}) and MainController has methods List and Page,
|
||||||
// visit the url /admin/main/list to exec List function or /admin/main/page to exec Page function.
|
// visit the url /admin/main/list to exec List function or /admin/main/page to exec Page function.
|
||||||
func AutoPrefix(prefix string, c ControllerInterface) *App {
|
func AutoPrefix(prefix string, c ControllerInterface) *App {
|
||||||
return (*App)(web.AutoPrefix(prefix, c))
|
return (*App)(web.AutoPrefix(prefix, c))
|
||||||
|
|||||||
@ -36,10 +36,6 @@ type M web.M
|
|||||||
// Hook function to run
|
// Hook function to run
|
||||||
type hookfunc func() error
|
type hookfunc func() error
|
||||||
|
|
||||||
var (
|
|
||||||
hooks = make([]hookfunc, 0) // hook function slice to store the hookfunc
|
|
||||||
)
|
|
||||||
|
|
||||||
// AddAPPStartHook is used to register the hookfunc
|
// AddAPPStartHook is used to register the hookfunc
|
||||||
// The hookfuncs will run in beego.Run()
|
// The hookfuncs will run in beego.Run()
|
||||||
// such as initiating session , starting middleware , building template, starting admin control and so on.
|
// such as initiating session , starting middleware , building template, starting admin control and so on.
|
||||||
|
|||||||
2
adapter/cache/cache.go
vendored
2
adapter/cache/cache.go
vendored
@ -16,7 +16,7 @@
|
|||||||
// Usage:
|
// Usage:
|
||||||
//
|
//
|
||||||
// import(
|
// import(
|
||||||
// "github.com/beego/beego/v2/cache"
|
// "github.com/beego/beego/v2/client/cache"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// bm, err := cache.NewCache("memory", `{"interval":60}`)
|
// bm, err := cache.NewCache("memory", `{"interval":60}`)
|
||||||
|
|||||||
187
adapter/cache/cache_test.go
vendored
187
adapter/cache/cache_test.go
vendored
@ -19,12 +19,16 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const initError = "init err"
|
||||||
|
|
||||||
func TestCacheIncr(t *testing.T) {
|
func TestCacheIncr(t *testing.T) {
|
||||||
bm, err := NewCache("memory", `{"interval":20}`)
|
bm, err := NewCache("memory", `{"interval":20}`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("init err")
|
t.Error(initError)
|
||||||
}
|
}
|
||||||
// timeoutDuration := 10 * time.Second
|
// timeoutDuration := 10 * time.Second
|
||||||
|
|
||||||
@ -45,147 +49,94 @@ func TestCacheIncr(t *testing.T) {
|
|||||||
|
|
||||||
func TestCache(t *testing.T) {
|
func TestCache(t *testing.T) {
|
||||||
bm, err := NewCache("memory", `{"interval":20}`)
|
bm, err := NewCache("memory", `{"interval":20}`)
|
||||||
if err != nil {
|
|
||||||
t.Error("init err")
|
|
||||||
}
|
|
||||||
timeoutDuration := 10 * time.Second
|
|
||||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
assert.Nil(t, err)
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(30 * time.Second)
|
timeoutDuration := 5 * time.Second
|
||||||
|
err = bm.Put("astaxie", 1, timeoutDuration)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
if bm.IsExist("astaxie") {
|
assert.True(t, bm.IsExist("astaxie"))
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
assert.Equal(t, 1, bm.Get("astaxie"))
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Incr("astaxie"); err != nil {
|
time.Sleep(10 * time.Second)
|
||||||
t.Error("Incr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := bm.Get("astaxie"); v.(int) != 2 {
|
assert.False(t, bm.IsExist("astaxie"))
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Decr("astaxie"); err != nil {
|
err = bm.Put("astaxie", 1, timeoutDuration)
|
||||||
t.Error("Decr Error", err)
|
assert.Nil(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
err = bm.Incr("astaxie")
|
||||||
t.Error("get err")
|
assert.Nil(t, err)
|
||||||
}
|
|
||||||
bm.Delete("astaxie")
|
|
||||||
if bm.IsExist("astaxie") {
|
|
||||||
t.Error("delete err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test GetMulti
|
assert.Equal(t, 2, bm.Get("astaxie"))
|
||||||
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
if v := bm.Get("astaxie"); v.(string) != "author" {
|
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
|
assert.Nil(t, bm.Decr("astaxie"))
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
assert.Equal(t, 1, bm.Get("astaxie"))
|
||||||
if !bm.IsExist("astaxie1") {
|
|
||||||
t.Error("check err")
|
assert.Nil(t, bm.Delete("astaxie"))
|
||||||
}
|
|
||||||
|
assert.False(t, bm.IsExist("astaxie"))
|
||||||
|
|
||||||
|
assert.Nil(t, bm.Put("astaxie", "author", timeoutDuration))
|
||||||
|
|
||||||
|
assert.True(t, bm.IsExist("astaxie"))
|
||||||
|
|
||||||
|
assert.Equal(t, "author", bm.Get("astaxie"))
|
||||||
|
|
||||||
|
assert.Nil(t, bm.Put("astaxie1", "author1", timeoutDuration))
|
||||||
|
|
||||||
|
assert.True(t, bm.IsExist("astaxie1"))
|
||||||
|
|
||||||
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
||||||
if len(vv) != 2 {
|
|
||||||
t.Error("GetMulti ERROR")
|
assert.Equal(t, 2, len(vv))
|
||||||
}
|
|
||||||
if vv[0].(string) != "author" {
|
assert.Equal(t, "author", vv[0])
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
assert.Equal(t, "author1", vv[1])
|
||||||
if vv[1].(string) != "author1" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileCache(t *testing.T) {
|
func TestFileCache(t *testing.T) {
|
||||||
bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}`)
|
bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}`)
|
||||||
if err != nil {
|
|
||||||
t.Error("init err")
|
|
||||||
}
|
|
||||||
timeoutDuration := 10 * time.Second
|
|
||||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
assert.Nil(t, err)
|
||||||
t.Error("get err")
|
timeoutDuration := 5 * time.Second
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Incr("astaxie"); err != nil {
|
assert.Nil(t, bm.Put("astaxie", 1, timeoutDuration))
|
||||||
t.Error("Incr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := bm.Get("astaxie"); v.(int) != 2 {
|
assert.True(t, bm.IsExist("astaxie"))
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Decr("astaxie"); err != nil {
|
assert.Equal(t, 1, bm.Get("astaxie"))
|
||||||
t.Error("Decr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
assert.Nil(t, bm.Incr("astaxie"))
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
bm.Delete("astaxie")
|
|
||||||
if bm.IsExist("astaxie") {
|
|
||||||
t.Error("delete err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test string
|
assert.Equal(t, 2, bm.Get("astaxie"))
|
||||||
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
if v := bm.Get("astaxie"); v.(string) != "author" {
|
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test GetMulti
|
assert.Nil(t, bm.Decr("astaxie"))
|
||||||
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
assert.Equal(t, 1, bm.Get("astaxie"))
|
||||||
}
|
assert.Nil(t, bm.Delete("astaxie"))
|
||||||
if !bm.IsExist("astaxie1") {
|
|
||||||
t.Error("check err")
|
assert.False(t, bm.IsExist("astaxie"))
|
||||||
}
|
|
||||||
|
assert.Nil(t, bm.Put("astaxie", "author", timeoutDuration))
|
||||||
|
|
||||||
|
assert.True(t, bm.IsExist("astaxie"))
|
||||||
|
|
||||||
|
assert.Equal(t, "author", bm.Get("astaxie"))
|
||||||
|
|
||||||
|
assert.Nil(t, bm.Put("astaxie1", "author1", timeoutDuration))
|
||||||
|
|
||||||
|
assert.True(t, bm.IsExist("astaxie1"))
|
||||||
|
|
||||||
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
||||||
if len(vv) != 2 {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if vv[0].(string) != "author" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if vv[1].(string) != "author1" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
|
|
||||||
os.RemoveAll("cache")
|
assert.Equal(t, 2, len(vv))
|
||||||
|
|
||||||
|
assert.Equal(t, "author", vv[0])
|
||||||
|
assert.Equal(t, "author1", vv[1])
|
||||||
|
assert.Nil(t, os.RemoveAll("cache"))
|
||||||
}
|
}
|
||||||
|
|||||||
28
adapter/cache/conv_test.go
vendored
28
adapter/cache/conv_test.go
vendored
@ -19,15 +19,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestGetString(t *testing.T) {
|
func TestGetString(t *testing.T) {
|
||||||
var t1 = "test1"
|
t1 := "test1"
|
||||||
if "test1" != GetString(t1) {
|
if "test1" != GetString(t1) {
|
||||||
t.Error("get string from string error")
|
t.Error("get string from string error")
|
||||||
}
|
}
|
||||||
var t2 = []byte("test2")
|
t2 := []byte("test2")
|
||||||
if "test2" != GetString(t2) {
|
if "test2" != GetString(t2) {
|
||||||
t.Error("get string from byte array error")
|
t.Error("get string from byte array error")
|
||||||
}
|
}
|
||||||
var t3 = 1
|
t3 := 1
|
||||||
if "1" != GetString(t3) {
|
if "1" != GetString(t3) {
|
||||||
t.Error("get string from int error")
|
t.Error("get string from int error")
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ func TestGetString(t *testing.T) {
|
|||||||
if "1" != GetString(t4) {
|
if "1" != GetString(t4) {
|
||||||
t.Error("get string from int64 error")
|
t.Error("get string from int64 error")
|
||||||
}
|
}
|
||||||
var t5 = 1.1
|
t5 := 1.1
|
||||||
if "1.1" != GetString(t5) {
|
if "1.1" != GetString(t5) {
|
||||||
t.Error("get string from float64 error")
|
t.Error("get string from float64 error")
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ func TestGetString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetInt(t *testing.T) {
|
func TestGetInt(t *testing.T) {
|
||||||
var t1 = 1
|
t1 := 1
|
||||||
if 1 != GetInt(t1) {
|
if 1 != GetInt(t1) {
|
||||||
t.Error("get int from int error")
|
t.Error("get int from int error")
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ func TestGetInt(t *testing.T) {
|
|||||||
if 64 != GetInt(t3) {
|
if 64 != GetInt(t3) {
|
||||||
t.Error("get int from int64 error")
|
t.Error("get int from int64 error")
|
||||||
}
|
}
|
||||||
var t4 = "128"
|
t4 := "128"
|
||||||
if 128 != GetInt(t4) {
|
if 128 != GetInt(t4) {
|
||||||
t.Error("get int from num string error")
|
t.Error("get int from num string error")
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ func TestGetInt(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetInt64(t *testing.T) {
|
func TestGetInt64(t *testing.T) {
|
||||||
var i int64 = 1
|
var i int64 = 1
|
||||||
var t1 = 1
|
t1 := 1
|
||||||
if i != GetInt64(t1) {
|
if i != GetInt64(t1) {
|
||||||
t.Error("get int64 from int error")
|
t.Error("get int64 from int error")
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ func TestGetInt64(t *testing.T) {
|
|||||||
if i != GetInt64(t3) {
|
if i != GetInt64(t3) {
|
||||||
t.Error("get int64 from int64 error")
|
t.Error("get int64 from int64 error")
|
||||||
}
|
}
|
||||||
var t4 = "1"
|
t4 := "1"
|
||||||
if i != GetInt64(t4) {
|
if i != GetInt64(t4) {
|
||||||
t.Error("get int64 from num string error")
|
t.Error("get int64 from num string error")
|
||||||
}
|
}
|
||||||
@ -91,22 +91,22 @@ func TestGetInt64(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetFloat64(t *testing.T) {
|
func TestGetFloat64(t *testing.T) {
|
||||||
var f = 1.11
|
f := 1.11
|
||||||
var t1 float32 = 1.11
|
var t1 float32 = 1.11
|
||||||
if f != GetFloat64(t1) {
|
if f != GetFloat64(t1) {
|
||||||
t.Error("get float64 from float32 error")
|
t.Error("get float64 from float32 error")
|
||||||
}
|
}
|
||||||
var t2 = 1.11
|
t2 := 1.11
|
||||||
if f != GetFloat64(t2) {
|
if f != GetFloat64(t2) {
|
||||||
t.Error("get float64 from float64 error")
|
t.Error("get float64 from float64 error")
|
||||||
}
|
}
|
||||||
var t3 = "1.11"
|
t3 := "1.11"
|
||||||
if f != GetFloat64(t3) {
|
if f != GetFloat64(t3) {
|
||||||
t.Error("get float64 from string error")
|
t.Error("get float64 from string error")
|
||||||
}
|
}
|
||||||
|
|
||||||
var f2 float64 = 1
|
var f2 float64 = 1
|
||||||
var t4 = 1
|
t4 := 1
|
||||||
if f2 != GetFloat64(t4) {
|
if f2 != GetFloat64(t4) {
|
||||||
t.Error("get float64 from int error")
|
t.Error("get float64 from int error")
|
||||||
}
|
}
|
||||||
@ -117,11 +117,11 @@ func TestGetFloat64(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetBool(t *testing.T) {
|
func TestGetBool(t *testing.T) {
|
||||||
var t1 = true
|
t1 := true
|
||||||
if !GetBool(t1) {
|
if !GetBool(t1) {
|
||||||
t.Error("get bool from bool error")
|
t.Error("get bool from bool error")
|
||||||
}
|
}
|
||||||
var t2 = "true"
|
t2 := "true"
|
||||||
if !GetBool(t2) {
|
if !GetBool(t2) {
|
||||||
t.Error("get bool from string error")
|
t.Error("get bool from string error")
|
||||||
}
|
}
|
||||||
|
|||||||
4
adapter/cache/memcache/memcache.go
vendored
4
adapter/cache/memcache/memcache.go
vendored
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/cache/memcache"
|
// _ "github.com/beego/beego/v2/client/cache/memcache"
|
||||||
// "github.com/beego/beego/v2/cache"
|
// "github.com/beego/beego/v2/client/cache"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`)
|
// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`)
|
||||||
|
|||||||
102
adapter/cache/memcache/memcache_test.go
vendored
102
adapter/cache/memcache/memcache_test.go
vendored
@ -21,94 +21,64 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/cache"
|
"github.com/beego/beego/v2/adapter/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMemcacheCache(t *testing.T) {
|
func TestMemcacheCache(t *testing.T) {
|
||||||
|
|
||||||
addr := os.Getenv("MEMCACHE_ADDR")
|
addr := os.Getenv("MEMCACHE_ADDR")
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
addr = "127.0.0.1:11211"
|
addr = "127.0.0.1:11211"
|
||||||
}
|
}
|
||||||
|
|
||||||
bm, err := cache.NewCache("memcache", fmt.Sprintf(`{"conn": "%s"}`, addr))
|
bm, err := cache.NewCache("memcache", fmt.Sprintf(`{"conn": "%s"}`, addr))
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Error("init err")
|
timeoutDuration := 5 * time.Second
|
||||||
}
|
|
||||||
timeoutDuration := 10 * time.Second
|
assert.Nil(t, bm.Put("astaxie", "1", timeoutDuration))
|
||||||
if err = bm.Put("astaxie", "1", timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
assert.True(t, bm.IsExist("astaxie"))
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(11 * time.Second)
|
time.Sleep(11 * time.Second)
|
||||||
|
|
||||||
if bm.IsExist("astaxie") {
|
assert.False(t, bm.IsExist("astaxie"))
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
if err = bm.Put("astaxie", "1", timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 1 {
|
assert.Nil(t, bm.Put("astaxie", "1", timeoutDuration))
|
||||||
t.Error("get err")
|
v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte)))
|
||||||
}
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 1, v)
|
||||||
|
|
||||||
if err = bm.Incr("astaxie"); err != nil {
|
assert.Nil(t, bm.Incr("astaxie"))
|
||||||
t.Error("Incr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 2 {
|
v, err = strconv.Atoi(string(bm.Get("astaxie").([]byte)))
|
||||||
t.Error("get err")
|
assert.Nil(t, err)
|
||||||
}
|
assert.Equal(t, 2, v)
|
||||||
|
|
||||||
if err = bm.Decr("astaxie"); err != nil {
|
assert.Nil(t, bm.Decr("astaxie"))
|
||||||
t.Error("Decr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 1 {
|
v, err = strconv.Atoi(string(bm.Get("astaxie").([]byte)))
|
||||||
t.Error("get err")
|
assert.Nil(t, err)
|
||||||
}
|
assert.Equal(t, 1, v)
|
||||||
bm.Delete("astaxie")
|
|
||||||
if bm.IsExist("astaxie") {
|
|
||||||
t.Error("delete err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test string
|
assert.Nil(t, bm.Delete("astaxie"))
|
||||||
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := bm.Get("astaxie").([]byte); string(v) != "author" {
|
assert.False(t, bm.IsExist("astaxie"))
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test GetMulti
|
assert.Nil(t, bm.Put("astaxie", "author", timeoutDuration))
|
||||||
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
assert.True(t, bm.IsExist("astaxie"))
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie1") {
|
assert.Equal(t, []byte("author"), bm.Get("astaxie"))
|
||||||
t.Error("check err")
|
|
||||||
}
|
assert.Nil(t, bm.Put("astaxie1", "author1", timeoutDuration))
|
||||||
|
|
||||||
|
assert.True(t, bm.IsExist("astaxie1"))
|
||||||
|
|
||||||
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
||||||
if len(vv) != 2 {
|
assert.Equal(t, 2, len(vv))
|
||||||
t.Error("GetMulti ERROR")
|
assert.Equal(t, []byte("author"), vv[0])
|
||||||
}
|
assert.Equal(t, []byte("author1"), vv[1])
|
||||||
if string(vv[0].([]byte)) != "author" && string(vv[0].([]byte)) != "author1" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if string(vv[1].([]byte)) != "author1" && string(vv[1].([]byte)) != "author" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test clear all
|
assert.Nil(t, bm.ClearAll())
|
||||||
if err = bm.ClearAll(); err != nil {
|
|
||||||
t.Error("clear all err")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
10
adapter/cache/redis/redis.go
vendored
10
adapter/cache/redis/redis.go
vendored
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/cache/redis"
|
// _ "github.com/beego/beego/v2/client/cache/redis"
|
||||||
// "github.com/beego/beego/v2/cache"
|
// "github.com/beego/beego/v2/client/cache"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`)
|
// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`)
|
||||||
@ -34,10 +34,8 @@ import (
|
|||||||
redis2 "github.com/beego/beego/v2/client/cache/redis"
|
redis2 "github.com/beego/beego/v2/client/cache/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// DefaultKey the collection name of redis for cache adapter.
|
||||||
// DefaultKey the collection name of redis for cache adapter.
|
var DefaultKey = "beecacheRedis"
|
||||||
DefaultKey = "beecacheRedis"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewRedisCache create new redis cache with default collection name.
|
// NewRedisCache create new redis cache with default collection name.
|
||||||
func NewRedisCache() cache.Cache {
|
func NewRedisCache() cache.Cache {
|
||||||
|
|||||||
124
adapter/cache/redis/redis_test.go
vendored
124
adapter/cache/redis/redis_test.go
vendored
@ -21,10 +21,16 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gomodule/redigo/redis"
|
"github.com/gomodule/redigo/redis"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/cache"
|
"github.com/beego/beego/v2/adapter/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
initError = "init err"
|
||||||
|
setError = "set Error"
|
||||||
|
)
|
||||||
|
|
||||||
func TestRedisCache(t *testing.T) {
|
func TestRedisCache(t *testing.T) {
|
||||||
redisAddr := os.Getenv("REDIS_ADDR")
|
redisAddr := os.Getenv("REDIS_ADDR")
|
||||||
if redisAddr == "" {
|
if redisAddr == "" {
|
||||||
@ -32,98 +38,79 @@ func TestRedisCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bm, err := cache.NewCache("redis", fmt.Sprintf(`{"conn": "%s"}`, redisAddr))
|
bm, err := cache.NewCache("redis", fmt.Sprintf(`{"conn": "%s"}`, redisAddr))
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Error("init err")
|
timeoutDuration := 5 * time.Second
|
||||||
}
|
|
||||||
timeoutDuration := 10 * time.Second
|
|
||||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(11 * time.Second)
|
assert.Nil(t, bm.Put("astaxie", 1, timeoutDuration))
|
||||||
|
|
||||||
if bm.IsExist("astaxie") {
|
assert.True(t, bm.IsExist("astaxie"))
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 {
|
time.Sleep(7 * time.Second)
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Incr("astaxie"); err != nil {
|
assert.False(t, bm.IsExist("astaxie"))
|
||||||
t.Error("Incr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := redis.Int(bm.Get("astaxie"), err); v != 2 {
|
assert.Nil(t, bm.Put("astaxie", 1, timeoutDuration))
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Decr("astaxie"); err != nil {
|
v, err := redis.Int(bm.Get("astaxie"), err)
|
||||||
t.Error("Decr Error", err)
|
assert.Nil(t, err)
|
||||||
}
|
assert.Equal(t, 1, v)
|
||||||
|
|
||||||
if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 {
|
assert.Nil(t, bm.Incr("astaxie"))
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
bm.Delete("astaxie")
|
|
||||||
if bm.IsExist("astaxie") {
|
|
||||||
t.Error("delete err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test string
|
v, err = redis.Int(bm.Get("astaxie"), err)
|
||||||
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
|
assert.Nil(t, err)
|
||||||
t.Error("set Error", err)
|
assert.Equal(t, 2, v)
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := redis.String(bm.Get("astaxie"), err); v != "author" {
|
assert.Nil(t, bm.Decr("astaxie"))
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test GetMulti
|
v, err = redis.Int(bm.Get("astaxie"), err)
|
||||||
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
|
assert.Nil(t, err)
|
||||||
t.Error("set Error", err)
|
assert.Equal(t, 1, v)
|
||||||
}
|
|
||||||
if !bm.IsExist("astaxie1") {
|
assert.Nil(t, bm.Delete("astaxie"))
|
||||||
t.Error("check err")
|
|
||||||
}
|
assert.False(t, bm.IsExist("astaxie"))
|
||||||
|
|
||||||
|
assert.Nil(t, bm.Put("astaxie", "author", timeoutDuration))
|
||||||
|
assert.True(t, bm.IsExist("astaxie"))
|
||||||
|
|
||||||
|
vs, err := redis.String(bm.Get("astaxie"), err)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "author", vs)
|
||||||
|
|
||||||
|
assert.Nil(t, bm.Put("astaxie1", "author1", timeoutDuration))
|
||||||
|
|
||||||
|
assert.True(t, bm.IsExist("astaxie1"))
|
||||||
|
|
||||||
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
||||||
if len(vv) != 2 {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if v, _ := redis.String(vv[0], nil); v != "author" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if v, _ := redis.String(vv[1], nil); v != "author1" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Equal(t, 2, len(vv))
|
||||||
|
|
||||||
|
vs, err = redis.String(vv[0], nil)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "author", vs)
|
||||||
|
|
||||||
|
vs, err = redis.String(vv[1], nil)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "author1", vs)
|
||||||
|
|
||||||
|
assert.Nil(t, bm.ClearAll())
|
||||||
// test clear all
|
// test clear all
|
||||||
if err = bm.ClearAll(); err != nil {
|
|
||||||
t.Error("clear all err")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCache_Scan(t *testing.T) {
|
func TestCacheScan(t *testing.T) {
|
||||||
timeoutDuration := 10 * time.Second
|
timeoutDuration := 10 * time.Second
|
||||||
// init
|
// init
|
||||||
bm, err := cache.NewCache("redis", `{"conn": "127.0.0.1:6379"}`)
|
bm, err := cache.NewCache("redis", `{"conn": "127.0.0.1:6379"}`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("init err")
|
t.Error(initError)
|
||||||
}
|
}
|
||||||
// insert all
|
// insert all
|
||||||
for i := 0; i < 10000; i++ {
|
for i := 0; i < 10000; i++ {
|
||||||
if err = bm.Put(fmt.Sprintf("astaxie%d", i), fmt.Sprintf("author%d", i), timeoutDuration); err != nil {
|
if err = bm.Put(fmt.Sprintf("astaxie%d", i), fmt.Sprintf("author%d", i), timeoutDuration); err != nil {
|
||||||
t.Error("set Error", err)
|
t.Error(setError, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,5 +118,4 @@ func TestCache_Scan(t *testing.T) {
|
|||||||
if err = bm.ClearAll(); err != nil {
|
if err = bm.ClearAll(); err != nil {
|
||||||
t.Error("clear all err")
|
t.Error("clear all err")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
114
adapter/cache/ssdb/ssdb_test.go
vendored
114
adapter/cache/ssdb/ssdb_test.go
vendored
@ -7,6 +7,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/cache"
|
"github.com/beego/beego/v2/adapter/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,95 +19,59 @@ func TestSsdbcacheCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssdb, err := cache.NewCache("ssdb", fmt.Sprintf(`{"conn": "%s"}`, ssdbAddr))
|
ssdb, err := cache.NewCache("ssdb", fmt.Sprintf(`{"conn": "%s"}`, ssdbAddr))
|
||||||
if err != nil {
|
|
||||||
t.Error("init err")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.False(t, ssdb.IsExist("ssdb"))
|
||||||
// test put and exist
|
// test put and exist
|
||||||
if ssdb.IsExist("ssdb") {
|
timeoutDuration := 3 * time.Second
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
timeoutDuration := 10 * time.Second
|
|
||||||
// timeoutDuration := -10*time.Second if timeoutDuration is negtive,it means permanent
|
// timeoutDuration := -10*time.Second if timeoutDuration is negtive,it means permanent
|
||||||
if err = ssdb.Put("ssdb", "ssdb", timeoutDuration); err != nil {
|
assert.Nil(t, ssdb.Put("ssdb", "ssdb", timeoutDuration))
|
||||||
t.Error("set Error", err)
|
assert.True(t, ssdb.IsExist("ssdb"))
|
||||||
}
|
|
||||||
if !ssdb.IsExist("ssdb") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get test done
|
assert.Nil(t, ssdb.Put("ssdb", "ssdb", timeoutDuration))
|
||||||
if err = ssdb.Put("ssdb", "ssdb", timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := ssdb.Get("ssdb"); v != "ssdb" {
|
assert.Equal(t, "ssdb", ssdb.Get("ssdb"))
|
||||||
t.Error("get Error")
|
|
||||||
}
|
|
||||||
|
|
||||||
// inc/dec test done
|
// inc/dec test done
|
||||||
if err = ssdb.Put("ssdb", "2", timeoutDuration); err != nil {
|
assert.Nil(t, ssdb.Put("ssdb", "2", timeoutDuration))
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
if err = ssdb.Incr("ssdb"); err != nil {
|
|
||||||
t.Error("incr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 {
|
assert.Nil(t, ssdb.Incr("ssdb"))
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = ssdb.Decr("ssdb"); err != nil {
|
v, err := strconv.Atoi(ssdb.Get("ssdb").(string))
|
||||||
t.Error("decr error")
|
assert.Nil(t, err)
|
||||||
}
|
assert.Equal(t, 3, v)
|
||||||
|
|
||||||
|
assert.Nil(t, ssdb.Decr("ssdb"))
|
||||||
|
|
||||||
|
assert.Nil(t, ssdb.Put("ssdb", "3", timeoutDuration))
|
||||||
|
|
||||||
// test del
|
// test del
|
||||||
if err = ssdb.Put("ssdb", "3", timeoutDuration); err != nil {
|
v, err = strconv.Atoi(ssdb.Get("ssdb").(string))
|
||||||
t.Error("set Error", err)
|
assert.Nil(t, err)
|
||||||
}
|
assert.Equal(t, 3, v)
|
||||||
if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 {
|
|
||||||
t.Error("get err")
|
assert.Nil(t, ssdb.Delete("ssdb"))
|
||||||
}
|
assert.False(t, ssdb.IsExist("ssdb"))
|
||||||
if err := ssdb.Delete("ssdb"); err == nil {
|
|
||||||
if ssdb.IsExist("ssdb") {
|
|
||||||
t.Error("delete err")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// test string
|
// test string
|
||||||
if err = ssdb.Put("ssdb", "ssdb", -10*time.Second); err != nil {
|
assert.Nil(t, ssdb.Put("ssdb", "ssdb", -10*time.Second))
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
assert.True(t, ssdb.IsExist("ssdb"))
|
||||||
if !ssdb.IsExist("ssdb") {
|
assert.Equal(t, "ssdb", ssdb.Get("ssdb"))
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
if v := ssdb.Get("ssdb").(string); v != "ssdb" {
|
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test GetMulti done
|
// test GetMulti done
|
||||||
if err = ssdb.Put("ssdb1", "ssdb1", -10*time.Second); err != nil {
|
assert.Nil(t, ssdb.Put("ssdb1", "ssdb1", -10*time.Second))
|
||||||
t.Error("set Error", err)
|
assert.True(t, ssdb.IsExist("ssdb1"))
|
||||||
}
|
|
||||||
if !ssdb.IsExist("ssdb1") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
vv := ssdb.GetMulti([]string{"ssdb", "ssdb1"})
|
|
||||||
if len(vv) != 2 {
|
|
||||||
t.Error("getmulti error")
|
|
||||||
}
|
|
||||||
if vv[0].(string) != "ssdb" {
|
|
||||||
t.Error("getmulti error")
|
|
||||||
}
|
|
||||||
if vv[1].(string) != "ssdb1" {
|
|
||||||
t.Error("getmulti error")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
vv := ssdb.GetMulti([]string{"ssdb", "ssdb1"})
|
||||||
|
assert.Equal(t, 2, len(vv))
|
||||||
|
|
||||||
|
assert.Equal(t, "ssdb", vv[0])
|
||||||
|
assert.Equal(t, "ssdb1", vv[1])
|
||||||
|
|
||||||
|
assert.Nil(t, ssdb.ClearAll())
|
||||||
|
assert.False(t, ssdb.IsExist("ssdb"))
|
||||||
|
assert.False(t, ssdb.IsExist("ssdb1"))
|
||||||
// test clear all done
|
// test clear all done
|
||||||
if err = ssdb.ClearAll(); err != nil {
|
|
||||||
t.Error("clear all err")
|
|
||||||
}
|
|
||||||
if ssdb.IsExist("ssdb") || ssdb.IsExist("ssdb1") {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
// Package config is used to parse config.
|
// Package config is used to parse config.
|
||||||
// Usage:
|
// Usage:
|
||||||
// import "github.com/beego/beego/v2/config"
|
// import "github.com/beego/beego/v2/core/config"
|
||||||
// Examples.
|
// Examples.
|
||||||
//
|
//
|
||||||
// cnf, err := config.NewConfig("ini", "config.conf")
|
// cnf, err := config.NewConfig("ini", "config.conf")
|
||||||
|
|||||||
@ -20,7 +20,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestExpandValueEnv(t *testing.T) {
|
func TestExpandValueEnv(t *testing.T) {
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
item string
|
item string
|
||||||
want string
|
want string
|
||||||
@ -51,5 +50,4 @@ func TestExpandValueEnv(t *testing.T) {
|
|||||||
t.Errorf("expand value error, item %q want %q, got %q", c.item, c.want, got)
|
t.Errorf("expand value error, item %q want %q, got %q", c.item, c.want, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,6 @@ import (
|
|||||||
|
|
||||||
// NewFakeConfig return a fake Configer
|
// NewFakeConfig return a fake Configer
|
||||||
func NewFakeConfig() Configer {
|
func NewFakeConfig() Configer {
|
||||||
new := config.NewFakeConfig()
|
config := config.NewFakeConfig()
|
||||||
return &newToOldConfigerAdapter{delegate: new}
|
return &newToOldConfigerAdapter{delegate: config}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestIni(t *testing.T) {
|
func TestIni(t *testing.T) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
inicontext = `
|
inicontext = `
|
||||||
;comment one
|
;comment one
|
||||||
@ -81,7 +80,8 @@ password = ${GOPATH}
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
f, err := os.Create("testini.conf")
|
cfgFile := "testini.conf"
|
||||||
|
f, err := os.Create(cfgFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -91,8 +91,8 @@ password = ${GOPATH}
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
defer os.Remove("testini.conf")
|
defer os.Remove(cfgFile)
|
||||||
iniconf, err := NewConfig("ini", "testini.conf")
|
iniconf, err := NewConfig("ini", cfgFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -128,11 +128,9 @@ password = ${GOPATH}
|
|||||||
if iniconf.String("name") != "astaxie" {
|
if iniconf.String("name") != "astaxie" {
|
||||||
t.Fatal("get name error")
|
t.Fatal("get name error")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIniSave(t *testing.T) {
|
func TestIniSave(t *testing.T) {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
inicontext = `
|
inicontext = `
|
||||||
app = app
|
app = app
|
||||||
|
|||||||
@ -18,10 +18,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestJsonStartsWithArray(t *testing.T) {
|
func TestJsonStartsWithArray(t *testing.T) {
|
||||||
|
|
||||||
const jsoncontextwitharray = `[
|
const jsoncontextwitharray = `[
|
||||||
{
|
{
|
||||||
"url": "user",
|
"url": "user",
|
||||||
@ -32,7 +33,8 @@ func TestJsonStartsWithArray(t *testing.T) {
|
|||||||
"serviceAPI": "http://www.test.com/employee"
|
"serviceAPI": "http://www.test.com/employee"
|
||||||
}
|
}
|
||||||
]`
|
]`
|
||||||
f, err := os.Create("testjsonWithArray.conf")
|
cfgFileName := "testjsonWithArray.conf"
|
||||||
|
f, err := os.Create(cfgFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -42,8 +44,8 @@ func TestJsonStartsWithArray(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
defer os.Remove("testjsonWithArray.conf")
|
defer os.Remove(cfgFileName)
|
||||||
jsonconf, err := NewConfig("json", "testjsonWithArray.conf")
|
jsonconf, err := NewConfig("json", cfgFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -68,7 +70,6 @@ func TestJsonStartsWithArray(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestJson(t *testing.T) {
|
func TestJson(t *testing.T) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
jsoncontext = `{
|
jsoncontext = `{
|
||||||
"appname": "beeapi",
|
"appname": "beeapi",
|
||||||
@ -132,7 +133,8 @@ func TestJson(t *testing.T) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
f, err := os.Create("testjson.conf")
|
cfgFileName := "testjson.conf"
|
||||||
|
f, err := os.Create(cfgFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -142,8 +144,8 @@ func TestJson(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
defer os.Remove("testjson.conf")
|
defer os.Remove(cfgFileName)
|
||||||
jsonconf, err := NewConfig("json", "testjson.conf")
|
jsonconf, err := NewConfig("json", cfgFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -167,56 +169,39 @@ func TestJson(t *testing.T) {
|
|||||||
default:
|
default:
|
||||||
value, err = jsonconf.DIY(k)
|
value, err = jsonconf.DIY(k)
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("get key %q value fatal,%v err %s", k, v, err)
|
assert.Nil(t, err)
|
||||||
} else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) {
|
assert.Equal(t, fmt.Sprintf("%v", v), fmt.Sprintf("%v", value))
|
||||||
t.Fatalf("get key %q value, want %v got %v .", k, v, value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
assert.Nil(t, jsonconf.Set("name", "astaxie"))
|
||||||
if err = jsonconf.Set("name", "astaxie"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if jsonconf.String("name") != "astaxie" {
|
|
||||||
t.Fatal("get name error")
|
|
||||||
}
|
|
||||||
|
|
||||||
if db, err := jsonconf.DIY("database"); err != nil {
|
assert.Equal(t, "astaxie", jsonconf.String("name"))
|
||||||
t.Fatal(err)
|
|
||||||
} else if m, ok := db.(map[string]interface{}); !ok {
|
|
||||||
t.Log(db)
|
|
||||||
t.Fatal("db not map[string]interface{}")
|
|
||||||
} else {
|
|
||||||
if m["host"].(string) != "host" {
|
|
||||||
t.Fatal("get host err")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := jsonconf.Int("unknown"); err == nil {
|
db, err := jsonconf.DIY("database")
|
||||||
t.Error("unknown keys should return an error when expecting an Int")
|
assert.Nil(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := jsonconf.Int64("unknown"); err == nil {
|
m, ok := db.(map[string]interface{})
|
||||||
t.Error("unknown keys should return an error when expecting an Int64")
|
assert.True(t, ok)
|
||||||
}
|
assert.Equal(t, "host", m["host"])
|
||||||
|
|
||||||
if _, err := jsonconf.Float("unknown"); err == nil {
|
_, err = jsonconf.Int("unknown")
|
||||||
t.Error("unknown keys should return an error when expecting a Float")
|
assert.NotNil(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := jsonconf.DIY("unknown"); err == nil {
|
_, err = jsonconf.Int64("unknown")
|
||||||
t.Error("unknown keys should return an error when expecting an interface{}")
|
assert.NotNil(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
if val := jsonconf.String("unknown"); val != "" {
|
_, err = jsonconf.Float("unknown")
|
||||||
t.Error("unknown keys should return an empty string when expecting a String")
|
assert.NotNil(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := jsonconf.Bool("unknown"); err == nil {
|
_, err = jsonconf.DIY("unknown")
|
||||||
t.Error("unknown keys should return an error when expecting a Bool")
|
assert.NotNil(t, err)
|
||||||
}
|
|
||||||
|
|
||||||
if !jsonconf.DefaultBool("unknown", true) {
|
val := jsonconf.String("unknown")
|
||||||
t.Error("unknown keys with default value wrong")
|
assert.Equal(t, "", val)
|
||||||
}
|
|
||||||
|
_, err = jsonconf.Bool("unknown")
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
assert.True(t, jsonconf.DefaultBool("unknown", true))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/config/xml"
|
// _ "github.com/beego/beego/v2/core/config/xml"
|
||||||
// "github.com/beego/beego/v2/config"
|
// "github.com/beego/beego/v2/core/config"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// cnf, err := config.NewConfig("xml", "config.xml")
|
// cnf, err := config.NewConfig("xml", "config.xml")
|
||||||
|
|||||||
@ -23,7 +23,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestXML(t *testing.T) {
|
func TestXML(t *testing.T) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// xml parse should incluce in <config></config> tags
|
// xml parse should incluce in <config></config> tags
|
||||||
xmlcontext = `<?xml version="1.0" encoding="UTF-8"?>
|
xmlcontext = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
@ -58,7 +57,8 @@ func TestXML(t *testing.T) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
f, err := os.Create("testxml.conf")
|
cfgFileName := "testxml.conf"
|
||||||
|
f, err := os.Create(cfgFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -68,9 +68,9 @@ func TestXML(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
defer os.Remove("testxml.conf")
|
defer os.Remove(cfgFileName)
|
||||||
|
|
||||||
xmlconf, err := config.NewConfig("xml", "testxml.conf")
|
xmlconf, err := config.NewConfig("xml", cfgFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/config/yaml"
|
// _ "github.com/beego/beego/v2/core/config/yaml"
|
||||||
// "github.com/beego/beego/v2/config"
|
// "github.com/beego/beego/v2/core/config"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// cnf, err := config.NewConfig("yaml", "config.yaml")
|
// cnf, err := config.NewConfig("yaml", "config.yaml")
|
||||||
|
|||||||
@ -23,7 +23,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestYaml(t *testing.T) {
|
func TestYaml(t *testing.T) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
yamlcontext = `
|
yamlcontext = `
|
||||||
"appname": beeapi
|
"appname": beeapi
|
||||||
@ -54,7 +53,8 @@ func TestYaml(t *testing.T) {
|
|||||||
"emptystrings": []string{},
|
"emptystrings": []string{},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
f, err := os.Create("testyaml.conf")
|
cfgFileName := "testyaml.conf"
|
||||||
|
f, err := os.Create(cfgFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -64,8 +64,8 @@ func TestYaml(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
defer os.Remove("testyaml.conf")
|
defer os.Remove(cfgFileName)
|
||||||
yamlconf, err := config.NewConfig("yaml", "testyaml.conf")
|
yamlconf, err := config.NewConfig("yaml", cfgFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -111,5 +111,4 @@ func TestYaml(t *testing.T) {
|
|||||||
if yamlconf.String("name") != "astaxie" {
|
if yamlconf.String("name") != "astaxie" {
|
||||||
t.Fatal("get name error")
|
t.Fatal("get name error")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
// Package context provide the context utils
|
// Package context provide the context utils
|
||||||
// Usage:
|
// Usage:
|
||||||
//
|
//
|
||||||
// import "github.com/beego/beego/v2/context"
|
// import "github.com/beego/beego/v2/server/web/context"
|
||||||
//
|
//
|
||||||
// ctx := context.Context{Request:req,ResponseWriter:rw}
|
// ctx := context.Context{Request:req,ResponseWriter:rw}
|
||||||
//
|
//
|
||||||
|
|||||||
18
adapter/context/param/conv.go
Normal file
18
adapter/context/param/conv.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package param
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
beecontext "github.com/beego/beego/v2/adapter/context"
|
||||||
|
"github.com/beego/beego/v2/server/web/context"
|
||||||
|
"github.com/beego/beego/v2/server/web/context/param"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConvertParams converts http method params to values that will be passed to the method controller as arguments
|
||||||
|
func ConvertParams(methodParams []*MethodParam, methodType reflect.Type, ctx *beecontext.Context) (result []reflect.Value) {
|
||||||
|
nps := make([]*param.MethodParam, 0, len(methodParams))
|
||||||
|
for _, mp := range methodParams {
|
||||||
|
nps = append(nps, (*param.MethodParam)(mp))
|
||||||
|
}
|
||||||
|
return param.ConvertParams(nps, methodType, (*context.Context)(ctx))
|
||||||
|
}
|
||||||
39
adapter/context/param/conv_test.go
Normal file
39
adapter/context/param/conv_test.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2020 beego
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package param
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/adapter/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Demo is used to test, it's empty
|
||||||
|
func Demo(i int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertParams(t *testing.T) {
|
||||||
|
res := ConvertParams(nil, reflect.TypeOf(Demo), context.NewContext())
|
||||||
|
assert.Equal(t, 0, len(res))
|
||||||
|
ctx := context.NewContext()
|
||||||
|
ctx.Input.RequestBody = []byte("11")
|
||||||
|
res = ConvertParams([]*MethodParam{
|
||||||
|
New("A", InBody),
|
||||||
|
}, reflect.TypeOf(Demo), ctx)
|
||||||
|
assert.Equal(t, int64(11), res[0].Int())
|
||||||
|
}
|
||||||
29
adapter/context/param/methodparams.go
Normal file
29
adapter/context/param/methodparams.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package param
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/beego/beego/v2/server/web/context/param"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MethodParam keeps param information to be auto passed to controller methods
|
||||||
|
type MethodParam param.MethodParam
|
||||||
|
|
||||||
|
// New creates a new MethodParam with name and specific options
|
||||||
|
func New(name string, opts ...MethodParamOption) *MethodParam {
|
||||||
|
newOps := make([]param.MethodParamOption, 0, len(opts))
|
||||||
|
for _, o := range opts {
|
||||||
|
newOps = append(newOps, oldMpoToNew(o))
|
||||||
|
}
|
||||||
|
return (*MethodParam)(param.New(name, newOps...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make creates an array of MethodParmas or an empty array
|
||||||
|
func Make(list ...*MethodParam) []*MethodParam {
|
||||||
|
if len(list) > 0 {
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mp *MethodParam) String() string {
|
||||||
|
return (*param.MethodParam)(mp).String()
|
||||||
|
}
|
||||||
34
adapter/context/param/methodparams_test.go
Normal file
34
adapter/context/param/methodparams_test.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2020 beego
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package param
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMethodParamString(t *testing.T) {
|
||||||
|
method := New("myName", IsRequired, InHeader, Default("abc"))
|
||||||
|
s := method.String()
|
||||||
|
assert.Equal(t, `param.New("myName", param.IsRequired, param.InHeader, param.Default("abc"))`, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMake(t *testing.T) {
|
||||||
|
res := Make()
|
||||||
|
assert.Equal(t, 0, len(res))
|
||||||
|
res = Make(New("myName", InBody))
|
||||||
|
assert.Equal(t, 1, len(res))
|
||||||
|
}
|
||||||
45
adapter/context/param/options.go
Normal file
45
adapter/context/param/options.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package param
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/beego/beego/v2/server/web/context/param"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MethodParamOption defines a func which apply options on a MethodParam
|
||||||
|
type MethodParamOption func(*MethodParam)
|
||||||
|
|
||||||
|
// IsRequired indicates that this param is required and can not be omitted from the http request
|
||||||
|
var IsRequired MethodParamOption = func(p *MethodParam) {
|
||||||
|
param.IsRequired((*param.MethodParam)(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
// InHeader indicates that this param is passed via an http header
|
||||||
|
var InHeader MethodParamOption = func(p *MethodParam) {
|
||||||
|
param.InHeader((*param.MethodParam)(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
// InPath indicates that this param is part of the URL path
|
||||||
|
var InPath MethodParamOption = func(p *MethodParam) {
|
||||||
|
param.InPath((*param.MethodParam)(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
// InBody indicates that this param is passed as an http request body
|
||||||
|
var InBody MethodParamOption = func(p *MethodParam) {
|
||||||
|
param.InBody((*param.MethodParam)(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default provides a default value for the http param
|
||||||
|
func Default(defaultValue interface{}) MethodParamOption {
|
||||||
|
return newMpoToOld(param.Default(defaultValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMpoToOld(n param.MethodParamOption) MethodParamOption {
|
||||||
|
return func(methodParam *MethodParam) {
|
||||||
|
n((*param.MethodParam)(methodParam))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func oldMpoToNew(old MethodParamOption) param.MethodParamOption {
|
||||||
|
return func(methodParam *param.MethodParam) {
|
||||||
|
old((*MethodParam)(methodParam))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,9 +19,8 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/session"
|
"github.com/beego/beego/v2/adapter/session"
|
||||||
webContext "github.com/beego/beego/v2/server/web/context"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/server/web"
|
"github.com/beego/beego/v2/server/web"
|
||||||
|
webContext "github.com/beego/beego/v2/server/web/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -49,9 +48,11 @@ type ControllerCommentsSlice web.ControllerCommentsSlice
|
|||||||
func (p ControllerCommentsSlice) Len() int {
|
func (p ControllerCommentsSlice) Len() int {
|
||||||
return (web.ControllerCommentsSlice)(p).Len()
|
return (web.ControllerCommentsSlice)(p).Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ControllerCommentsSlice) Less(i, j int) bool {
|
func (p ControllerCommentsSlice) Less(i, j int) bool {
|
||||||
return (web.ControllerCommentsSlice)(p).Less(i, j)
|
return (web.ControllerCommentsSlice)(p).Less(i, j)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ControllerCommentsSlice) Swap(i, j int) {
|
func (p ControllerCommentsSlice) Swap(i, j int) {
|
||||||
(web.ControllerCommentsSlice)(p).Swap(i, j)
|
(web.ControllerCommentsSlice)(p).Swap(i, j)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/context"
|
"github.com/beego/beego/v2/adapter/context"
|
||||||
beecontext "github.com/beego/beego/v2/server/web/context"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/server/web"
|
"github.com/beego/beego/v2/server/web"
|
||||||
|
beecontext "github.com/beego/beego/v2/server/web/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
// "net/http"
|
// "net/http"
|
||||||
// "os"
|
// "os"
|
||||||
//
|
//
|
||||||
// "github.com/beego/beego/v2/grace"
|
// "github.com/beego/beego/v2/server/web/grace"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func handler(w http.ResponseWriter, r *http.Request) {
|
// func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
// Package httplib is used as http.Client
|
// Package httplib is used as http.Client
|
||||||
// Usage:
|
// Usage:
|
||||||
//
|
//
|
||||||
// import "github.com/beego/beego/v2/httplib"
|
// import "github.com/beego/beego/v2/client/httplib"
|
||||||
//
|
//
|
||||||
// b := httplib.Post("http://beego.me/")
|
// b := httplib.Post("http://beego.me/")
|
||||||
// b.Param("username","astaxie")
|
// b.Param("username","astaxie")
|
||||||
@ -115,12 +115,6 @@ func (b *BeegoHTTPRequest) SetUserAgent(useragent string) *BeegoHTTPRequest {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug sets show debug or not when executing request.
|
|
||||||
func (b *BeegoHTTPRequest) Debug(isdebug bool) *BeegoHTTPRequest {
|
|
||||||
b.delegate.Debug(isdebug)
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retries sets Retries times.
|
// Retries sets Retries times.
|
||||||
// default is 0 means no retried.
|
// default is 0 means no retried.
|
||||||
// -1 means retried forever.
|
// -1 means retried forever.
|
||||||
@ -135,17 +129,6 @@ func (b *BeegoHTTPRequest) RetryDelay(delay time.Duration) *BeegoHTTPRequest {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// DumpBody setting whether need to Dump the Body.
|
|
||||||
func (b *BeegoHTTPRequest) DumpBody(isdump bool) *BeegoHTTPRequest {
|
|
||||||
b.delegate.DumpBody(isdump)
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// DumpRequest return the DumpRequest
|
|
||||||
func (b *BeegoHTTPRequest) DumpRequest() []byte {
|
|
||||||
return b.delegate.DumpRequest()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTimeout sets connect time out and read-write time out for BeegoRequest.
|
// SetTimeout sets connect time out and read-write time out for BeegoRequest.
|
||||||
func (b *BeegoHTTPRequest) SetTimeout(connectTimeout, readWriteTimeout time.Duration) *BeegoHTTPRequest {
|
func (b *BeegoHTTPRequest) SetTimeout(connectTimeout, readWriteTimeout time.Duration) *BeegoHTTPRequest {
|
||||||
b.delegate.SetTimeout(connectTimeout, readWriteTimeout)
|
b.delegate.SetTimeout(connectTimeout, readWriteTimeout)
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
package httplib
|
package httplib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
@ -25,8 +26,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
getURL = "http://httpbin.org/get"
|
||||||
|
ipURL = "http://httpbin.org/ip"
|
||||||
|
)
|
||||||
|
|
||||||
func TestResponse(t *testing.T) {
|
func TestResponse(t *testing.T) {
|
||||||
req := Get("http://httpbin.org/get")
|
req := Get(getURL)
|
||||||
resp, err := req.Response()
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -59,11 +65,10 @@ func TestDoRequest(t *testing.T) {
|
|||||||
if elapsedTime < delayedTime {
|
if elapsedTime < delayedTime {
|
||||||
t.Errorf("Not enough retries. Took %dms. Delay was meant to take %dms", elapsedTime, delayedTime)
|
t.Errorf("Not enough retries. Took %dms. Delay was meant to take %dms", elapsedTime, delayedTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGet(t *testing.T) {
|
func TestGet(t *testing.T) {
|
||||||
req := Get("http://httpbin.org/get")
|
req := Get(getURL)
|
||||||
b, err := req.Bytes()
|
b, err := req.Bytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -205,7 +210,7 @@ func TestWithSetting(t *testing.T) {
|
|||||||
setting.ReadWriteTimeout = 5 * time.Second
|
setting.ReadWriteTimeout = 5 * time.Second
|
||||||
SetDefaultSetting(setting)
|
SetDefaultSetting(setting)
|
||||||
|
|
||||||
str, err := Get("http://httpbin.org/get").String()
|
str, err := Get(getURL).String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -218,7 +223,7 @@ func TestWithSetting(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToJson(t *testing.T) {
|
func TestToJson(t *testing.T) {
|
||||||
req := Get("http://httpbin.org/ip")
|
req := Get(ipURL)
|
||||||
resp, err := req.Response()
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -244,33 +249,32 @@ func TestToJson(t *testing.T) {
|
|||||||
t.Fatal("response is not valid ip")
|
t.Fatal("response is not valid ip")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToFile(t *testing.T) {
|
func TestToFile(t *testing.T) {
|
||||||
f := "beego_testfile"
|
f := "beego_testfile"
|
||||||
req := Get("http://httpbin.org/ip")
|
req := Get(ipURL)
|
||||||
err := req.ToFile(f)
|
err := req.ToFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer os.Remove(f)
|
defer os.Remove(f)
|
||||||
b, err := ioutil.ReadFile(f)
|
b, err := ioutil.ReadFile(f)
|
||||||
if n := strings.Index(string(b), "origin"); n == -1 {
|
if n := bytes.Index(b, []byte("origin")); n == -1 {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToFileDir(t *testing.T) {
|
func TestToFileDir(t *testing.T) {
|
||||||
f := "./files/beego_testfile"
|
f := "./files/beego_testfile"
|
||||||
req := Get("http://httpbin.org/ip")
|
req := Get(ipURL)
|
||||||
err := req.ToFile(f)
|
err := req.ToFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll("./files")
|
defer os.RemoveAll("./files")
|
||||||
b, err := ioutil.ReadFile(f)
|
b, err := ioutil.ReadFile(f)
|
||||||
if n := strings.Index(string(b), "origin"); n == -1 {
|
if n := bytes.Index(b, []byte("origin")); n == -1 {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,108 +18,106 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/core/logs"
|
"github.com/beego/beego/v2/core/logs"
|
||||||
|
|
||||||
webLog "github.com/beego/beego/v2/core/logs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Log levels to control the logging output.
|
// Log levels to control the logging output.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
const (
|
const (
|
||||||
LevelEmergency = webLog.LevelEmergency
|
LevelEmergency = logs.LevelEmergency
|
||||||
LevelAlert = webLog.LevelAlert
|
LevelAlert = logs.LevelAlert
|
||||||
LevelCritical = webLog.LevelCritical
|
LevelCritical = logs.LevelCritical
|
||||||
LevelError = webLog.LevelError
|
LevelError = logs.LevelError
|
||||||
LevelWarning = webLog.LevelWarning
|
LevelWarning = logs.LevelWarning
|
||||||
LevelNotice = webLog.LevelNotice
|
LevelNotice = logs.LevelNotice
|
||||||
LevelInformational = webLog.LevelInformational
|
LevelInformational = logs.LevelInformational
|
||||||
LevelDebug = webLog.LevelDebug
|
LevelDebug = logs.LevelDebug
|
||||||
)
|
)
|
||||||
|
|
||||||
// BeeLogger references the used application logger.
|
// BeeLogger references the used application logger.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
var BeeLogger = logs.GetBeeLogger()
|
var BeeLogger = logs.GetBeeLogger()
|
||||||
|
|
||||||
// SetLevel sets the global log level used by the simple logger.
|
// SetLevel sets the global log level used by the simple logger.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func SetLevel(l int) {
|
func SetLevel(l int) {
|
||||||
logs.SetLevel(l)
|
logs.SetLevel(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLogFuncCall set the CallDepth, default is 3
|
// SetLogFuncCall set the CallDepth, default is 3
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func SetLogFuncCall(b bool) {
|
func SetLogFuncCall(b bool) {
|
||||||
logs.SetLogFuncCall(b)
|
logs.SetLogFuncCall(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLogger sets a new logger.
|
// SetLogger sets a new logger.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func SetLogger(adaptername string, config string) error {
|
func SetLogger(adaptername string, config string) error {
|
||||||
return logs.SetLogger(adaptername, config)
|
return logs.SetLogger(adaptername, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emergency logs a message at emergency level.
|
// Emergency logs a message at emergency level.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Emergency(v ...interface{}) {
|
func Emergency(v ...interface{}) {
|
||||||
logs.Emergency(generateFmtStr(len(v)), v...)
|
logs.Emergency(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alert logs a message at alert level.
|
// Alert logs a message at alert level.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Alert(v ...interface{}) {
|
func Alert(v ...interface{}) {
|
||||||
logs.Alert(generateFmtStr(len(v)), v...)
|
logs.Alert(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical logs a message at critical level.
|
// Critical logs a message at critical level.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Critical(v ...interface{}) {
|
func Critical(v ...interface{}) {
|
||||||
logs.Critical(generateFmtStr(len(v)), v...)
|
logs.Critical(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error logs a message at error level.
|
// Error logs a message at error level.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Error(v ...interface{}) {
|
func Error(v ...interface{}) {
|
||||||
logs.Error(generateFmtStr(len(v)), v...)
|
logs.Error(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warning logs a message at warning level.
|
// Warning logs a message at warning level.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Warning(v ...interface{}) {
|
func Warning(v ...interface{}) {
|
||||||
logs.Warning(generateFmtStr(len(v)), v...)
|
logs.Warning(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn compatibility alias for Warning()
|
// Warn compatibility alias for Warning()
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Warn(v ...interface{}) {
|
func Warn(v ...interface{}) {
|
||||||
logs.Warn(generateFmtStr(len(v)), v...)
|
logs.Warn(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notice logs a message at notice level.
|
// Notice logs a message at notice level.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Notice(v ...interface{}) {
|
func Notice(v ...interface{}) {
|
||||||
logs.Notice(generateFmtStr(len(v)), v...)
|
logs.Notice(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Informational logs a message at info level.
|
// Informational logs a message at info level.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Informational(v ...interface{}) {
|
func Informational(v ...interface{}) {
|
||||||
logs.Informational(generateFmtStr(len(v)), v...)
|
logs.Informational(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info compatibility alias for Warning()
|
// Info compatibility alias for Warning()
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Info(v ...interface{}) {
|
func Info(v ...interface{}) {
|
||||||
logs.Info(generateFmtStr(len(v)), v...)
|
logs.Info(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug logs a message at debug level.
|
// Debug logs a message at debug level.
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Debug(v ...interface{}) {
|
func Debug(v ...interface{}) {
|
||||||
logs.Debug(generateFmtStr(len(v)), v...)
|
logs.Debug(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trace logs a message at trace level.
|
// Trace logs a message at trace level.
|
||||||
// compatibility alias for Warning()
|
// compatibility alias for Warning()
|
||||||
// Deprecated: use github.com/beego/beego/v2/logs instead.
|
// Deprecated: use github.com/beego/beego/v2/core/logs instead.
|
||||||
func Trace(v ...interface{}) {
|
func Trace(v ...interface{}) {
|
||||||
logs.Trace(generateFmtStr(len(v)), v...)
|
logs.Trace(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
// Package logs provide a general log interface
|
// Package logs provide a general log interface
|
||||||
// Usage:
|
// Usage:
|
||||||
//
|
//
|
||||||
// import "github.com/beego/beego/v2/logs"
|
// import "github.com/beego/beego/v2/core/logs"
|
||||||
//
|
//
|
||||||
// log := NewLogger(10000)
|
// log := NewLogger(10000)
|
||||||
// log.SetLogger("console", "")
|
// log.SetLogger("console", "")
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBeeLogger_Info(t *testing.T) {
|
func TestBeeLoggerInfo(t *testing.T) {
|
||||||
log := NewLogger(1000)
|
log := NewLogger(1000)
|
||||||
log.SetLogger("file", `{"net":"tcp","addr":":7020"}`)
|
log.SetLogger("file", `{"net":"tcp","addr":":7020"}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
package metric
|
package metric
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
@ -26,7 +27,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestPrometheusMiddleWare(t *testing.T) {
|
func TestPrometheusMiddleWare(t *testing.T) {
|
||||||
middleware := PrometheusMiddleWare(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}))
|
middleware := PrometheusMiddleWare(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
|
||||||
|
fmt.Print("you are coming")
|
||||||
|
}))
|
||||||
writer := &context.Response{}
|
writer := &context.Response{}
|
||||||
request := &http.Request{
|
request := &http.Request{
|
||||||
URL: &url.URL{
|
URL: &url.URL{
|
||||||
|
|||||||
@ -18,9 +18,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
adtContext "github.com/beego/beego/v2/adapter/context"
|
adtContext "github.com/beego/beego/v2/adapter/context"
|
||||||
"github.com/beego/beego/v2/server/web/context"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/server/web"
|
"github.com/beego/beego/v2/server/web"
|
||||||
|
"github.com/beego/beego/v2/server/web/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
type namespaceCond func(*adtContext.Context) bool
|
type namespaceCond func(*adtContext.Context) bool
|
||||||
@ -240,141 +239,158 @@ func AddNamespace(nl ...*Namespace) {
|
|||||||
|
|
||||||
// NSCond is Namespace Condition
|
// NSCond is Namespace Condition
|
||||||
func NSCond(cond namespaceCond) LinkNamespace {
|
func NSCond(cond namespaceCond) LinkNamespace {
|
||||||
return func(namespace *Namespace) {
|
wc := web.NSCond(func(b *context.Context) bool {
|
||||||
web.NSCond(func(b *context.Context) bool {
|
|
||||||
return cond((*adtContext.Context)(b))
|
return cond((*adtContext.Context)(b))
|
||||||
})
|
})
|
||||||
|
return func(namespace *Namespace) {
|
||||||
|
wc((*web.Namespace)(namespace))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSBefore Namespace BeforeRouter filter
|
// NSBefore Namespace BeforeRouter filter
|
||||||
func NSBefore(filterList ...FilterFunc) LinkNamespace {
|
func NSBefore(filterList ...FilterFunc) LinkNamespace {
|
||||||
return func(namespace *Namespace) {
|
|
||||||
nfs := oldToNewFilter(filterList)
|
nfs := oldToNewFilter(filterList)
|
||||||
web.NSBefore(nfs...)
|
wf := web.NSBefore(nfs...)
|
||||||
|
return func(namespace *Namespace) {
|
||||||
|
wf((*web.Namespace)(namespace))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSAfter add Namespace FinishRouter filter
|
// NSAfter add Namespace FinishRouter filter
|
||||||
func NSAfter(filterList ...FilterFunc) LinkNamespace {
|
func NSAfter(filterList ...FilterFunc) LinkNamespace {
|
||||||
return func(namespace *Namespace) {
|
|
||||||
nfs := oldToNewFilter(filterList)
|
nfs := oldToNewFilter(filterList)
|
||||||
web.NSAfter(nfs...)
|
wf := web.NSAfter(nfs...)
|
||||||
|
return func(namespace *Namespace) {
|
||||||
|
wf((*web.Namespace)(namespace))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSInclude Namespace Include ControllerInterface
|
// NSInclude Namespace Include ControllerInterface
|
||||||
func NSInclude(cList ...ControllerInterface) LinkNamespace {
|
func NSInclude(cList ...ControllerInterface) LinkNamespace {
|
||||||
return func(namespace *Namespace) {
|
|
||||||
nfs := oldToNewCtrlIntfs(cList)
|
nfs := oldToNewCtrlIntfs(cList)
|
||||||
web.NSInclude(nfs...)
|
wi := web.NSInclude(nfs...)
|
||||||
|
return func(namespace *Namespace) {
|
||||||
|
wi((*web.Namespace)(namespace))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSRouter call Namespace Router
|
// NSRouter call Namespace Router
|
||||||
func NSRouter(rootpath string, c ControllerInterface, mappingMethods ...string) LinkNamespace {
|
func NSRouter(rootpath string, c ControllerInterface, mappingMethods ...string) LinkNamespace {
|
||||||
|
wn := web.NSRouter(rootpath, c, mappingMethods...)
|
||||||
return func(namespace *Namespace) {
|
return func(namespace *Namespace) {
|
||||||
web.Router(rootpath, c, mappingMethods...)
|
wn((*web.Namespace)(namespace))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSGet call Namespace Get
|
// NSGet call Namespace Get
|
||||||
func NSGet(rootpath string, f FilterFunc) LinkNamespace {
|
func NSGet(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
ln := web.NSGet(rootpath, func(ctx *context.Context) {
|
||||||
web.NSGet(rootpath, func(ctx *context.Context) {
|
|
||||||
f((*adtContext.Context)(ctx))
|
f((*adtContext.Context)(ctx))
|
||||||
})
|
})
|
||||||
|
return func(ns *Namespace) {
|
||||||
|
ln((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSPost call Namespace Post
|
// NSPost call Namespace Post
|
||||||
func NSPost(rootpath string, f FilterFunc) LinkNamespace {
|
func NSPost(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
wp := web.NSPost(rootpath, func(ctx *context.Context) {
|
||||||
web.Post(rootpath, func(ctx *context.Context) {
|
|
||||||
f((*adtContext.Context)(ctx))
|
f((*adtContext.Context)(ctx))
|
||||||
})
|
})
|
||||||
|
return func(ns *Namespace) {
|
||||||
|
wp((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSHead call Namespace Head
|
// NSHead call Namespace Head
|
||||||
func NSHead(rootpath string, f FilterFunc) LinkNamespace {
|
func NSHead(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
wb := web.NSHead(rootpath, func(ctx *context.Context) {
|
||||||
web.NSHead(rootpath, func(ctx *context.Context) {
|
|
||||||
f((*adtContext.Context)(ctx))
|
f((*adtContext.Context)(ctx))
|
||||||
})
|
})
|
||||||
|
return func(ns *Namespace) {
|
||||||
|
wb((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSPut call Namespace Put
|
// NSPut call Namespace Put
|
||||||
func NSPut(rootpath string, f FilterFunc) LinkNamespace {
|
func NSPut(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
wn := web.NSPut(rootpath, func(ctx *context.Context) {
|
||||||
web.NSPut(rootpath, func(ctx *context.Context) {
|
|
||||||
f((*adtContext.Context)(ctx))
|
f((*adtContext.Context)(ctx))
|
||||||
})
|
})
|
||||||
|
return func(ns *Namespace) {
|
||||||
|
wn((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSDelete call Namespace Delete
|
// NSDelete call Namespace Delete
|
||||||
func NSDelete(rootpath string, f FilterFunc) LinkNamespace {
|
func NSDelete(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
wn := web.NSDelete(rootpath, func(ctx *context.Context) {
|
||||||
web.NSDelete(rootpath, func(ctx *context.Context) {
|
|
||||||
f((*adtContext.Context)(ctx))
|
f((*adtContext.Context)(ctx))
|
||||||
})
|
})
|
||||||
|
return func(ns *Namespace) {
|
||||||
|
wn((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSAny call Namespace Any
|
// NSAny call Namespace Any
|
||||||
func NSAny(rootpath string, f FilterFunc) LinkNamespace {
|
func NSAny(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
wn := web.NSAny(rootpath, func(ctx *context.Context) {
|
||||||
web.NSAny(rootpath, func(ctx *context.Context) {
|
|
||||||
f((*adtContext.Context)(ctx))
|
f((*adtContext.Context)(ctx))
|
||||||
})
|
})
|
||||||
|
return func(ns *Namespace) {
|
||||||
|
wn((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSOptions call Namespace Options
|
// NSOptions call Namespace Options
|
||||||
func NSOptions(rootpath string, f FilterFunc) LinkNamespace {
|
func NSOptions(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
wo := web.NSOptions(rootpath, func(ctx *context.Context) {
|
||||||
web.NSOptions(rootpath, func(ctx *context.Context) {
|
|
||||||
f((*adtContext.Context)(ctx))
|
f((*adtContext.Context)(ctx))
|
||||||
})
|
})
|
||||||
|
return func(ns *Namespace) {
|
||||||
|
wo((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSPatch call Namespace Patch
|
// NSPatch call Namespace Patch
|
||||||
func NSPatch(rootpath string, f FilterFunc) LinkNamespace {
|
func NSPatch(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
wn := web.NSPatch(rootpath, func(ctx *context.Context) {
|
||||||
web.NSPatch(rootpath, func(ctx *context.Context) {
|
|
||||||
f((*adtContext.Context)(ctx))
|
f((*adtContext.Context)(ctx))
|
||||||
})
|
})
|
||||||
|
return func(ns *Namespace) {
|
||||||
|
wn((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSAutoRouter call Namespace AutoRouter
|
// NSAutoRouter call Namespace AutoRouter
|
||||||
func NSAutoRouter(c ControllerInterface) LinkNamespace {
|
func NSAutoRouter(c ControllerInterface) LinkNamespace {
|
||||||
|
wn := web.NSAutoRouter(c)
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
web.NSAutoRouter(c)
|
wn((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSAutoPrefix call Namespace AutoPrefix
|
// NSAutoPrefix call Namespace AutoPrefix
|
||||||
func NSAutoPrefix(prefix string, c ControllerInterface) LinkNamespace {
|
func NSAutoPrefix(prefix string, c ControllerInterface) LinkNamespace {
|
||||||
|
wn := web.NSAutoPrefix(prefix, c)
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
web.NSAutoPrefix(prefix, c)
|
wn((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSNamespace add sub Namespace
|
// NSNamespace add sub Namespace
|
||||||
func NSNamespace(prefix string, params ...LinkNamespace) LinkNamespace {
|
func NSNamespace(prefix string, params ...LinkNamespace) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
|
||||||
nps := oldToNewLinkNs(params)
|
nps := oldToNewLinkNs(params)
|
||||||
web.NSNamespace(prefix, nps...)
|
wn := web.NSNamespace(prefix, nps...)
|
||||||
|
return func(ns *Namespace) {
|
||||||
|
wn((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSHandler add handler
|
// NSHandler add handler
|
||||||
func NSHandler(rootpath string, h http.Handler) LinkNamespace {
|
func NSHandler(rootpath string, h http.Handler) LinkNamespace {
|
||||||
|
wn := web.NSHandler(rootpath, h)
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
web.NSHandler(rootpath, h)
|
wn((*web.Namespace)(ns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,5 @@ import (
|
|||||||
"github.com/beego/beego/v2/client/orm"
|
"github.com/beego/beego/v2/client/orm"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// ErrMissPK missing pk error
|
||||||
// ErrMissPK missing pk error
|
var ErrMissPK = orm.ErrMissPK
|
||||||
ErrMissPK = orm.ErrMissPK
|
|
||||||
)
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ func RegisterModel(models ...interface{}) {
|
|||||||
|
|
||||||
// RegisterModelWithPrefix register models with a prefix
|
// RegisterModelWithPrefix register models with a prefix
|
||||||
func RegisterModelWithPrefix(prefix string, models ...interface{}) {
|
func RegisterModelWithPrefix(prefix string, models ...interface{}) {
|
||||||
orm.RegisterModelWithPrefix(prefix, models)
|
orm.RegisterModelWithPrefix(prefix, models...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterModelWithSuffix register models with a suffix
|
// RegisterModelWithSuffix register models with a suffix
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020
|
// Copyright 2020 beego
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -15,20 +15,17 @@
|
|||||||
package orm
|
package orm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/beego/beego/v2/client/orm"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type baseQuerySetter struct {
|
type User struct {
|
||||||
|
Id int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *baseQuerySetter) ForceIndex(indexes ...string) orm.QuerySeter {
|
type Seller struct {
|
||||||
panic("you should not invoke this method.")
|
Id int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *baseQuerySetter) UseIndex(indexes ...string) orm.QuerySeter {
|
func TestRegisterModelWithPrefix(t *testing.T) {
|
||||||
panic("you should not invoke this method.")
|
RegisterModelWithPrefix("test", &User{}, &Seller{})
|
||||||
}
|
|
||||||
|
|
||||||
func (b *baseQuerySetter) IgnoreIndex(indexes ...string) orm.QuerySeter {
|
|
||||||
panic("you should not invoke this method.")
|
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@
|
|||||||
//
|
//
|
||||||
// import (
|
// import (
|
||||||
// "fmt"
|
// "fmt"
|
||||||
// "github.com/beego/beego/v2/orm"
|
// "github.com/beego/beego/v2/client/orm"
|
||||||
// _ "github.com/go-sql-driver/mysql" // import your used driver
|
// _ "github.com/go-sql-driver/mysql" // import your used driver
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
|
|||||||
@ -195,7 +195,7 @@ func snakeStringWithAcronym(s string) string {
|
|||||||
}
|
}
|
||||||
data = append(data, d)
|
data = append(data, d)
|
||||||
}
|
}
|
||||||
return strings.ToLower(string(data[:]))
|
return strings.ToLower(string(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// snake string, XxYy to xx_yy , XxYY to xx_y_y
|
// snake string, XxYy to xx_yy , XxYY to xx_y_y
|
||||||
@ -213,7 +213,7 @@ func snakeString(s string) string {
|
|||||||
}
|
}
|
||||||
data = append(data, d)
|
data = append(data, d)
|
||||||
}
|
}
|
||||||
return strings.ToLower(string(data[:]))
|
return strings.ToLower(string(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNameStrategy set different name strategy
|
// SetNameStrategy set different name strategy
|
||||||
@ -241,7 +241,7 @@ func camelString(s string) string {
|
|||||||
}
|
}
|
||||||
data = append(data, d)
|
data = append(data, d)
|
||||||
}
|
}
|
||||||
return string(data[:])
|
return string(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
type argString []string
|
type argString []string
|
||||||
|
|||||||
@ -16,6 +16,8 @@ package orm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCamelString(t *testing.T) {
|
func TestCamelString(t *testing.T) {
|
||||||
@ -29,9 +31,7 @@ func TestCamelString(t *testing.T) {
|
|||||||
|
|
||||||
for _, v := range snake {
|
for _, v := range snake {
|
||||||
res := camelString(v)
|
res := camelString(v)
|
||||||
if res != answer[v] {
|
assert.Equal(t, answer[v], res)
|
||||||
t.Error("Unit Test Fail:", v, res, answer[v])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,9 +46,7 @@ func TestSnakeString(t *testing.T) {
|
|||||||
|
|
||||||
for _, v := range camel {
|
for _, v := range camel {
|
||||||
res := snakeString(v)
|
res := snakeString(v)
|
||||||
if res != answer[v] {
|
assert.Equal(t, answer[v], res)
|
||||||
t.Error("Unit Test Fail:", v, res, answer[v])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +61,6 @@ func TestSnakeStringWithAcronym(t *testing.T) {
|
|||||||
|
|
||||||
for _, v := range camel {
|
for _, v := range camel {
|
||||||
res := snakeStringWithAcronym(v)
|
res := snakeStringWithAcronym(v)
|
||||||
if res != answer[v] {
|
assert.Equal(t, answer[v], res)
|
||||||
t.Error("Unit Test Fail:", v, res, answer[v])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
// Simple Usage:
|
// Simple Usage:
|
||||||
// import(
|
// import(
|
||||||
// "github.com/beego/beego/v2"
|
// "github.com/beego/beego/v2"
|
||||||
// "github.com/beego/beego/v2/plugins/apiauth"
|
// "github.com/beego/beego/v2/server/web/filter/apiauth"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func main(){
|
// func main(){
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
// Simple Usage:
|
// Simple Usage:
|
||||||
// import(
|
// import(
|
||||||
// "github.com/beego/beego/v2"
|
// "github.com/beego/beego/v2"
|
||||||
// "github.com/beego/beego/v2/plugins/auth"
|
// "github.com/beego/beego/v2/server/web/filter/auth"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func main(){
|
// func main(){
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
// Simple Usage:
|
// Simple Usage:
|
||||||
// import(
|
// import(
|
||||||
// "github.com/beego/beego/v2"
|
// "github.com/beego/beego/v2"
|
||||||
// "github.com/beego/beego/v2/plugins/authz"
|
// "github.com/beego/beego/v2/server/web/filter/authz"
|
||||||
// "github.com/casbin/casbin"
|
// "github.com/casbin/casbin"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
|
|||||||
@ -26,6 +26,11 @@ import (
|
|||||||
"github.com/beego/beego/v2/adapter/plugins/auth"
|
"github.com/beego/beego/v2/adapter/plugins/auth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
authCfg = "authz_model.conf"
|
||||||
|
authCsv = "authz_policy.csv"
|
||||||
|
)
|
||||||
|
|
||||||
func testRequest(t *testing.T, handler *beego.ControllerRegister, user string, path string, method string, code int) {
|
func testRequest(t *testing.T, handler *beego.ControllerRegister, user string, path string, method string, code int) {
|
||||||
r, _ := http.NewRequest(method, path, nil)
|
r, _ := http.NewRequest(method, path, nil)
|
||||||
r.SetBasicAuth(user, "123")
|
r.SetBasicAuth(user, "123")
|
||||||
@ -40,70 +45,79 @@ func testRequest(t *testing.T, handler *beego.ControllerRegister, user string, p
|
|||||||
func TestBasic(t *testing.T) {
|
func TestBasic(t *testing.T) {
|
||||||
handler := beego.NewControllerRegister()
|
handler := beego.NewControllerRegister()
|
||||||
|
|
||||||
handler.InsertFilter("*", beego.BeforeRouter, auth.Basic("alice", "123"))
|
_ = handler.InsertFilter("*", beego.BeforeRouter, auth.Basic("alice", "123"))
|
||||||
handler.InsertFilter("*", beego.BeforeRouter, NewAuthorizer(casbin.NewEnforcer("authz_model.conf", "authz_policy.csv")))
|
|
||||||
|
_ = handler.InsertFilter("*", beego.BeforeRouter, NewAuthorizer(casbin.NewEnforcer(authCfg, authCsv)))
|
||||||
|
|
||||||
handler.Any("*", func(ctx *context.Context) {
|
handler.Any("*", func(ctx *context.Context) {
|
||||||
ctx.Output.SetStatus(200)
|
ctx.Output.SetStatus(200)
|
||||||
})
|
})
|
||||||
|
|
||||||
testRequest(t, handler, "alice", "/dataset1/resource1", "GET", 200)
|
const d1r1 = "/dataset1/resource1"
|
||||||
testRequest(t, handler, "alice", "/dataset1/resource1", "POST", 200)
|
testRequest(t, handler, "alice", d1r1, "GET", 200)
|
||||||
testRequest(t, handler, "alice", "/dataset1/resource2", "GET", 200)
|
testRequest(t, handler, "alice", d1r1, "POST", 200)
|
||||||
testRequest(t, handler, "alice", "/dataset1/resource2", "POST", 403)
|
const d1r2 = "/dataset1/resource2"
|
||||||
|
testRequest(t, handler, "alice", d1r2, "GET", 200)
|
||||||
|
testRequest(t, handler, "alice", d1r2, "POST", 403)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPathWildcard(t *testing.T) {
|
func TestPathWildcard(t *testing.T) {
|
||||||
handler := beego.NewControllerRegister()
|
handler := beego.NewControllerRegister()
|
||||||
|
|
||||||
handler.InsertFilter("*", beego.BeforeRouter, auth.Basic("bob", "123"))
|
_ = handler.InsertFilter("*", beego.BeforeRouter, auth.Basic("bob", "123"))
|
||||||
handler.InsertFilter("*", beego.BeforeRouter, NewAuthorizer(casbin.NewEnforcer("authz_model.conf", "authz_policy.csv")))
|
_ = handler.InsertFilter("*", beego.BeforeRouter, NewAuthorizer(casbin.NewEnforcer(authCfg, authCsv)))
|
||||||
|
|
||||||
handler.Any("*", func(ctx *context.Context) {
|
handler.Any("*", func(ctx *context.Context) {
|
||||||
ctx.Output.SetStatus(200)
|
ctx.Output.SetStatus(200)
|
||||||
})
|
})
|
||||||
|
|
||||||
testRequest(t, handler, "bob", "/dataset2/resource1", "GET", 200)
|
const d2r1 = "/dataset2/resource1"
|
||||||
testRequest(t, handler, "bob", "/dataset2/resource1", "POST", 200)
|
testRequest(t, handler, "bob", d2r1, "GET", 200)
|
||||||
testRequest(t, handler, "bob", "/dataset2/resource1", "DELETE", 200)
|
testRequest(t, handler, "bob", d2r1, "POST", 200)
|
||||||
testRequest(t, handler, "bob", "/dataset2/resource2", "GET", 200)
|
testRequest(t, handler, "bob", d2r1, "DELETE", 200)
|
||||||
testRequest(t, handler, "bob", "/dataset2/resource2", "POST", 403)
|
const d2r2 = "/dataset2/resource2"
|
||||||
testRequest(t, handler, "bob", "/dataset2/resource2", "DELETE", 403)
|
testRequest(t, handler, "bob", d2r2, "GET", 200)
|
||||||
|
testRequest(t, handler, "bob", d2r2, "POST", 403)
|
||||||
|
testRequest(t, handler, "bob", d2r2, "DELETE", 403)
|
||||||
|
|
||||||
testRequest(t, handler, "bob", "/dataset2/folder1/item1", "GET", 403)
|
const item1 = "/dataset2/folder1/item1"
|
||||||
testRequest(t, handler, "bob", "/dataset2/folder1/item1", "POST", 200)
|
testRequest(t, handler, "bob", item1, "GET", 403)
|
||||||
testRequest(t, handler, "bob", "/dataset2/folder1/item1", "DELETE", 403)
|
testRequest(t, handler, "bob", item1, "POST", 200)
|
||||||
testRequest(t, handler, "bob", "/dataset2/folder1/item2", "GET", 403)
|
testRequest(t, handler, "bob", item1, "DELETE", 403)
|
||||||
testRequest(t, handler, "bob", "/dataset2/folder1/item2", "POST", 200)
|
const item2 = "/dataset2/folder1/item2"
|
||||||
testRequest(t, handler, "bob", "/dataset2/folder1/item2", "DELETE", 403)
|
testRequest(t, handler, "bob", item2, "GET", 403)
|
||||||
|
testRequest(t, handler, "bob", item2, "POST", 200)
|
||||||
|
testRequest(t, handler, "bob", item2, "DELETE", 403)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRBAC(t *testing.T) {
|
func TestRBAC(t *testing.T) {
|
||||||
handler := beego.NewControllerRegister()
|
handler := beego.NewControllerRegister()
|
||||||
|
|
||||||
handler.InsertFilter("*", beego.BeforeRouter, auth.Basic("cathy", "123"))
|
_ = handler.InsertFilter("*", beego.BeforeRouter, auth.Basic("cathy", "123"))
|
||||||
e := casbin.NewEnforcer("authz_model.conf", "authz_policy.csv")
|
e := casbin.NewEnforcer(authCfg, authCsv)
|
||||||
handler.InsertFilter("*", beego.BeforeRouter, NewAuthorizer(e))
|
_ = handler.InsertFilter("*", beego.BeforeRouter, NewAuthorizer(e))
|
||||||
|
|
||||||
handler.Any("*", func(ctx *context.Context) {
|
handler.Any("*", func(ctx *context.Context) {
|
||||||
ctx.Output.SetStatus(200)
|
ctx.Output.SetStatus(200)
|
||||||
})
|
})
|
||||||
|
|
||||||
// cathy can access all /dataset1/* resources via all methods because it has the dataset1_admin role.
|
// cathy can access all /dataset1/* resources via all methods because it has the dataset1_admin role.
|
||||||
testRequest(t, handler, "cathy", "/dataset1/item", "GET", 200)
|
const dataSet1 = "/dataset1/item"
|
||||||
testRequest(t, handler, "cathy", "/dataset1/item", "POST", 200)
|
testRequest(t, handler, "cathy", dataSet1, "GET", 200)
|
||||||
testRequest(t, handler, "cathy", "/dataset1/item", "DELETE", 200)
|
testRequest(t, handler, "cathy", dataSet1, "POST", 200)
|
||||||
testRequest(t, handler, "cathy", "/dataset2/item", "GET", 403)
|
testRequest(t, handler, "cathy", dataSet1, "DELETE", 200)
|
||||||
testRequest(t, handler, "cathy", "/dataset2/item", "POST", 403)
|
const dataSet2 = "/dataset2/item"
|
||||||
testRequest(t, handler, "cathy", "/dataset2/item", "DELETE", 403)
|
testRequest(t, handler, "cathy", dataSet2, "GET", 403)
|
||||||
|
testRequest(t, handler, "cathy", dataSet2, "POST", 403)
|
||||||
|
testRequest(t, handler, "cathy", dataSet2, "DELETE", 403)
|
||||||
|
|
||||||
// delete all roles on user cathy, so cathy cannot access any resources now.
|
// delete all roles on user cathy, so cathy cannot access any resources now.
|
||||||
e.DeleteRolesForUser("cathy")
|
e.DeleteRolesForUser("cathy")
|
||||||
|
|
||||||
testRequest(t, handler, "cathy", "/dataset1/item", "GET", 403)
|
testRequest(t, handler, "cathy", dataSet1, "GET", 403)
|
||||||
testRequest(t, handler, "cathy", "/dataset1/item", "POST", 403)
|
testRequest(t, handler, "cathy", dataSet1, "POST", 403)
|
||||||
testRequest(t, handler, "cathy", "/dataset1/item", "DELETE", 403)
|
testRequest(t, handler, "cathy", dataSet1, "DELETE", 403)
|
||||||
testRequest(t, handler, "cathy", "/dataset2/item", "GET", 403)
|
testRequest(t, handler, "cathy", dataSet2, "GET", 403)
|
||||||
testRequest(t, handler, "cathy", "/dataset2/item", "POST", 403)
|
testRequest(t, handler, "cathy", dataSet2, "POST", 403)
|
||||||
testRequest(t, handler, "cathy", "/dataset2/item", "DELETE", 403)
|
testRequest(t, handler, "cathy", dataSet2, "DELETE", 403)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
// Usage
|
// Usage
|
||||||
// import (
|
// import (
|
||||||
// "github.com/beego/beego/v2"
|
// "github.com/beego/beego/v2"
|
||||||
// "github.com/beego/beego/v2/plugins/cors"
|
// "github.com/beego/beego/v2/server/web/filter/cors"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func main() {
|
// func main() {
|
||||||
@ -37,10 +37,9 @@ package cors
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
beego "github.com/beego/beego/v2/adapter"
|
beego "github.com/beego/beego/v2/adapter"
|
||||||
|
"github.com/beego/beego/v2/adapter/context"
|
||||||
beecontext "github.com/beego/beego/v2/server/web/context"
|
beecontext "github.com/beego/beego/v2/server/web/context"
|
||||||
"github.com/beego/beego/v2/server/web/filter/cors"
|
"github.com/beego/beego/v2/server/web/filter/cors"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Options represents Access Control options.
|
// Options represents Access Control options.
|
||||||
|
|||||||
@ -19,9 +19,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
beecontext "github.com/beego/beego/v2/adapter/context"
|
beecontext "github.com/beego/beego/v2/adapter/context"
|
||||||
"github.com/beego/beego/v2/server/web/context"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/server/web"
|
"github.com/beego/beego/v2/server/web"
|
||||||
|
"github.com/beego/beego/v2/server/web/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// default filter execution points
|
// default filter execution points
|
||||||
@ -87,7 +86,7 @@ func NewControllerRegister() *ControllerRegister {
|
|||||||
// Add("/api",&RestController{},"get,post:ApiFunc"
|
// Add("/api",&RestController{},"get,post:ApiFunc"
|
||||||
// Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
|
// Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
|
||||||
func (p *ControllerRegister) Add(pattern string, c ControllerInterface, mappingMethods ...string) {
|
func (p *ControllerRegister) Add(pattern string, c ControllerInterface, mappingMethods ...string) {
|
||||||
(*web.ControllerRegister)(p).Add(pattern, c, mappingMethods...)
|
(*web.ControllerRegister)(p).Add(pattern, c, web.WithRouterMethods(c, mappingMethods...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include only when the Runmode is dev will generate router file in the router/auto.go from the controller
|
// Include only when the Runmode is dev will generate router file in the router/auto.go from the controller
|
||||||
@ -217,7 +216,7 @@ func (p *ControllerRegister) Handler(pattern string, h http.Handler, options ...
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddAuto router to ControllerRegister.
|
// AddAuto router to ControllerRegister.
|
||||||
// example beego.AddAuto(&MainContorlller{}),
|
// example beego.AddAuto(&MainController{}),
|
||||||
// MainController has method List and Page.
|
// MainController has method List and Page.
|
||||||
// visit the url /main/list to execute List function
|
// visit the url /main/list to execute List function
|
||||||
// /main/page to execute Page function.
|
// /main/page to execute Page function.
|
||||||
@ -226,7 +225,7 @@ func (p *ControllerRegister) AddAuto(c ControllerInterface) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddAutoPrefix Add auto router to ControllerRegister with prefix.
|
// AddAutoPrefix Add auto router to ControllerRegister with prefix.
|
||||||
// example beego.AddAutoPrefix("/admin",&MainContorlller{}),
|
// example beego.AddAutoPrefix("/admin",&MainController{}),
|
||||||
// MainController has method List and Page.
|
// MainController has method List and Page.
|
||||||
// visit the url /admin/main/list to execute List function
|
// visit the url /admin/main/list to execute List function
|
||||||
// /admin/main/page to execute Page function.
|
// /admin/main/page to execute Page function.
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/session/couchbase"
|
// _ "github.com/beego/beego/v2/server/web/session/couchbase"
|
||||||
// "github.com/beego/beego/v2/session"
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/session/memcache"
|
// _ "github.com/beego/beego/v2/server/web/session/memcache"
|
||||||
// "github.com/beego/beego/v2/session"
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
@ -37,7 +37,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/session"
|
"github.com/beego/beego/v2/adapter/session"
|
||||||
|
|
||||||
beemem "github.com/beego/beego/v2/server/web/session/memcache"
|
beemem "github.com/beego/beego/v2/server/web/session/memcache"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -28,8 +28,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/session/mysql"
|
// _ "github.com/beego/beego/v2/server/web/session/mysql"
|
||||||
// "github.com/beego/beego/v2/session"
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
@ -44,11 +44,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/session"
|
|
||||||
"github.com/beego/beego/v2/server/web/session/mysql"
|
|
||||||
|
|
||||||
// import mysql driver
|
// import mysql driver
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/adapter/session"
|
||||||
|
"github.com/beego/beego/v2/server/web/session/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@ -38,8 +38,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/session/postgresql"
|
// _ "github.com/beego/beego/v2/server/web/session/postgresql"
|
||||||
// "github.com/beego/beego/v2/session"
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
@ -54,10 +54,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/session"
|
|
||||||
// import postgresql Driver
|
// import postgresql Driver
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/adapter/session"
|
||||||
"github.com/beego/beego/v2/server/web/session/postgres"
|
"github.com/beego/beego/v2/server/web/session/postgres"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/session/redis"
|
// _ "github.com/beego/beego/v2/server/web/session/redis"
|
||||||
// "github.com/beego/beego/v2/session"
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
@ -37,7 +37,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/session"
|
"github.com/beego/beego/v2/adapter/session"
|
||||||
|
|
||||||
beeRedis "github.com/beego/beego/v2/server/web/session/redis"
|
beeRedis "github.com/beego/beego/v2/server/web/session/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/session/redis_cluster"
|
// _ "github.com/beego/beego/v2/server/web/session/redis_cluster"
|
||||||
// "github.com/beego/beego/v2/session"
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// _ "github.com/beego/beego/v2/session/redis_sentinel"
|
// _ "github.com/beego/beego/v2/server/web/session/redis_sentinel"
|
||||||
// "github.com/beego/beego/v2/session"
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
@ -37,7 +37,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/session"
|
"github.com/beego/beego/v2/adapter/session"
|
||||||
|
|
||||||
sentinel "github.com/beego/beego/v2/server/web/session/redis_sentinel"
|
sentinel "github.com/beego/beego/v2/server/web/session/redis_sentinel"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/session"
|
"github.com/beego/beego/v2/adapter/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,72 +21,55 @@ func TestRedisSentinel(t *testing.T) {
|
|||||||
ProviderConfig: "127.0.0.1:6379,100,,0,master",
|
ProviderConfig: "127.0.0.1:6379,100,,0,master",
|
||||||
}
|
}
|
||||||
globalSessions, e := session.NewManager("redis_sentinel", sessionConfig)
|
globalSessions, e := session.NewManager("redis_sentinel", sessionConfig)
|
||||||
|
|
||||||
if e != nil {
|
if e != nil {
|
||||||
t.Log(e)
|
t.Log(e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// todo test if e==nil
|
|
||||||
go globalSessions.GC()
|
go globalSessions.GC()
|
||||||
|
|
||||||
r, _ := http.NewRequest("GET", "/", nil)
|
r, _ := http.NewRequest("GET", "/", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
sess, err := globalSessions.SessionStart(w, r)
|
sess, err := globalSessions.SessionStart(w, r)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal("session start failed:", err)
|
|
||||||
}
|
|
||||||
defer sess.SessionRelease(w)
|
defer sess.SessionRelease(w)
|
||||||
|
|
||||||
// SET AND GET
|
// SET AND GET
|
||||||
err = sess.Set("username", "astaxie")
|
err = sess.Set("username", "astaxie")
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal("set username failed:", err)
|
|
||||||
}
|
|
||||||
username := sess.Get("username")
|
username := sess.Get("username")
|
||||||
if username != "astaxie" {
|
assert.Equal(t, "astaxie", username)
|
||||||
t.Fatal("get username failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
err = sess.Delete("username")
|
err = sess.Delete("username")
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal("delete username failed:", err)
|
|
||||||
}
|
|
||||||
username = sess.Get("username")
|
username = sess.Get("username")
|
||||||
if username != nil {
|
assert.Nil(t, username)
|
||||||
t.Fatal("delete username failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// FLUSH
|
// FLUSH
|
||||||
err = sess.Set("username", "astaxie")
|
err = sess.Set("username", "astaxie")
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal("set failed:", err)
|
|
||||||
}
|
|
||||||
err = sess.Set("password", "1qaz2wsx")
|
err = sess.Set("password", "1qaz2wsx")
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal("set failed:", err)
|
|
||||||
}
|
|
||||||
username = sess.Get("username")
|
username = sess.Get("username")
|
||||||
if username != "astaxie" {
|
assert.Equal(t, "astaxie", username)
|
||||||
t.Fatal("get username failed")
|
|
||||||
}
|
|
||||||
password := sess.Get("password")
|
password := sess.Get("password")
|
||||||
if password != "1qaz2wsx" {
|
assert.Equal(t, "1qaz2wsx", password)
|
||||||
t.Fatal("get password failed")
|
|
||||||
}
|
|
||||||
err = sess.Flush()
|
err = sess.Flush()
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal("flush failed:", err)
|
|
||||||
}
|
|
||||||
username = sess.Get("username")
|
username = sess.Get("username")
|
||||||
if username != nil {
|
assert.Nil(t, username)
|
||||||
t.Fatal("flush failed")
|
|
||||||
}
|
|
||||||
password = sess.Get("password")
|
password = sess.Get("password")
|
||||||
if password != nil {
|
assert.Nil(t, password)
|
||||||
t.Fatal("flush failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
sess.SessionRelease(w)
|
sess.SessionRelease(w)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const setCookieKey = "Set-Cookie"
|
||||||
|
|
||||||
func TestCookie(t *testing.T) {
|
func TestCookie(t *testing.T) {
|
||||||
config := `{"cookieName":"gosessionid","enableSetCookie":false,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}`
|
config := `{"cookieName":"gosessionid","enableSetCookie":false,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}`
|
||||||
conf := new(ManagerConfig)
|
conf := new(ManagerConfig)
|
||||||
@ -46,7 +48,8 @@ func TestCookie(t *testing.T) {
|
|||||||
t.Fatal("get username error")
|
t.Fatal("get username error")
|
||||||
}
|
}
|
||||||
sess.SessionRelease(w)
|
sess.SessionRelease(w)
|
||||||
if cookiestr := w.Header().Get("Set-Cookie"); cookiestr == "" {
|
|
||||||
|
if cookiestr := w.Header().Get(setCookieKey); cookiestr == "" {
|
||||||
t.Fatal("setcookie error")
|
t.Fatal("setcookie error")
|
||||||
} else {
|
} else {
|
||||||
parts := strings.Split(strings.TrimSpace(cookiestr), ";")
|
parts := strings.Split(strings.TrimSpace(cookiestr), ";")
|
||||||
@ -79,7 +82,7 @@ func TestDestorySessionCookie(t *testing.T) {
|
|||||||
|
|
||||||
// request again ,will get same sesssion id .
|
// request again ,will get same sesssion id .
|
||||||
r1, _ := http.NewRequest("GET", "/", nil)
|
r1, _ := http.NewRequest("GET", "/", nil)
|
||||||
r1.Header.Set("Cookie", w.Header().Get("Set-Cookie"))
|
r1.Header.Set("Cookie", w.Header().Get(setCookieKey))
|
||||||
w = httptest.NewRecorder()
|
w = httptest.NewRecorder()
|
||||||
newSession, err := globalSessions.SessionStart(w, r1)
|
newSession, err := globalSessions.SessionStart(w, r1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -92,7 +95,7 @@ func TestDestorySessionCookie(t *testing.T) {
|
|||||||
// After destroy session , will get a new session id .
|
// After destroy session , will get a new session id .
|
||||||
globalSessions.SessionDestroy(w, r1)
|
globalSessions.SessionDestroy(w, r1)
|
||||||
r2, _ := http.NewRequest("GET", "/", nil)
|
r2, _ := http.NewRequest("GET", "/", nil)
|
||||||
r2.Header.Set("Cookie", w.Header().Get("Set-Cookie"))
|
r2.Header.Set("Cookie", w.Header().Get(setCookieKey))
|
||||||
|
|
||||||
w = httptest.NewRecorder()
|
w = httptest.NewRecorder()
|
||||||
newSession, err = globalSessions.SessionStart(w, r2)
|
newSession, err = globalSessions.SessionStart(w, r2)
|
||||||
|
|||||||
@ -22,15 +22,15 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const sid = "Session_id"
|
const (
|
||||||
const sidNew = "Session_id_new"
|
sid = "Session_id"
|
||||||
const sessionPath = "./_session_runtime"
|
sidNew = "Session_id_new"
|
||||||
|
sessionPath = "./_session_runtime"
|
||||||
var (
|
|
||||||
mutex sync.Mutex
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFileProvider_SessionExist(t *testing.T) {
|
var mutex sync.Mutex
|
||||||
|
|
||||||
|
func TestFileProviderSessionExist(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -53,7 +53,7 @@ func TestFileProvider_SessionExist(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileProvider_SessionExist2(t *testing.T) {
|
func TestFileProviderSessionExist2(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -75,7 +75,7 @@ func TestFileProvider_SessionExist2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileProvider_SessionRead(t *testing.T) {
|
func TestFileProviderSessionRead(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -97,7 +97,7 @@ func TestFileProvider_SessionRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileProvider_SessionRead1(t *testing.T) {
|
func TestFileProviderSessionRead1(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -117,7 +117,7 @@ func TestFileProvider_SessionRead1(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileProvider_SessionAll(t *testing.T) {
|
func TestFileProviderSessionAll(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -140,7 +140,7 @@ func TestFileProvider_SessionAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileProvider_SessionRegenerate(t *testing.T) {
|
func TestFileProviderSessionRegenerate(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -172,7 +172,7 @@ func TestFileProvider_SessionRegenerate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileProvider_SessionDestroy(t *testing.T) {
|
func TestFileProviderSessionDestroy(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -200,7 +200,7 @@ func TestFileProvider_SessionDestroy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileProvider_SessionGC(t *testing.T) {
|
func TestFileProviderSessionGC(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -226,7 +226,7 @@ func TestFileProvider_SessionGC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileSessionStore_Set(t *testing.T) {
|
func TestFileSessionStoreSet(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -245,7 +245,7 @@ func TestFileSessionStore_Set(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileSessionStore_Get(t *testing.T) {
|
func TestFileSessionStoreGet(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -266,7 +266,7 @@ func TestFileSessionStore_Get(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileSessionStore_Delete(t *testing.T) {
|
func TestFileSessionStoreDelete(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -289,7 +289,7 @@ func TestFileSessionStore_Delete(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileSessionStore_Flush(t *testing.T) {
|
func TestFileSessionStoreFlush(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
@ -313,7 +313,7 @@ func TestFileSessionStore_Flush(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileSessionStore_SessionID(t *testing.T) {
|
func TestFileSessionStoreSessionID(t *testing.T) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
os.RemoveAll(sessionPath)
|
os.RemoveAll(sessionPath)
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_gob(t *testing.T) {
|
func TestGob(t *testing.T) {
|
||||||
a := make(map[interface{}]interface{})
|
a := make(map[interface{}]interface{})
|
||||||
a["username"] = "astaxie"
|
a["username"] = "astaxie"
|
||||||
a[12] = 234
|
a[12] = 234
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
// import(
|
// import(
|
||||||
// "github.com/beego/beego/v2/session"
|
// "github.com/beego/beego/v2/server/web/session"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/session"
|
"github.com/beego/beego/v2/adapter/session"
|
||||||
|
|
||||||
beeSsdb "github.com/beego/beego/v2/server/web/session/ssdb"
|
beeSsdb "github.com/beego/beego/v2/server/web/session/ssdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -118,7 +118,6 @@ func AssetsJs(text string) template.HTML {
|
|||||||
|
|
||||||
// AssetsCSS returns stylesheet link tag with src string.
|
// AssetsCSS returns stylesheet link tag with src string.
|
||||||
func AssetsCSS(text string) template.HTML {
|
func AssetsCSS(text string) template.HTML {
|
||||||
|
|
||||||
text = "<link href=\"" + text + "\" rel=\"stylesheet\" />"
|
text = "<link href=\"" + text + "\" rel=\"stylesheet\" />"
|
||||||
|
|
||||||
return template.HTML(text)
|
return template.HTML(text)
|
||||||
|
|||||||
@ -19,19 +19,15 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSubstr(t *testing.T) {
|
func TestSubstr(t *testing.T) {
|
||||||
s := `012345`
|
s := `012345`
|
||||||
if Substr(s, 0, 2) != "01" {
|
assert.Equal(t, "01", Substr(s, 0, 2))
|
||||||
t.Error("should be equal")
|
assert.Equal(t, "012345", Substr(s, 0, 100))
|
||||||
}
|
assert.Equal(t, "012345", Substr(s, 12, 100))
|
||||||
if Substr(s, 0, 100) != "012345" {
|
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
if Substr(s, 12, 100) != "012345" {
|
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHtml2str(t *testing.T) {
|
func TestHtml2str(t *testing.T) {
|
||||||
@ -39,73 +35,50 @@ func TestHtml2str(t *testing.T) {
|
|||||||
|
|
||||||
|
|
||||||
\n`
|
\n`
|
||||||
if HTML2str(h) != "123\\n\n\\n" {
|
assert.Equal(t, "123\\n\n\\n", HTML2str(h))
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDateFormat(t *testing.T) {
|
func TestDateFormat(t *testing.T) {
|
||||||
ts := "Mon, 01 Jul 2013 13:27:42 CST"
|
ts := "Mon, 01 Jul 2013 13:27:42 CST"
|
||||||
tt, _ := time.Parse(time.RFC1123, ts)
|
tt, _ := time.Parse(time.RFC1123, ts)
|
||||||
|
|
||||||
if ss := DateFormat(tt, "2006-01-02 15:04:05"); ss != "2013-07-01 13:27:42" {
|
assert.Equal(t, "2013-07-01 13:27:42", DateFormat(tt, "2006-01-02 15:04:05"))
|
||||||
t.Errorf("2013-07-01 13:27:42 does not equal %v", ss)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDate(t *testing.T) {
|
func TestDate(t *testing.T) {
|
||||||
ts := "Mon, 01 Jul 2013 13:27:42 CST"
|
ts := "Mon, 01 Jul 2013 13:27:42 CST"
|
||||||
tt, _ := time.Parse(time.RFC1123, ts)
|
tt, _ := time.Parse(time.RFC1123, ts)
|
||||||
|
|
||||||
if ss := Date(tt, "Y-m-d H:i:s"); ss != "2013-07-01 13:27:42" {
|
assert.Equal(t, "2013-07-01 13:27:42", Date(tt, "Y-m-d H:i:s"))
|
||||||
t.Errorf("2013-07-01 13:27:42 does not equal %v", ss)
|
|
||||||
}
|
assert.Equal(t, "13-7-1 01:27:42 PM", Date(tt, "y-n-j h:i:s A"))
|
||||||
if ss := Date(tt, "y-n-j h:i:s A"); ss != "13-7-1 01:27:42 PM" {
|
assert.Equal(t, "Mon, 01 Jul 2013 1:27:42 pm", Date(tt, "D, d M Y g:i:s a"))
|
||||||
t.Errorf("13-7-1 01:27:42 PM does not equal %v", ss)
|
assert.Equal(t, "Monday, 01 July 2013 13:27:42", Date(tt, "l, d F Y G:i:s"))
|
||||||
}
|
|
||||||
if ss := Date(tt, "D, d M Y g:i:s a"); ss != "Mon, 01 Jul 2013 1:27:42 pm" {
|
|
||||||
t.Errorf("Mon, 01 Jul 2013 1:27:42 pm does not equal %v", ss)
|
|
||||||
}
|
|
||||||
if ss := Date(tt, "l, d F Y G:i:s"); ss != "Monday, 01 July 2013 13:27:42" {
|
|
||||||
t.Errorf("Monday, 01 July 2013 13:27:42 does not equal %v", ss)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompareRelated(t *testing.T) {
|
func TestCompareRelated(t *testing.T) {
|
||||||
if !Compare("abc", "abc") {
|
assert.True(t, Compare("abc", "abc"))
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
assert.False(t, Compare("abc", "aBc"))
|
||||||
if Compare("abc", "aBc") {
|
|
||||||
t.Error("should be not equal")
|
assert.True(t, Compare("1", 1))
|
||||||
}
|
|
||||||
if !Compare("1", 1) {
|
assert.False(t, CompareNot("abc", "abc"))
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
assert.True(t, CompareNot("abc", "aBc"))
|
||||||
if CompareNot("abc", "abc") {
|
assert.True(t, NotNil("a string"))
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
if !CompareNot("abc", "aBc") {
|
|
||||||
t.Error("should be not equal")
|
|
||||||
}
|
|
||||||
if !NotNil("a string") {
|
|
||||||
t.Error("should not be nil")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHtmlquote(t *testing.T) {
|
func TestHtmlquote(t *testing.T) {
|
||||||
h := `<' ”“&">`
|
h := `<' ”“&">`
|
||||||
s := `<' ”“&">`
|
s := `<' ”“&">`
|
||||||
if Htmlquote(s) != h {
|
assert.Equal(t, h, Htmlquote(s))
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHtmlunquote(t *testing.T) {
|
func TestHtmlunquote(t *testing.T) {
|
||||||
h := `<' ”“&">`
|
h := `<' ”“&">`
|
||||||
s := `<' ”“&">`
|
s := `<' ”“&">`
|
||||||
if Htmlunquote(h) != s {
|
assert.Equal(t, s, Htmlunquote(h))
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseForm(t *testing.T) {
|
func TestParseForm(t *testing.T) {
|
||||||
@ -148,55 +121,42 @@ func TestParseForm(t *testing.T) {
|
|||||||
"hobby": []string{"", "Basketball", "Football"},
|
"hobby": []string{"", "Basketball", "Football"},
|
||||||
"memo": []string{"nothing"},
|
"memo": []string{"nothing"},
|
||||||
}
|
}
|
||||||
if err := ParseForm(form, u); err == nil {
|
|
||||||
t.Fatal("nothing will be changed")
|
assert.NotNil(t, ParseForm(form, u))
|
||||||
}
|
|
||||||
if err := ParseForm(form, &u); err != nil {
|
assert.Nil(t, ParseForm(form, &u))
|
||||||
t.Fatal(err)
|
|
||||||
}
|
assert.Equal(t, 0, u.ID)
|
||||||
if u.ID != 0 {
|
|
||||||
t.Errorf("ID should equal 0 but got %v", u.ID)
|
assert.Equal(t, 0, len(u.tag))
|
||||||
}
|
|
||||||
if len(u.tag) != 0 {
|
assert.Equal(t, "test", u.Name)
|
||||||
t.Errorf("tag's length should equal 0 but got %v", len(u.tag))
|
|
||||||
}
|
assert.Equal(t, 40, u.Age)
|
||||||
if u.Name.(string) != "test" {
|
|
||||||
t.Errorf("Name should equal `test` but got `%v`", u.Name.(string))
|
assert.Equal(t, "test@gmail.com", u.Email)
|
||||||
}
|
|
||||||
if u.Age != 40 {
|
assert.Equal(t, "I am an engineer!", u.Intro)
|
||||||
t.Errorf("Age should equal 40 but got %v", u.Age)
|
|
||||||
}
|
assert.True(t, u.StrBool)
|
||||||
if u.Email != "test@gmail.com" {
|
|
||||||
t.Errorf("Email should equal `test@gmail.com` but got `%v`", u.Email)
|
|
||||||
}
|
|
||||||
if u.Intro != "I am an engineer!" {
|
|
||||||
t.Errorf("Intro should equal `I am an engineer!` but got `%v`", u.Intro)
|
|
||||||
}
|
|
||||||
if !u.StrBool {
|
|
||||||
t.Errorf("strboll should equal `true`, but got `%v`", u.StrBool)
|
|
||||||
}
|
|
||||||
y, m, d := u.Date.Date()
|
y, m, d := u.Date.Date()
|
||||||
if y != 2014 || m.String() != "November" || d != 12 {
|
|
||||||
t.Errorf("Date should equal `2014-11-12`, but got `%v`", u.Date.String())
|
assert.Equal(t, 2014, y)
|
||||||
}
|
assert.Equal(t, "November", m.String())
|
||||||
if u.Organization != "beego" {
|
assert.Equal(t, 12, d)
|
||||||
t.Errorf("Organization should equal `beego`, but got `%v`", u.Organization)
|
|
||||||
}
|
assert.Equal(t, "beego", u.Organization)
|
||||||
if u.Title != "CXO" {
|
|
||||||
t.Errorf("Title should equal `CXO`, but got `%v`", u.Title)
|
assert.Equal(t, "CXO", u.Title)
|
||||||
}
|
|
||||||
if u.Hobby[0] != "" {
|
assert.Equal(t, "", u.Hobby[0])
|
||||||
t.Errorf("Hobby should equal ``, but got `%v`", u.Hobby[0])
|
|
||||||
}
|
assert.Equal(t, "Basketball", u.Hobby[1])
|
||||||
if u.Hobby[1] != "Basketball" {
|
|
||||||
t.Errorf("Hobby should equal `Basketball`, but got `%v`", u.Hobby[1])
|
assert.Equal(t, "Football", u.Hobby[2])
|
||||||
}
|
|
||||||
if u.Hobby[2] != "Football" {
|
assert.Equal(t, 0, len(u.Memo))
|
||||||
t.Errorf("Hobby should equal `Football`, but got `%v`", u.Hobby[2])
|
|
||||||
}
|
|
||||||
if len(u.Memo) != 0 {
|
|
||||||
t.Errorf("Memo's length should equal 0 but got %v", len(u.Memo))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRenderForm(t *testing.T) {
|
func TestRenderForm(t *testing.T) {
|
||||||
@ -212,18 +172,14 @@ func TestRenderForm(t *testing.T) {
|
|||||||
|
|
||||||
u := user{Name: "test", Intro: "Some Text"}
|
u := user{Name: "test", Intro: "Some Text"}
|
||||||
output := RenderForm(u)
|
output := RenderForm(u)
|
||||||
if output != template.HTML("") {
|
assert.Equal(t, template.HTML(""), output)
|
||||||
t.Errorf("output should be empty but got %v", output)
|
|
||||||
}
|
|
||||||
output = RenderForm(&u)
|
output = RenderForm(&u)
|
||||||
result := template.HTML(
|
result := template.HTML(
|
||||||
`Name: <input name="username" type="text" value="test"></br>` +
|
`Name: <input name="username" type="text" value="test"></br>` +
|
||||||
`年龄:<input name="age" type="text" value="0"></br>` +
|
`年龄:<input name="age" type="text" value="0"></br>` +
|
||||||
`Sex: <input name="Sex" type="text" value=""></br>` +
|
`Sex: <input name="Sex" type="text" value=""></br>` +
|
||||||
`Intro: <textarea name="Intro">Some Text</textarea>`)
|
`Intro: <textarea name="Intro">Some Text</textarea>`)
|
||||||
if output != result {
|
assert.Equal(t, result, output)
|
||||||
t.Errorf("output should equal `%v` but got `%v`", result, output)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMapGet(t *testing.T) {
|
func TestMapGet(t *testing.T) {
|
||||||
@ -233,29 +189,17 @@ func TestMapGet(t *testing.T) {
|
|||||||
"1": 2,
|
"1": 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
if res, err := MapGet(m1, "a"); err == nil {
|
res, err := MapGet(m1, "a")
|
||||||
if res.(int64) != 1 {
|
assert.Nil(t, err)
|
||||||
t.Errorf("Should return 1, but return %v", res)
|
assert.Equal(t, int64(1), res)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Errorf("Error happens %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res, err := MapGet(m1, "1"); err == nil {
|
res, err = MapGet(m1, "1")
|
||||||
if res.(int64) != 2 {
|
assert.Nil(t, err)
|
||||||
t.Errorf("Should return 2, but return %v", res)
|
assert.Equal(t, int64(2), res)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Errorf("Error happens %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res, err := MapGet(m1, 1); err == nil {
|
res, err = MapGet(m1, 1)
|
||||||
if res.(int64) != 2 {
|
assert.Nil(t, err)
|
||||||
t.Errorf("Should return 2, but return %v", res)
|
assert.Equal(t, int64(2), res)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Errorf("Error happens %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// test 2 level map
|
// test 2 level map
|
||||||
m2 := M{
|
m2 := M{
|
||||||
@ -264,13 +208,9 @@ func TestMapGet(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if res, err := MapGet(m2, 1, 2); err == nil {
|
res, err = MapGet(m2, 1, 2)
|
||||||
if res.(float64) != 3.5 {
|
assert.Nil(t, err)
|
||||||
t.Errorf("Should return 3.5, but return %v", res)
|
assert.Equal(t, 3.5, res)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Errorf("Error happens %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// test 5 level map
|
// test 5 level map
|
||||||
m5 := M{
|
m5 := M{
|
||||||
@ -285,20 +225,12 @@ func TestMapGet(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if res, err := MapGet(m5, 1, 2, 3, 4, 5); err == nil {
|
res, err = MapGet(m5, 1, 2, 3, 4, 5)
|
||||||
if res.(float64) != 1.2 {
|
assert.Nil(t, err)
|
||||||
t.Errorf("Should return 1.2, but return %v", res)
|
assert.Equal(t, 1.2, res)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Errorf("Error happens %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check whether element not exists in map
|
// check whether element not exists in map
|
||||||
if res, err := MapGet(m5, 5, 4, 3, 2, 1); err == nil {
|
res, err = MapGet(m5, 5, 4, 3, 2, 1)
|
||||||
if res != nil {
|
assert.Nil(t, err)
|
||||||
t.Errorf("Should return nil, but return %v", res)
|
assert.Nil(t, res)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Errorf("Error happens %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,12 +14,7 @@
|
|||||||
|
|
||||||
package testing
|
package testing
|
||||||
|
|
||||||
import (
|
import "github.com/beego/beego/v2/client/httplib/testing"
|
||||||
"github.com/beego/beego/v2/client/httplib/testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var port = ""
|
|
||||||
var baseURL = "http://localhost:"
|
|
||||||
|
|
||||||
// TestHTTPRequest beego test request client
|
// TestHTTPRequest beego test request client
|
||||||
type TestHTTPRequest testing.TestHTTPRequest
|
type TestHTTPRequest testing.TestHTTPRequest
|
||||||
|
|||||||
@ -16,19 +16,10 @@ package toolbox
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/core/admin"
|
"github.com/beego/beego/v2/core/admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var startTime = time.Now()
|
|
||||||
var pid int
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
pid = os.Getpid()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessInput parse input command string
|
// ProcessInput parse input command string
|
||||||
func ProcessInput(input string, w io.Writer) {
|
func ProcessInput(input string, w io.Writer) {
|
||||||
admin.ProcessInput(input, w)
|
admin.ProcessInput(input, w)
|
||||||
|
|||||||
@ -21,13 +21,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestStatics(t *testing.T) {
|
func TestStatics(t *testing.T) {
|
||||||
StatisticsMap.AddStatistics("POST", "/api/user", "&admin.user", time.Duration(2000))
|
userApi := "/api/user"
|
||||||
StatisticsMap.AddStatistics("POST", "/api/user", "&admin.user", time.Duration(120000))
|
post := "POST"
|
||||||
StatisticsMap.AddStatistics("GET", "/api/user", "&admin.user", time.Duration(13000))
|
adminUser := "&admin.user"
|
||||||
StatisticsMap.AddStatistics("POST", "/api/admin", "&admin.user", time.Duration(14000))
|
StatisticsMap.AddStatistics(post, userApi, adminUser, time.Duration(2000))
|
||||||
StatisticsMap.AddStatistics("POST", "/api/user/astaxie", "&admin.user", time.Duration(12000))
|
StatisticsMap.AddStatistics(post, userApi, adminUser, time.Duration(120000))
|
||||||
StatisticsMap.AddStatistics("POST", "/api/user/xiemengjun", "&admin.user", time.Duration(13000))
|
StatisticsMap.AddStatistics("GET", userApi, adminUser, time.Duration(13000))
|
||||||
StatisticsMap.AddStatistics("DELETE", "/api/user", "&admin.user", time.Duration(1400))
|
StatisticsMap.AddStatistics(post, "/api/admin", adminUser, time.Duration(14000))
|
||||||
|
StatisticsMap.AddStatistics(post, "/api/user/astaxie", adminUser, time.Duration(12000))
|
||||||
|
StatisticsMap.AddStatistics(post, "/api/user/xiemengjun", adminUser, time.Duration(13000))
|
||||||
|
StatisticsMap.AddStatistics("DELETE", userApi, adminUser, time.Duration(1400))
|
||||||
t.Log(StatisticsMap.GetMap())
|
t.Log(StatisticsMap.GetMap())
|
||||||
|
|
||||||
data := StatisticsMap.GetMapData()
|
data := StatisticsMap.GetMapData()
|
||||||
|
|||||||
@ -80,7 +80,6 @@ type Task struct {
|
|||||||
|
|
||||||
// NewTask add new task with name, time and func
|
// NewTask add new task with name, time and func
|
||||||
func NewTask(tname string, spec string, f TaskFunc) *Task {
|
func NewTask(tname string, spec string, f TaskFunc) *Task {
|
||||||
|
|
||||||
task := task.NewTask(tname, spec, func(ctx context.Context) error {
|
task := task.NewTask(tname, spec, func(ctx context.Context) error {
|
||||||
return f()
|
return f()
|
||||||
})
|
})
|
||||||
@ -98,7 +97,6 @@ func (t *Task) GetSpec() string {
|
|||||||
|
|
||||||
// GetStatus get current task status
|
// GetStatus get current task status
|
||||||
func (t *Task) GetStatus() string {
|
func (t *Task) GetStatus() string {
|
||||||
|
|
||||||
t.initDelegate()
|
t.initDelegate()
|
||||||
|
|
||||||
return t.delegate.GetStatus(context.Background())
|
return t.delegate.GetStatus(context.Background())
|
||||||
@ -222,7 +220,6 @@ type MapSorter task.MapSorter
|
|||||||
|
|
||||||
// NewMapSorter create new tasker map
|
// NewMapSorter create new tasker map
|
||||||
func NewMapSorter(m map[string]Tasker) *MapSorter {
|
func NewMapSorter(m map[string]Tasker) *MapSorter {
|
||||||
|
|
||||||
newTaskerMap := make(map[string]task.Tasker, len(m))
|
newTaskerMap := make(map[string]task.Tasker, len(m))
|
||||||
|
|
||||||
for key, value := range m {
|
for key, value := range m {
|
||||||
@ -249,6 +246,7 @@ func (ms *MapSorter) Less(i, j int) bool {
|
|||||||
}
|
}
|
||||||
return ms.Vals[i].GetNext(context.Background()).Before(ms.Vals[j].GetNext(context.Background()))
|
return ms.Vals[i].GetNext(context.Background()).Before(ms.Vals[j].GetNext(context.Background()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *MapSorter) Swap(i, j int) {
|
func (ms *MapSorter) Swap(i, j int) {
|
||||||
ms.Vals[i], ms.Vals[j] = ms.Vals[j], ms.Vals[i]
|
ms.Vals[i], ms.Vals[j] = ms.Vals[j], ms.Vals[i]
|
||||||
ms.Keys[i], ms.Keys[j] = ms.Keys[j], ms.Keys[i]
|
ms.Keys[i], ms.Keys[j] = ms.Keys[j], ms.Keys[i]
|
||||||
@ -289,3 +287,7 @@ func (o *oldToNewAdapter) SetPrev(ctx context.Context, t time.Time) {
|
|||||||
func (o *oldToNewAdapter) GetPrev(ctx context.Context) time.Time {
|
func (o *oldToNewAdapter) GetPrev(ctx context.Context) time.Time {
|
||||||
return o.delegate.GetPrev()
|
return o.delegate.GetPrev()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *oldToNewAdapter) GetTimeout(ctx context.Context) time.Duration {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|||||||
@ -16,9 +16,8 @@ package adapter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/beego/beego/v2/adapter/context"
|
"github.com/beego/beego/v2/adapter/context"
|
||||||
beecontext "github.com/beego/beego/v2/server/web/context"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/server/web"
|
"github.com/beego/beego/v2/server/web"
|
||||||
|
beecontext "github.com/beego/beego/v2/server/web/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tree has three elements: FixRouter/wildcard/leaves
|
// Tree has three elements: FixRouter/wildcard/leaves
|
||||||
|
|||||||
@ -7,8 +7,8 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/beego/beego/v2"
|
"github.com/beego/beego/v2"
|
||||||
"github.com/beego/beego/v2/cache"
|
"github.com/beego/beego/v2/client/cache"
|
||||||
"github.com/beego/beego/v2/utils/captcha"
|
"github.com/beego/beego/v2/server/web/captcha"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cpt *captcha.Captcha
|
var cpt *captcha.Captcha
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
//
|
//
|
||||||
// import (
|
// import (
|
||||||
// "github.com/beego/beego/v2"
|
// "github.com/beego/beego/v2"
|
||||||
// "github.com/beego/beego/v2/cache"
|
// "github.com/beego/beego/v2/client/cache"
|
||||||
// "github.com/beego/beego/v2/utils/captcha"
|
// "github.com/beego/beego/v2/server/web/captcha"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// var cpt *captcha.Captcha
|
// var cpt *captcha.Captcha
|
||||||
@ -63,16 +63,13 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/server/web/captcha"
|
|
||||||
beecontext "github.com/beego/beego/v2/server/web/context"
|
|
||||||
|
|
||||||
"github.com/beego/beego/v2/adapter/cache"
|
"github.com/beego/beego/v2/adapter/cache"
|
||||||
"github.com/beego/beego/v2/adapter/context"
|
"github.com/beego/beego/v2/adapter/context"
|
||||||
|
"github.com/beego/beego/v2/server/web/captcha"
|
||||||
|
beecontext "github.com/beego/beego/v2/server/web/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var defaultChars = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||||
defaultChars = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// default captcha attributes
|
// default captcha attributes
|
||||||
|
|||||||
@ -28,8 +28,8 @@ func TestPrint(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPrintPoint(t *testing.T) {
|
func TestPrintPoint(t *testing.T) {
|
||||||
var v1 = new(mytype)
|
v1 := new(mytype)
|
||||||
var v2 = new(mytype)
|
v2 := new(mytype)
|
||||||
|
|
||||||
v1.prev = nil
|
v1.prev = nil
|
||||||
v1.next = v2
|
v1.next = v2
|
||||||
|
|||||||
@ -8,7 +8,7 @@ In your beego.Controller:
|
|||||||
|
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import "github.com/beego/beego/v2/utils/pagination"
|
import "github.com/beego/beego/v2/server/web/pagination"
|
||||||
|
|
||||||
type PostsController struct {
|
type PostsController struct {
|
||||||
beego.Controller
|
beego.Controller
|
||||||
|
|||||||
@ -16,7 +16,7 @@ package utils
|
|||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestRand_01(t *testing.T) {
|
func TestRand01(t *testing.T) {
|
||||||
bs0 := RandomCreateBytes(16)
|
bs0 := RandomCreateBytes(16)
|
||||||
bs1 := RandomCreateBytes(16)
|
bs1 := RandomCreateBytes(16)
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type reducetype func(interface{}) interface{}
|
type reducetype func(interface{}) interface{}
|
||||||
|
|
||||||
type filtertype func(interface{}) bool
|
type filtertype func(interface{}) bool
|
||||||
|
|
||||||
// InSlice checks given string in string slice or not.
|
// InSlice checks given string in string slice or not.
|
||||||
|
|||||||
@ -27,9 +27,7 @@ const (
|
|||||||
LabelTag = validation.LabelTag
|
LabelTag = validation.LabelTag
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var ErrInt64On32 = validation.ErrInt64On32
|
||||||
ErrInt64On32 = validation.ErrInt64On32
|
|
||||||
)
|
|
||||||
|
|
||||||
// CustomFunc is for custom validate function
|
// CustomFunc is for custom validate function
|
||||||
type CustomFunc func(v *Validation, obj interface{}, key string)
|
type CustomFunc func(v *Validation, obj interface{}, key string)
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
// Package validation for validations
|
// Package validation for validations
|
||||||
//
|
//
|
||||||
// import (
|
// import (
|
||||||
// "github.com/beego/beego/v2/validation"
|
// "github.com/beego/beego/v2/core/validation"
|
||||||
// "log"
|
// "log"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
|
|||||||
@ -18,131 +18,82 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRequired(t *testing.T) {
|
func TestRequired(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
if valid.Required(nil, "nil").Ok {
|
assert.False(t, valid.Required(nil, "nil").Ok)
|
||||||
t.Error("nil object should be false")
|
assert.True(t, valid.Required(true, "bool").Ok)
|
||||||
}
|
|
||||||
if !valid.Required(true, "bool").Ok {
|
assert.True(t, valid.Required(false, "bool").Ok)
|
||||||
t.Error("Bool value should always return true")
|
assert.False(t, valid.Required("", "string").Ok)
|
||||||
}
|
assert.False(t, valid.Required(" ", "string").Ok)
|
||||||
if !valid.Required(false, "bool").Ok {
|
assert.False(t, valid.Required("\n", "string").Ok)
|
||||||
t.Error("Bool value should always return true")
|
|
||||||
}
|
assert.True(t, valid.Required("astaxie", "string").Ok)
|
||||||
if valid.Required("", "string").Ok {
|
assert.False(t, valid.Required(0, "zero").Ok)
|
||||||
t.Error("\"'\" string should be false")
|
|
||||||
}
|
assert.True(t, valid.Required(1, "int").Ok)
|
||||||
if valid.Required(" ", "string").Ok {
|
|
||||||
t.Error("\" \" string should be false") // For #2361
|
assert.True(t, valid.Required(time.Now(), "time").Ok)
|
||||||
}
|
|
||||||
if valid.Required("\n", "string").Ok {
|
assert.False(t, valid.Required([]string{}, "emptySlice").Ok)
|
||||||
t.Error("new line string should be false") // For #2361
|
|
||||||
}
|
assert.True(t, valid.Required([]interface{}{"ok"}, "slice").Ok)
|
||||||
if !valid.Required("astaxie", "string").Ok {
|
|
||||||
t.Error("string should be true")
|
|
||||||
}
|
|
||||||
if valid.Required(0, "zero").Ok {
|
|
||||||
t.Error("Integer should not be equal 0")
|
|
||||||
}
|
|
||||||
if !valid.Required(1, "int").Ok {
|
|
||||||
t.Error("Integer except 0 should be true")
|
|
||||||
}
|
|
||||||
if !valid.Required(time.Now(), "time").Ok {
|
|
||||||
t.Error("time should be true")
|
|
||||||
}
|
|
||||||
if valid.Required([]string{}, "emptySlice").Ok {
|
|
||||||
t.Error("empty slice should be false")
|
|
||||||
}
|
|
||||||
if !valid.Required([]interface{}{"ok"}, "slice").Ok {
|
|
||||||
t.Error("slice should be true")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMin(t *testing.T) {
|
func TestMin(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
if valid.Min(-1, 0, "min0").Ok {
|
assert.False(t, valid.Min(-1, 0, "min0").Ok)
|
||||||
t.Error("-1 is less than the minimum value of 0 should be false")
|
assert.True(t, valid.Min(1, 0, "min0").Ok)
|
||||||
}
|
|
||||||
if !valid.Min(1, 0, "min0").Ok {
|
|
||||||
t.Error("1 is greater or equal than the minimum value of 0 should be true")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMax(t *testing.T) {
|
func TestMax(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
if valid.Max(1, 0, "max0").Ok {
|
assert.False(t, valid.Max(1, 0, "max0").Ok)
|
||||||
t.Error("1 is greater than the minimum value of 0 should be false")
|
assert.True(t, valid.Max(-1, 0, "max0").Ok)
|
||||||
}
|
|
||||||
if !valid.Max(-1, 0, "max0").Ok {
|
|
||||||
t.Error("-1 is less or equal than the maximum value of 0 should be true")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRange(t *testing.T) {
|
func TestRange(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
if valid.Range(-1, 0, 1, "range0_1").Ok {
|
assert.False(t, valid.Range(-1, 0, 1, "range0_1").Ok)
|
||||||
t.Error("-1 is between 0 and 1 should be false")
|
|
||||||
}
|
assert.True(t, valid.Range(1, 0, 1, "range0_1").Ok)
|
||||||
if !valid.Range(1, 0, 1, "range0_1").Ok {
|
|
||||||
t.Error("1 is between 0 and 1 should be true")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMinSize(t *testing.T) {
|
func TestMinSize(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
if valid.MinSize("", 1, "minSize1").Ok {
|
assert.False(t, valid.MinSize("", 1, "minSize1").Ok)
|
||||||
t.Error("the length of \"\" is less than the minimum value of 1 should be false")
|
|
||||||
}
|
assert.True(t, valid.MinSize("ok", 1, "minSize1").Ok)
|
||||||
if !valid.MinSize("ok", 1, "minSize1").Ok {
|
assert.False(t, valid.MinSize([]string{}, 1, "minSize1").Ok)
|
||||||
t.Error("the length of \"ok\" is greater or equal than the minimum value of 1 should be true")
|
assert.True(t, valid.MinSize([]interface{}{"ok"}, 1, "minSize1").Ok)
|
||||||
}
|
|
||||||
if valid.MinSize([]string{}, 1, "minSize1").Ok {
|
|
||||||
t.Error("the length of empty slice is less than the minimum value of 1 should be false")
|
|
||||||
}
|
|
||||||
if !valid.MinSize([]interface{}{"ok"}, 1, "minSize1").Ok {
|
|
||||||
t.Error("the length of [\"ok\"] is greater or equal than the minimum value of 1 should be true")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMaxSize(t *testing.T) {
|
func TestMaxSize(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
if valid.MaxSize("ok", 1, "maxSize1").Ok {
|
assert.False(t, valid.MaxSize("ok", 1, "maxSize1").Ok)
|
||||||
t.Error("the length of \"ok\" is greater than the maximum value of 1 should be false")
|
assert.True(t, valid.MaxSize("", 1, "maxSize1").Ok)
|
||||||
}
|
assert.False(t, valid.MaxSize([]interface{}{"ok", false}, 1, "maxSize1").Ok)
|
||||||
if !valid.MaxSize("", 1, "maxSize1").Ok {
|
assert.True(t, valid.MaxSize([]string{}, 1, "maxSize1").Ok)
|
||||||
t.Error("the length of \"\" is less or equal than the maximum value of 1 should be true")
|
|
||||||
}
|
|
||||||
if valid.MaxSize([]interface{}{"ok", false}, 1, "maxSize1").Ok {
|
|
||||||
t.Error("the length of [\"ok\", false] is greater than the maximum value of 1 should be false")
|
|
||||||
}
|
|
||||||
if !valid.MaxSize([]string{}, 1, "maxSize1").Ok {
|
|
||||||
t.Error("the length of empty slice is less or equal than the maximum value of 1 should be true")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLength(t *testing.T) {
|
func TestLength(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
if valid.Length("", 1, "length1").Ok {
|
assert.False(t, valid.Length("", 1, "length1").Ok)
|
||||||
t.Error("the length of \"\" must equal 1 should be false")
|
assert.True(t, valid.Length("1", 1, "length1").Ok)
|
||||||
}
|
|
||||||
if !valid.Length("1", 1, "length1").Ok {
|
assert.False(t, valid.Length([]string{}, 1, "length1").Ok)
|
||||||
t.Error("the length of \"1\" must equal 1 should be true")
|
assert.True(t, valid.Length([]interface{}{"ok"}, 1, "length1").Ok)
|
||||||
}
|
|
||||||
if valid.Length([]string{}, 1, "length1").Ok {
|
|
||||||
t.Error("the length of empty slice must equal 1 should be false")
|
|
||||||
}
|
|
||||||
if !valid.Length([]interface{}{"ok"}, 1, "length1").Ok {
|
|
||||||
t.Error("the length of [\"ok\"] must equal 1 should be true")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAlpha(t *testing.T) {
|
func TestAlpha(t *testing.T) {
|
||||||
@ -178,13 +129,16 @@ func TestAlphaNumeric(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const email = "suchuangji@gmail.com"
|
||||||
|
|
||||||
func TestMatch(t *testing.T) {
|
func TestMatch(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
if valid.Match("suchuangji@gmail", regexp.MustCompile(`^\w+@\w+\.\w+$`), "match").Ok {
|
if valid.Match("suchuangji@gmail", regexp.MustCompile(`^\w+@\w+\.\w+$`), "match").Ok {
|
||||||
t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be false")
|
t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be false")
|
||||||
}
|
}
|
||||||
if !valid.Match("suchuangji@gmail.com", regexp.MustCompile(`^\w+@\w+\.\w+$`), "match").Ok {
|
|
||||||
|
if !valid.Match(email, regexp.MustCompile(`^\w+@\w+\.\w+$`), "match").Ok {
|
||||||
t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be true")
|
t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,7 +171,7 @@ func TestEmail(t *testing.T) {
|
|||||||
if valid.Email("not@a email", "email").Ok {
|
if valid.Email("not@a email", "email").Ok {
|
||||||
t.Error("\"not@a email\" is a valid email address should be false")
|
t.Error("\"not@a email\" is a valid email address should be false")
|
||||||
}
|
}
|
||||||
if !valid.Email("suchuangji@gmail.com", "email").Ok {
|
if !valid.Email(email, "email").Ok {
|
||||||
t.Error("\"suchuangji@gmail.com\" is a valid email address should be true")
|
t.Error("\"suchuangji@gmail.com\" is a valid email address should be true")
|
||||||
}
|
}
|
||||||
if valid.Email("@suchuangji@gmail.com", "email").Ok {
|
if valid.Email("@suchuangji@gmail.com", "email").Ok {
|
||||||
@ -242,7 +196,7 @@ func TestIP(t *testing.T) {
|
|||||||
func TestBase64(t *testing.T) {
|
func TestBase64(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
if valid.Base64("suchuangji@gmail.com", "base64").Ok {
|
if valid.Base64(email, "base64").Ok {
|
||||||
t.Error("\"suchuangji@gmail.com\" are a valid base64 characters should be false")
|
t.Error("\"suchuangji@gmail.com\" are a valid base64 characters should be false")
|
||||||
}
|
}
|
||||||
if !valid.Base64("c3VjaHVhbmdqaUBnbWFpbC5jb20=", "base64").Ok {
|
if !valid.Base64("c3VjaHVhbmdqaUBnbWFpbC5jb20=", "base64").Ok {
|
||||||
@ -370,44 +324,25 @@ func TestValid(t *testing.T) {
|
|||||||
|
|
||||||
u := user{Name: "test@/test/;com", Age: 40}
|
u := user{Name: "test@/test/;com", Age: 40}
|
||||||
b, err := valid.Valid(u)
|
b, err := valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.True(t, b)
|
||||||
}
|
|
||||||
if !b {
|
|
||||||
t.Error("validation should be passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
uptr := &user{Name: "test", Age: 40}
|
uptr := &user{Name: "test", Age: 40}
|
||||||
valid.Clear()
|
valid.Clear()
|
||||||
b, err = valid.Valid(uptr)
|
b, err = valid.Valid(uptr)
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
assert.Nil(t, err)
|
||||||
}
|
assert.False(t, b)
|
||||||
if b {
|
assert.Equal(t, 1, len(valid.Errors))
|
||||||
t.Error("validation should not be passed")
|
assert.Equal(t, "Name.Match", valid.Errors[0].Key)
|
||||||
}
|
|
||||||
if len(valid.Errors) != 1 {
|
|
||||||
t.Fatalf("valid errors len should be 1 but got %d", len(valid.Errors))
|
|
||||||
}
|
|
||||||
if valid.Errors[0].Key != "Name.Match" {
|
|
||||||
t.Errorf("Message key should be `Name.Match` but got %s", valid.Errors[0].Key)
|
|
||||||
}
|
|
||||||
|
|
||||||
u = user{Name: "test@/test/;com", Age: 180}
|
u = user{Name: "test@/test/;com", Age: 180}
|
||||||
valid.Clear()
|
valid.Clear()
|
||||||
b, err = valid.Valid(u)
|
b, err = valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.False(t, b)
|
||||||
}
|
assert.Equal(t, 1, len(valid.Errors))
|
||||||
if b {
|
assert.Equal(t, "Age.Range.", valid.Errors[0].Key)
|
||||||
t.Error("validation should not be passed")
|
|
||||||
}
|
|
||||||
if len(valid.Errors) != 1 {
|
|
||||||
t.Fatalf("valid errors len should be 1 but got %d", len(valid.Errors))
|
|
||||||
}
|
|
||||||
if valid.Errors[0].Key != "Age.Range." {
|
|
||||||
t.Errorf("Message key should be `Age.Range` but got %s", valid.Errors[0].Key)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRecursiveValid(t *testing.T) {
|
func TestRecursiveValid(t *testing.T) {
|
||||||
@ -432,12 +367,8 @@ func TestRecursiveValid(t *testing.T) {
|
|||||||
|
|
||||||
u := Account{Password: "abc123_", U: User{}}
|
u := Account{Password: "abc123_", U: User{}}
|
||||||
b, err := valid.RecursiveValid(u)
|
b, err := valid.RecursiveValid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.False(t, b)
|
||||||
}
|
|
||||||
if b {
|
|
||||||
t.Error("validation should not be passed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSkipValid(t *testing.T) {
|
func TestSkipValid(t *testing.T) {
|
||||||
@ -474,21 +405,13 @@ func TestSkipValid(t *testing.T) {
|
|||||||
|
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
b, err := valid.Valid(u)
|
b, err := valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.False(t, b)
|
||||||
}
|
|
||||||
if b {
|
|
||||||
t.Fatal("validation should not be passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
valid = Validation{RequiredFirst: true}
|
valid = Validation{RequiredFirst: true}
|
||||||
b, err = valid.Valid(u)
|
b, err = valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.True(t, b)
|
||||||
}
|
|
||||||
if !b {
|
|
||||||
t.Fatal("validation should be passed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPointer(t *testing.T) {
|
func TestPointer(t *testing.T) {
|
||||||
@ -506,12 +429,8 @@ func TestPointer(t *testing.T) {
|
|||||||
|
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
b, err := valid.Valid(u)
|
b, err := valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.False(t, b)
|
||||||
}
|
|
||||||
if b {
|
|
||||||
t.Fatal("validation should not be passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
validEmail := "a@a.com"
|
validEmail := "a@a.com"
|
||||||
u = User{
|
u = User{
|
||||||
@ -521,12 +440,8 @@ func TestPointer(t *testing.T) {
|
|||||||
|
|
||||||
valid = Validation{RequiredFirst: true}
|
valid = Validation{RequiredFirst: true}
|
||||||
b, err = valid.Valid(u)
|
b, err = valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.True(t, b)
|
||||||
}
|
|
||||||
if !b {
|
|
||||||
t.Fatal("validation should be passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
u = User{
|
u = User{
|
||||||
ReqEmail: &validEmail,
|
ReqEmail: &validEmail,
|
||||||
@ -535,12 +450,8 @@ func TestPointer(t *testing.T) {
|
|||||||
|
|
||||||
valid = Validation{}
|
valid = Validation{}
|
||||||
b, err = valid.Valid(u)
|
b, err = valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.False(t, b)
|
||||||
}
|
|
||||||
if b {
|
|
||||||
t.Fatal("validation should not be passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidEmail := "a@a"
|
invalidEmail := "a@a"
|
||||||
u = User{
|
u = User{
|
||||||
@ -550,12 +461,8 @@ func TestPointer(t *testing.T) {
|
|||||||
|
|
||||||
valid = Validation{RequiredFirst: true}
|
valid = Validation{RequiredFirst: true}
|
||||||
b, err = valid.Valid(u)
|
b, err = valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.False(t, b)
|
||||||
}
|
|
||||||
if b {
|
|
||||||
t.Fatal("validation should not be passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
u = User{
|
u = User{
|
||||||
ReqEmail: &validEmail,
|
ReqEmail: &validEmail,
|
||||||
@ -564,12 +471,8 @@ func TestPointer(t *testing.T) {
|
|||||||
|
|
||||||
valid = Validation{}
|
valid = Validation{}
|
||||||
b, err = valid.Valid(u)
|
b, err = valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.False(t, b)
|
||||||
}
|
|
||||||
if b {
|
|
||||||
t.Fatal("validation should not be passed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCanSkipAlso(t *testing.T) {
|
func TestCanSkipAlso(t *testing.T) {
|
||||||
@ -589,21 +492,13 @@ func TestCanSkipAlso(t *testing.T) {
|
|||||||
|
|
||||||
valid := Validation{RequiredFirst: true}
|
valid := Validation{RequiredFirst: true}
|
||||||
b, err := valid.Valid(u)
|
b, err := valid.Valid(u)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Fatal(err)
|
assert.False(t, b)
|
||||||
}
|
|
||||||
if b {
|
|
||||||
t.Fatal("validation should not be passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
valid = Validation{RequiredFirst: true}
|
valid = Validation{RequiredFirst: true}
|
||||||
valid.CanSkipAlso("Range")
|
valid.CanSkipAlso("Range")
|
||||||
b, err = valid.Valid(u)
|
b, err = valid.Valid(u)
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !b {
|
|
||||||
t.Fatal("validation should be passed")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, b)
|
||||||
}
|
}
|
||||||
|
|||||||
4
client/cache/README.md
vendored
4
client/cache/README.md
vendored
@ -4,7 +4,7 @@ cache is a Go cache manager. It can use many cache adapters. The repo is inspire
|
|||||||
|
|
||||||
## How to install?
|
## How to install?
|
||||||
|
|
||||||
go get github.com/beego/beego/v2/cache
|
go get github.com/beego/beego/v2/client/cache
|
||||||
|
|
||||||
## What adapters are supported?
|
## What adapters are supported?
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ As of now this cache support memory, Memcache and Redis.
|
|||||||
First you must import it
|
First you must import it
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/beego/beego/v2/cache"
|
"github.com/beego/beego/v2/client/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
Then init a Cache (example with memory adapter)
|
Then init a Cache (example with memory adapter)
|
||||||
|
|||||||
11
client/cache/cache.go
vendored
11
client/cache/cache.go
vendored
@ -16,7 +16,7 @@
|
|||||||
// Usage:
|
// Usage:
|
||||||
//
|
//
|
||||||
// import(
|
// import(
|
||||||
// "github.com/beego/beego/v2/cache"
|
// "github.com/beego/beego/v2/client/cache"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// bm, err := cache.NewCache("memory", `{"interval":60}`)
|
// bm, err := cache.NewCache("memory", `{"interval":60}`)
|
||||||
@ -33,8 +33,9 @@ package cache
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/core/berror"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cache interface contains all behaviors for cache adapter.
|
// Cache interface contains all behaviors for cache adapter.
|
||||||
@ -55,12 +56,14 @@ type Cache interface {
|
|||||||
// Set a cached value with key and expire time.
|
// Set a cached value with key and expire time.
|
||||||
Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error
|
Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error
|
||||||
// Delete cached value by key.
|
// Delete cached value by key.
|
||||||
|
// Should not return error if key not found
|
||||||
Delete(ctx context.Context, key string) error
|
Delete(ctx context.Context, key string) error
|
||||||
// Increment a cached int value by key, as a counter.
|
// Increment a cached int value by key, as a counter.
|
||||||
Incr(ctx context.Context, key string) error
|
Incr(ctx context.Context, key string) error
|
||||||
// Decrement a cached int value by key, as a counter.
|
// Decrement a cached int value by key, as a counter.
|
||||||
Decr(ctx context.Context, key string) error
|
Decr(ctx context.Context, key string) error
|
||||||
// Check if a cached value exists or not.
|
// Check if a cached value exists or not.
|
||||||
|
// if key is expired, return (false, nil)
|
||||||
IsExist(ctx context.Context, key string) (bool, error)
|
IsExist(ctx context.Context, key string) (bool, error)
|
||||||
// Clear all cache.
|
// Clear all cache.
|
||||||
ClearAll(ctx context.Context) error
|
ClearAll(ctx context.Context) error
|
||||||
@ -78,7 +81,7 @@ var adapters = make(map[string]Instance)
|
|||||||
// it panics.
|
// it panics.
|
||||||
func Register(name string, adapter Instance) {
|
func Register(name string, adapter Instance) {
|
||||||
if adapter == nil {
|
if adapter == nil {
|
||||||
panic("cache: Register adapter is nil")
|
panic(berror.Error(NilCacheAdapter, "cache: Register adapter is nil").Error())
|
||||||
}
|
}
|
||||||
if _, ok := adapters[name]; ok {
|
if _, ok := adapters[name]; ok {
|
||||||
panic("cache: Register called twice for adapter " + name)
|
panic("cache: Register called twice for adapter " + name)
|
||||||
@ -92,7 +95,7 @@ func Register(name string, adapter Instance) {
|
|||||||
func NewCache(adapterName, config string) (adapter Cache, err error) {
|
func NewCache(adapterName, config string) (adapter Cache, err error) {
|
||||||
instanceFunc, ok := adapters[adapterName]
|
instanceFunc, ok := adapters[adapterName]
|
||||||
if !ok {
|
if !ok {
|
||||||
err = fmt.Errorf("cache: unknown adapter name %q (forgot to import?)", adapterName)
|
err = berror.Errorf(UnknownAdapter, "cache: unknown adapter name %s (forgot to import?)", adapterName)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
adapter = instanceFunc()
|
adapter = instanceFunc()
|
||||||
|
|||||||
228
client/cache/cache_test.go
vendored
228
client/cache/cache_test.go
vendored
@ -16,17 +16,19 @@ package cache
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCacheIncr(t *testing.T) {
|
func TestCacheIncr(t *testing.T) {
|
||||||
bm, err := NewCache("memory", `{"interval":20}`)
|
bm, err := NewCache("memory", `{"interval":20}`)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Error("init err")
|
|
||||||
}
|
|
||||||
// timeoutDuration := 10 * time.Second
|
// timeoutDuration := 10 * time.Second
|
||||||
|
|
||||||
bm.Put(context.Background(), "edwardhey", 0, time.Second*20)
|
bm.Put(context.Background(), "edwardhey", 0, time.Second*20)
|
||||||
@ -46,11 +48,9 @@ func TestCacheIncr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCache(t *testing.T) {
|
func TestCache(t *testing.T) {
|
||||||
bm, err := NewCache("memory", `{"interval":20}`)
|
bm, err := NewCache("memory", `{"interval":1}`)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Error("init err")
|
timeoutDuration := 5 * time.Second
|
||||||
}
|
|
||||||
timeoutDuration := 10 * time.Second
|
|
||||||
if err = bm.Put(context.Background(), "astaxie", 1, timeoutDuration); err != nil {
|
if err = bm.Put(context.Background(), "astaxie", 1, timeoutDuration); err != nil {
|
||||||
t.Error("set Error", err)
|
t.Error("set Error", err)
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ func TestCache(t *testing.T) {
|
|||||||
t.Error("get err")
|
t.Error("get err")
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(30 * time.Second)
|
time.Sleep(7 * time.Second)
|
||||||
|
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
||||||
t.Error("check err")
|
t.Error("check err")
|
||||||
@ -73,130 +73,95 @@ func TestCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// test different integer type for incr & decr
|
// test different integer type for incr & decr
|
||||||
testMultiIncrDecr(t, bm, timeoutDuration)
|
testMultiTypeIncrDecr(t, bm, timeoutDuration)
|
||||||
|
|
||||||
|
// test overflow of incr&decr
|
||||||
|
testIncrOverFlow(t, bm, timeoutDuration)
|
||||||
|
testDecrOverFlow(t, bm, timeoutDuration)
|
||||||
|
|
||||||
bm.Delete(context.Background(), "astaxie")
|
bm.Delete(context.Background(), "astaxie")
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
res, _ := bm.IsExist(context.Background(), "astaxie")
|
||||||
t.Error("delete err")
|
assert.False(t, res)
|
||||||
}
|
|
||||||
|
|
||||||
// test GetMulti
|
assert.Nil(t, bm.Put(context.Background(), "astaxie", "author", timeoutDuration))
|
||||||
if err = bm.Put(context.Background(), "astaxie", "author", timeoutDuration); err != nil {
|
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); !res {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
if v, _ := bm.Get(context.Background(), "astaxie"); v.(string) != "author" {
|
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Put(context.Background(), "astaxie1", "author1", timeoutDuration); err != nil {
|
res, _ = bm.IsExist(context.Background(), "astaxie")
|
||||||
t.Error("set Error", err)
|
assert.True(t, res)
|
||||||
}
|
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie1"); !res {
|
v, _ := bm.Get(context.Background(), "astaxie")
|
||||||
t.Error("check err")
|
assert.Equal(t, "author", v)
|
||||||
}
|
|
||||||
|
assert.Nil(t, bm.Put(context.Background(), "astaxie1", "author1", timeoutDuration))
|
||||||
|
|
||||||
|
res, _ = bm.IsExist(context.Background(), "astaxie1")
|
||||||
|
assert.True(t, res)
|
||||||
|
|
||||||
vv, _ := bm.GetMulti(context.Background(), []string{"astaxie", "astaxie1"})
|
vv, _ := bm.GetMulti(context.Background(), []string{"astaxie", "astaxie1"})
|
||||||
if len(vv) != 2 {
|
assert.Equal(t, 2, len(vv))
|
||||||
t.Error("GetMulti ERROR")
|
assert.Equal(t, "author", vv[0])
|
||||||
}
|
assert.Equal(t, "author1", vv[1])
|
||||||
if vv[0].(string) != "author" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if vv[1].(string) != "author1" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
|
|
||||||
vv, err = bm.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"})
|
vv, err = bm.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"})
|
||||||
if len(vv) != 2 {
|
assert.Equal(t, 2, len(vv))
|
||||||
t.Error("GetMulti ERROR")
|
assert.Nil(t, vv[0])
|
||||||
}
|
assert.Equal(t, "author1", vv[1])
|
||||||
if vv[0] != nil {
|
|
||||||
t.Error("GetMulti ERROR")
|
assert.NotNil(t, err)
|
||||||
}
|
assert.True(t, strings.Contains(err.Error(), "key isn't exist"))
|
||||||
if vv[1].(string) != "author1" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if err != nil && err.Error() != "key [astaxie0] error: the key isn't exist" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileCache(t *testing.T) {
|
func TestFileCache(t *testing.T) {
|
||||||
bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}`)
|
bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}`)
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Error("init err")
|
|
||||||
}
|
|
||||||
timeoutDuration := 10 * time.Second
|
timeoutDuration := 10 * time.Second
|
||||||
if err = bm.Put(context.Background(), "astaxie", 1, timeoutDuration); err != nil {
|
assert.Nil(t, bm.Put(context.Background(), "astaxie", 1, timeoutDuration))
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); !res {
|
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 1 {
|
res, _ := bm.IsExist(context.Background(), "astaxie")
|
||||||
t.Error("get err")
|
assert.True(t, res)
|
||||||
}
|
v, _ := bm.Get(context.Background(), "astaxie")
|
||||||
|
assert.Equal(t, 1, v)
|
||||||
|
|
||||||
// test different integer type for incr & decr
|
// test different integer type for incr & decr
|
||||||
testMultiIncrDecr(t, bm, timeoutDuration)
|
testMultiTypeIncrDecr(t, bm, timeoutDuration)
|
||||||
|
|
||||||
|
// test overflow of incr&decr
|
||||||
|
testIncrOverFlow(t, bm, timeoutDuration)
|
||||||
|
testDecrOverFlow(t, bm, timeoutDuration)
|
||||||
|
|
||||||
bm.Delete(context.Background(), "astaxie")
|
bm.Delete(context.Background(), "astaxie")
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
res, _ = bm.IsExist(context.Background(), "astaxie")
|
||||||
t.Error("delete err")
|
assert.False(t, res)
|
||||||
}
|
|
||||||
|
|
||||||
// test string
|
// test string
|
||||||
if err = bm.Put(context.Background(), "astaxie", "author", timeoutDuration); err != nil {
|
assert.Nil(t, bm.Put(context.Background(), "astaxie", "author", timeoutDuration))
|
||||||
t.Error("set Error", err)
|
res, _ = bm.IsExist(context.Background(), "astaxie")
|
||||||
}
|
assert.True(t, res)
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); !res {
|
|
||||||
t.Error("check err")
|
v, _ = bm.Get(context.Background(), "astaxie")
|
||||||
}
|
assert.Equal(t, "author", v)
|
||||||
if v, _ := bm.Get(context.Background(), "astaxie"); v.(string) != "author" {
|
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test GetMulti
|
// test GetMulti
|
||||||
if err = bm.Put(context.Background(), "astaxie1", "author1", timeoutDuration); err != nil {
|
assert.Nil(t, bm.Put(context.Background(), "astaxie1", "author1", timeoutDuration))
|
||||||
t.Error("set Error", err)
|
|
||||||
}
|
res, _ = bm.IsExist(context.Background(), "astaxie1")
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie1"); !res {
|
assert.True(t, res)
|
||||||
t.Error("check err")
|
|
||||||
}
|
|
||||||
|
|
||||||
vv, _ := bm.GetMulti(context.Background(), []string{"astaxie", "astaxie1"})
|
vv, _ := bm.GetMulti(context.Background(), []string{"astaxie", "astaxie1"})
|
||||||
if len(vv) != 2 {
|
assert.Equal(t, 2, len(vv))
|
||||||
t.Error("GetMulti ERROR")
|
assert.Equal(t, "author", vv[0])
|
||||||
}
|
assert.Equal(t, "author1", vv[1])
|
||||||
if vv[0].(string) != "author" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if vv[1].(string) != "author1" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
|
|
||||||
vv, err = bm.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"})
|
vv, err = bm.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"})
|
||||||
if len(vv) != 2 {
|
assert.Equal(t, 2, len(vv))
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if vv[0] != nil {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if vv[1].(string) != "author1" {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
t.Error("GetMulti ERROR")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Nil(t, vv[0])
|
||||||
|
|
||||||
|
assert.Equal(t, "author1", vv[1])
|
||||||
|
assert.NotNil(t, err)
|
||||||
os.RemoveAll("cache")
|
os.RemoveAll("cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMultiIncrDecr(t *testing.T, c Cache, timeout time.Duration) {
|
func testMultiTypeIncrDecr(t *testing.T, c Cache, timeout time.Duration) {
|
||||||
testIncrDecr(t, c, 1, 2, timeout)
|
testIncrDecr(t, c, 1, 2, timeout)
|
||||||
testIncrDecr(t, c, int32(1), int32(2), timeout)
|
testIncrDecr(t, c, int32(1), int32(2), timeout)
|
||||||
testIncrDecr(t, c, int64(1), int64(2), timeout)
|
testIncrDecr(t, c, int64(1), int64(2), timeout)
|
||||||
@ -206,30 +171,51 @@ func testMultiIncrDecr(t *testing.T, c Cache, timeout time.Duration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testIncrDecr(t *testing.T, c Cache, beforeIncr interface{}, afterIncr interface{}, timeout time.Duration) {
|
func testIncrDecr(t *testing.T, c Cache, beforeIncr interface{}, afterIncr interface{}, timeout time.Duration) {
|
||||||
var err error
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
key := "incDecKey"
|
key := "incDecKey"
|
||||||
if err = c.Put(ctx, key, beforeIncr, timeout); err != nil {
|
|
||||||
t.Error("Get Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = c.Incr(ctx, key); err != nil {
|
assert.Nil(t, c.Put(ctx, key, beforeIncr, timeout))
|
||||||
t.Error("Incr Error", err)
|
assert.Nil(t, c.Incr(ctx, key))
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := c.Get(ctx, key); v != afterIncr {
|
v, _ := c.Get(ctx, key)
|
||||||
t.Error("Get Error")
|
assert.Equal(t, afterIncr, v)
|
||||||
}
|
|
||||||
|
|
||||||
if err = c.Decr(ctx, key); err != nil {
|
assert.Nil(t, c.Decr(ctx, key))
|
||||||
t.Error("Decr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := c.Get(ctx, key); v != beforeIncr {
|
v, _ = c.Get(ctx, key)
|
||||||
t.Error("Get Error")
|
assert.Equal(t, v, beforeIncr)
|
||||||
}
|
assert.Nil(t, c.Delete(ctx, key))
|
||||||
|
}
|
||||||
|
|
||||||
if err := c.Delete(ctx, key); err != nil {
|
func testIncrOverFlow(t *testing.T, c Cache, timeout time.Duration) {
|
||||||
t.Error("Delete Error")
|
ctx := context.Background()
|
||||||
|
key := "incKey"
|
||||||
|
|
||||||
|
assert.Nil(t, c.Put(ctx, key, int64(math.MaxInt64), timeout))
|
||||||
|
// int64
|
||||||
|
defer func() {
|
||||||
|
assert.Nil(t, c.Delete(ctx, key))
|
||||||
|
}()
|
||||||
|
assert.NotNil(t, c.Incr(ctx, key))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDecrOverFlow(t *testing.T, c Cache, timeout time.Duration) {
|
||||||
|
var err error
|
||||||
|
ctx := context.Background()
|
||||||
|
key := "decKey"
|
||||||
|
|
||||||
|
// int64
|
||||||
|
if err = c.Put(ctx, key, int64(math.MinInt64), timeout); err != nil {
|
||||||
|
t.Error("Put Error: ", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err = c.Delete(ctx, key); err != nil {
|
||||||
|
t.Errorf("Delete error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err = c.Decr(ctx, key); err == nil {
|
||||||
|
t.Error("Decr error")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
95
client/cache/calc_utils.go
vendored
Normal file
95
client/cache/calc_utils.go
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/core/berror"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrIncrementOverflow = berror.Error(IncrementOverflow, "this incr invocation will overflow.")
|
||||||
|
ErrDecrementOverflow = berror.Error(DecrementOverflow, "this decr invocation will overflow.")
|
||||||
|
ErrNotIntegerType = berror.Error(NotIntegerType, "item val is not (u)int (u)int32 (u)int64")
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MinUint32 uint32 = 0
|
||||||
|
MinUint64 uint64 = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
func incr(originVal interface{}) (interface{}, error) {
|
||||||
|
switch val := originVal.(type) {
|
||||||
|
case int:
|
||||||
|
tmp := val + 1
|
||||||
|
if val > 0 && tmp < 0 {
|
||||||
|
return nil, ErrIncrementOverflow
|
||||||
|
}
|
||||||
|
return tmp, nil
|
||||||
|
case int32:
|
||||||
|
if val == math.MaxInt32 {
|
||||||
|
return nil, ErrIncrementOverflow
|
||||||
|
}
|
||||||
|
return val + 1, nil
|
||||||
|
case int64:
|
||||||
|
if val == math.MaxInt64 {
|
||||||
|
return nil, ErrIncrementOverflow
|
||||||
|
}
|
||||||
|
return val + 1, nil
|
||||||
|
case uint:
|
||||||
|
tmp := val + 1
|
||||||
|
if tmp < val {
|
||||||
|
return nil, ErrIncrementOverflow
|
||||||
|
}
|
||||||
|
return tmp, nil
|
||||||
|
case uint32:
|
||||||
|
if val == math.MaxUint32 {
|
||||||
|
return nil, ErrIncrementOverflow
|
||||||
|
}
|
||||||
|
return val + 1, nil
|
||||||
|
case uint64:
|
||||||
|
if val == math.MaxUint64 {
|
||||||
|
return nil, ErrIncrementOverflow
|
||||||
|
}
|
||||||
|
return val + 1, nil
|
||||||
|
default:
|
||||||
|
return nil, ErrNotIntegerType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func decr(originVal interface{}) (interface{}, error) {
|
||||||
|
switch val := originVal.(type) {
|
||||||
|
case int:
|
||||||
|
tmp := val - 1
|
||||||
|
if val < 0 && tmp > 0 {
|
||||||
|
return nil, ErrDecrementOverflow
|
||||||
|
}
|
||||||
|
return tmp, nil
|
||||||
|
case int32:
|
||||||
|
if val == math.MinInt32 {
|
||||||
|
return nil, ErrDecrementOverflow
|
||||||
|
}
|
||||||
|
return val - 1, nil
|
||||||
|
case int64:
|
||||||
|
if val == math.MinInt64 {
|
||||||
|
return nil, ErrDecrementOverflow
|
||||||
|
}
|
||||||
|
return val - 1, nil
|
||||||
|
case uint:
|
||||||
|
if val == 0 {
|
||||||
|
return nil, ErrDecrementOverflow
|
||||||
|
}
|
||||||
|
return val - 1, nil
|
||||||
|
case uint32:
|
||||||
|
if val == MinUint32 {
|
||||||
|
return nil, ErrDecrementOverflow
|
||||||
|
}
|
||||||
|
return val - 1, nil
|
||||||
|
case uint64:
|
||||||
|
if val == MinUint64 {
|
||||||
|
return nil, ErrDecrementOverflow
|
||||||
|
}
|
||||||
|
return val - 1, nil
|
||||||
|
default:
|
||||||
|
return nil, ErrNotIntegerType
|
||||||
|
}
|
||||||
|
}
|
||||||
140
client/cache/calc_utils_test.go
vendored
Normal file
140
client/cache/calc_utils_test.go
vendored
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIncr(t *testing.T) {
|
||||||
|
// int
|
||||||
|
var originVal interface{} = int(1)
|
||||||
|
var updateVal interface{} = int(2)
|
||||||
|
val, err := incr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = incr(int(1<<(strconv.IntSize-1) - 1))
|
||||||
|
assert.Equal(t, ErrIncrementOverflow, err)
|
||||||
|
|
||||||
|
// int32
|
||||||
|
originVal = int32(1)
|
||||||
|
updateVal = int32(2)
|
||||||
|
val, err = incr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = incr(int32(math.MaxInt32))
|
||||||
|
assert.Equal(t, ErrIncrementOverflow, err)
|
||||||
|
|
||||||
|
// int64
|
||||||
|
originVal = int64(1)
|
||||||
|
updateVal = int64(2)
|
||||||
|
val, err = incr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = incr(int64(math.MaxInt64))
|
||||||
|
assert.Equal(t, ErrIncrementOverflow, err)
|
||||||
|
|
||||||
|
// uint
|
||||||
|
originVal = uint(1)
|
||||||
|
updateVal = uint(2)
|
||||||
|
val, err = incr(originVal)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = incr(uint(1<<(strconv.IntSize) - 1))
|
||||||
|
assert.Equal(t, ErrIncrementOverflow, err)
|
||||||
|
|
||||||
|
// uint32
|
||||||
|
originVal = uint32(1)
|
||||||
|
updateVal = uint32(2)
|
||||||
|
val, err = incr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = incr(uint32(math.MaxUint32))
|
||||||
|
assert.Equal(t, ErrIncrementOverflow, err)
|
||||||
|
|
||||||
|
// uint64
|
||||||
|
originVal = uint64(1)
|
||||||
|
updateVal = uint64(2)
|
||||||
|
val, err = incr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = incr(uint64(math.MaxUint64))
|
||||||
|
assert.Equal(t, ErrIncrementOverflow, err)
|
||||||
|
// other type
|
||||||
|
_, err = incr("string")
|
||||||
|
assert.Equal(t, ErrNotIntegerType, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecr(t *testing.T) {
|
||||||
|
// int
|
||||||
|
var originVal interface{} = int(2)
|
||||||
|
var updateVal interface{} = int(1)
|
||||||
|
val, err := decr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = decr(int(-1 << (strconv.IntSize - 1)))
|
||||||
|
assert.Equal(t, ErrDecrementOverflow, err)
|
||||||
|
// int32
|
||||||
|
originVal = int32(2)
|
||||||
|
updateVal = int32(1)
|
||||||
|
val, err = decr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = decr(int32(math.MinInt32))
|
||||||
|
assert.Equal(t, ErrDecrementOverflow, err)
|
||||||
|
|
||||||
|
// int64
|
||||||
|
originVal = int64(2)
|
||||||
|
updateVal = int64(1)
|
||||||
|
val, err = decr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = decr(int64(math.MinInt64))
|
||||||
|
assert.Equal(t, ErrDecrementOverflow, err)
|
||||||
|
|
||||||
|
// uint
|
||||||
|
originVal = uint(2)
|
||||||
|
updateVal = uint(1)
|
||||||
|
val, err = decr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = decr(uint(0))
|
||||||
|
assert.Equal(t, ErrDecrementOverflow, err)
|
||||||
|
|
||||||
|
// uint32
|
||||||
|
originVal = uint32(2)
|
||||||
|
updateVal = uint32(1)
|
||||||
|
val, err = decr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = decr(uint32(0))
|
||||||
|
assert.Equal(t, ErrDecrementOverflow, err)
|
||||||
|
|
||||||
|
// uint64
|
||||||
|
originVal = uint64(2)
|
||||||
|
updateVal = uint64(1)
|
||||||
|
val, err = decr(originVal)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, val, updateVal)
|
||||||
|
|
||||||
|
_, err = decr(uint64(0))
|
||||||
|
assert.Equal(t, ErrDecrementOverflow, err)
|
||||||
|
|
||||||
|
// other type
|
||||||
|
_, err = decr("string")
|
||||||
|
assert.Equal(t, ErrNotIntegerType, err)
|
||||||
|
}
|
||||||
142
client/cache/conv_test.go
vendored
142
client/cache/conv_test.go
vendored
@ -16,128 +16,74 @@ package cache
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetString(t *testing.T) {
|
func TestGetString(t *testing.T) {
|
||||||
var t1 = "test1"
|
t1 := "test1"
|
||||||
if "test1" != GetString(t1) {
|
|
||||||
t.Error("get string from string error")
|
|
||||||
}
|
|
||||||
var t2 = []byte("test2")
|
|
||||||
if "test2" != GetString(t2) {
|
|
||||||
t.Error("get string from byte array error")
|
|
||||||
}
|
|
||||||
var t3 = 1
|
|
||||||
if "1" != GetString(t3) {
|
|
||||||
t.Error("get string from int error")
|
|
||||||
}
|
|
||||||
var t4 int64 = 1
|
|
||||||
if "1" != GetString(t4) {
|
|
||||||
t.Error("get string from int64 error")
|
|
||||||
}
|
|
||||||
var t5 = 1.1
|
|
||||||
if "1.1" != GetString(t5) {
|
|
||||||
t.Error("get string from float64 error")
|
|
||||||
}
|
|
||||||
|
|
||||||
if "" != GetString(nil) {
|
assert.Equal(t, "test1", GetString(t1))
|
||||||
t.Error("get string from nil error")
|
t2 := []byte("test2")
|
||||||
}
|
assert.Equal(t, "test2", GetString(t2))
|
||||||
|
t3 := 1
|
||||||
|
assert.Equal(t, "1", GetString(t3))
|
||||||
|
var t4 int64 = 1
|
||||||
|
assert.Equal(t, "1", GetString(t4))
|
||||||
|
t5 := 1.1
|
||||||
|
assert.Equal(t, "1.1", GetString(t5))
|
||||||
|
assert.Equal(t, "", GetString(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetInt(t *testing.T) {
|
func TestGetInt(t *testing.T) {
|
||||||
var t1 = 1
|
t1 := 1
|
||||||
if 1 != GetInt(t1) {
|
assert.Equal(t, 1, GetInt(t1))
|
||||||
t.Error("get int from int error")
|
|
||||||
}
|
|
||||||
var t2 int32 = 32
|
var t2 int32 = 32
|
||||||
if 32 != GetInt(t2) {
|
assert.Equal(t, 32, GetInt(t2))
|
||||||
t.Error("get int from int32 error")
|
|
||||||
}
|
|
||||||
var t3 int64 = 64
|
var t3 int64 = 64
|
||||||
if 64 != GetInt(t3) {
|
assert.Equal(t, 64, GetInt(t3))
|
||||||
t.Error("get int from int64 error")
|
t4 := "128"
|
||||||
}
|
|
||||||
var t4 = "128"
|
assert.Equal(t, 128, GetInt(t4))
|
||||||
if 128 != GetInt(t4) {
|
assert.Equal(t, 0, GetInt(nil))
|
||||||
t.Error("get int from num string error")
|
|
||||||
}
|
|
||||||
if 0 != GetInt(nil) {
|
|
||||||
t.Error("get int from nil error")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetInt64(t *testing.T) {
|
func TestGetInt64(t *testing.T) {
|
||||||
var i int64 = 1
|
var i int64 = 1
|
||||||
var t1 = 1
|
t1 := 1
|
||||||
if i != GetInt64(t1) {
|
assert.Equal(t, i, GetInt64(t1))
|
||||||
t.Error("get int64 from int error")
|
|
||||||
}
|
|
||||||
var t2 int32 = 1
|
var t2 int32 = 1
|
||||||
if i != GetInt64(t2) {
|
|
||||||
t.Error("get int64 from int32 error")
|
assert.Equal(t, i, GetInt64(t2))
|
||||||
}
|
|
||||||
var t3 int64 = 1
|
var t3 int64 = 1
|
||||||
if i != GetInt64(t3) {
|
assert.Equal(t, i, GetInt64(t3))
|
||||||
t.Error("get int64 from int64 error")
|
t4 := "1"
|
||||||
}
|
assert.Equal(t, i, GetInt64(t4))
|
||||||
var t4 = "1"
|
assert.Equal(t, int64(0), GetInt64(nil))
|
||||||
if i != GetInt64(t4) {
|
|
||||||
t.Error("get int64 from num string error")
|
|
||||||
}
|
|
||||||
if 0 != GetInt64(nil) {
|
|
||||||
t.Error("get int64 from nil")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetFloat64(t *testing.T) {
|
func TestGetFloat64(t *testing.T) {
|
||||||
var f = 1.11
|
f := 1.11
|
||||||
var t1 float32 = 1.11
|
var t1 float32 = 1.11
|
||||||
if f != GetFloat64(t1) {
|
assert.Equal(t, f, GetFloat64(t1))
|
||||||
t.Error("get float64 from float32 error")
|
t2 := 1.11
|
||||||
}
|
assert.Equal(t, f, GetFloat64(t2))
|
||||||
var t2 = 1.11
|
t3 := "1.11"
|
||||||
if f != GetFloat64(t2) {
|
assert.Equal(t, f, GetFloat64(t3))
|
||||||
t.Error("get float64 from float64 error")
|
|
||||||
}
|
|
||||||
var t3 = "1.11"
|
|
||||||
if f != GetFloat64(t3) {
|
|
||||||
t.Error("get float64 from string error")
|
|
||||||
}
|
|
||||||
|
|
||||||
var f2 float64 = 1
|
var f2 float64 = 1
|
||||||
var t4 = 1
|
t4 := 1
|
||||||
if f2 != GetFloat64(t4) {
|
assert.Equal(t, f2, GetFloat64(t4))
|
||||||
t.Error("get float64 from int error")
|
|
||||||
}
|
|
||||||
|
|
||||||
if 0 != GetFloat64(nil) {
|
assert.Equal(t, float64(0), GetFloat64(nil))
|
||||||
t.Error("get float64 from nil error")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetBool(t *testing.T) {
|
func TestGetBool(t *testing.T) {
|
||||||
var t1 = true
|
t1 := true
|
||||||
if !GetBool(t1) {
|
assert.True(t, GetBool(t1))
|
||||||
t.Error("get bool from bool error")
|
t2 := "true"
|
||||||
}
|
assert.True(t, GetBool(t2))
|
||||||
var t2 = "true"
|
|
||||||
if !GetBool(t2) {
|
|
||||||
t.Error("get bool from string error")
|
|
||||||
}
|
|
||||||
if GetBool(nil) {
|
|
||||||
t.Error("get bool from nil error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func byteArrayEquals(a []byte, b []byte) bool {
|
assert.False(t, GetBool(nil))
|
||||||
if len(a) != len(b) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, v := range a {
|
|
||||||
if v != b[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|||||||
176
client/cache/error_code.go
vendored
Normal file
176
client/cache/error_code.go
vendored
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
// Copyright 2021 beego
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/beego/beego/v2/core/berror"
|
||||||
|
)
|
||||||
|
|
||||||
|
var NilCacheAdapter = berror.DefineCode(4002001, moduleName, "NilCacheAdapter", `
|
||||||
|
It means that you register cache adapter by pass nil.
|
||||||
|
A cache adapter is an instance of Cache interface.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var DuplicateAdapter = berror.DefineCode(4002002, moduleName, "DuplicateAdapter", `
|
||||||
|
You register two adapter with same name. In beego cache module, one name one adapter.
|
||||||
|
Once you got this error, please check the error stack, search adapter
|
||||||
|
`)
|
||||||
|
|
||||||
|
var UnknownAdapter = berror.DefineCode(4002003, moduleName, "UnknownAdapter", `
|
||||||
|
Unknown adapter, do you forget to register the adapter?
|
||||||
|
You must register adapter before use it. For example, if you want to use redis implementation,
|
||||||
|
you must import the cache/redis package.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var IncrementOverflow = berror.DefineCode(4002004, moduleName, "IncrementOverflow", `
|
||||||
|
The increment operation will overflow.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var DecrementOverflow = berror.DefineCode(4002005, moduleName, "DecrementOverflow", `
|
||||||
|
The decrement operation will overflow.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var NotIntegerType = berror.DefineCode(4002006, moduleName, "NotIntegerType", `
|
||||||
|
The type of value is not (u)int (u)int32 (u)int64.
|
||||||
|
When you want to call Incr or Decr function of Cache API, you must confirm that the value's type is one of (u)int (u)int32 (u)int64.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidFileCacheDirectoryLevelCfg = berror.DefineCode(4002007, moduleName, "InvalidFileCacheDirectoryLevelCfg", `
|
||||||
|
You pass invalid DirectoryLevel parameter when you try to StartAndGC file cache instance.
|
||||||
|
This parameter must be a integer, and please check your input.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidFileCacheEmbedExpiryCfg = berror.DefineCode(4002008, moduleName, "InvalidFileCacheEmbedExpiryCfg", `
|
||||||
|
You pass invalid EmbedExpiry parameter when you try to StartAndGC file cache instance.
|
||||||
|
This parameter must be a integer, and please check your input.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var CreateFileCacheDirFailed = berror.DefineCode(4002009, moduleName, "CreateFileCacheDirFailed", `
|
||||||
|
Beego failed to create file cache directory. There are two cases:
|
||||||
|
1. You pass invalid CachePath parameter. Please check your input.
|
||||||
|
2. Beego doesn't have the permission to create this directory. Please check your file mode.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidFileCachePath = berror.DefineCode(4002010, moduleName, "InvalidFilePath", `
|
||||||
|
The file path of FileCache is invalid. Please correct the config.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var ReadFileCacheContentFailed = berror.DefineCode(4002011, moduleName, "ReadFileCacheContentFailed", `
|
||||||
|
Usually you won't got this error. It means that Beego cannot read the data from the file.
|
||||||
|
You need to check whether the file exist. Sometimes it may be deleted by other processes.
|
||||||
|
If the file exists, please check the permission that Beego is able to read data from the file.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidGobEncodedData = berror.DefineCode(4002012, moduleName, "InvalidEncodedData", `
|
||||||
|
The data is invalid. When you try to decode the invalid data, you got this error.
|
||||||
|
Please confirm that the data is encoded by GOB correctly.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var GobEncodeDataFailed = berror.DefineCode(4002013, moduleName, "GobEncodeDataFailed", `
|
||||||
|
Beego could not encode the data to GOB byte array. In general, the data type is invalid.
|
||||||
|
For example, GOB doesn't support function type.
|
||||||
|
Basic types, string, structure, structure pointer are supported.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var KeyExpired = berror.DefineCode(4002014, moduleName, "KeyExpired", `
|
||||||
|
Cache key is expired.
|
||||||
|
You should notice that, a key is expired and then it may be deleted by GC goroutine.
|
||||||
|
So when you query a key which may be expired, you may got this code, or KeyNotExist.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var KeyNotExist = berror.DefineCode(4002015, moduleName, "KeyNotExist", `
|
||||||
|
Key not found.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var MultiGetFailed = berror.DefineCode(4002016, moduleName, "MultiGetFailed", `
|
||||||
|
Get multiple keys failed. Please check the detail msg to find out the root cause.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidMemoryCacheCfg = berror.DefineCode(4002017, moduleName, "InvalidMemoryCacheCfg", `
|
||||||
|
The config is invalid. Please check your input. It must be a json string.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidMemCacheCfg = berror.DefineCode(4002018, moduleName, "InvalidMemCacheCfg", `
|
||||||
|
The config is invalid. Please check your input, it must be json string and contains "conn" field.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidMemCacheValue = berror.DefineCode(4002019, moduleName, "InvalidMemCacheValue", `
|
||||||
|
The value must be string or byte[], please check your input.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidRedisCacheCfg = berror.DefineCode(4002020, moduleName, "InvalidRedisCacheCfg", `
|
||||||
|
The config must be json string, and has "conn" field.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidSsdbCacheCfg = berror.DefineCode(4002021, moduleName, "InvalidSsdbCacheCfg", `
|
||||||
|
The config must be json string, and has "conn" field. The value of "conn" field should be "host:port".
|
||||||
|
"port" must be a valid integer.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidSsdbCacheValue = berror.DefineCode(4002022, moduleName, "InvalidSsdbCacheValue", `
|
||||||
|
SSDB cache only accept string value. Please check your input.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var DeleteFileCacheItemFailed = berror.DefineCode(5002001, moduleName, "DeleteFileCacheItemFailed", `
|
||||||
|
Beego try to delete file cache item failed.
|
||||||
|
Please check whether Beego generated file correctly.
|
||||||
|
And then confirm whether this file is already deleted by other processes or other people.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var MemCacheCurdFailed = berror.DefineCode(5002002, moduleName, "MemCacheError", `
|
||||||
|
When you want to get, put, delete key-value from remote memcache servers, you may get error:
|
||||||
|
1. You pass invalid servers address, so Beego could not connect to remote server;
|
||||||
|
2. The servers address is correct, but there is some net issue. Typically there is some firewalls between application and memcache server;
|
||||||
|
3. Key is invalid. The key's length should be less than 250 and must not contains special characters;
|
||||||
|
4. The response from memcache server is invalid;
|
||||||
|
`)
|
||||||
|
|
||||||
|
var RedisCacheCurdFailed = berror.DefineCode(5002003, moduleName, "RedisCacheCurdFailed", `
|
||||||
|
When Beego uses client to send request to redis server, it failed.
|
||||||
|
1. The server addresses is invalid;
|
||||||
|
2. Network issue, firewall issue or network is unstable;
|
||||||
|
3. Client failed to manage connection. In extreme cases, Beego's redis client didn't maintain connections correctly, for example, Beego try to send request via closed connection;
|
||||||
|
4. The request are huge and redis server spent too much time to process it, and client is timeout;
|
||||||
|
|
||||||
|
In general, if you always got this error whatever you do, in most cases, it was caused by network issue.
|
||||||
|
You could check your network state, and confirm that firewall rules are correct.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var InvalidConnection = berror.DefineCode(5002004, moduleName, "InvalidConnection", `
|
||||||
|
The connection is invalid. Please check your connection info, network, firewall.
|
||||||
|
You could simply uses ping, telnet or write some simple tests to test network.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var DialFailed = berror.DefineCode(5002005, moduleName, "DialFailed", `
|
||||||
|
When Beego try to dial to remote servers, it failed. Please check your connection info and network state, server state.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var SsdbCacheCurdFailed = berror.DefineCode(5002006, moduleName, "SsdbCacheCurdFailed", `
|
||||||
|
When you try to use SSDB cache, it failed. There are many cases:
|
||||||
|
1. servers unavailable;
|
||||||
|
2. network issue, including network unstable, firewall;
|
||||||
|
3. connection issue;
|
||||||
|
4. request are huge and servers spent too much time to process it, got timeout;
|
||||||
|
`)
|
||||||
|
|
||||||
|
var SsdbBadResponse = berror.DefineCode(5002007, moduleName, "SsdbBadResponse", `
|
||||||
|
The reponse from SSDB server is invalid.
|
||||||
|
Usually it indicates something wrong on server side.
|
||||||
|
`)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrKeyExpired = berror.Error(KeyExpired, "the key is expired")
|
||||||
|
ErrKeyNotExist = berror.Error(KeyNotExist, "the key isn't exist")
|
||||||
|
)
|
||||||
198
client/cache/file.go
vendored
198
client/cache/file.go
vendored
@ -30,7 +30,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/beego/beego/v2/core/berror"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FileCacheItem is basic unit of file cache adapter which
|
// FileCacheItem is basic unit of file cache adapter which
|
||||||
@ -67,44 +67,65 @@ func NewFileCache() Cache {
|
|||||||
// StartAndGC starts gc for file cache.
|
// StartAndGC starts gc for file cache.
|
||||||
// config must be in the format {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}
|
// config must be in the format {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}
|
||||||
func (fc *FileCache) StartAndGC(config string) error {
|
func (fc *FileCache) StartAndGC(config string) error {
|
||||||
|
|
||||||
cfg := make(map[string]string)
|
cfg := make(map[string]string)
|
||||||
err := json.Unmarshal([]byte(config), &cfg)
|
err := json.Unmarshal([]byte(config), &cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, ok := cfg["CachePath"]; !ok {
|
|
||||||
cfg["CachePath"] = FileCachePath
|
|
||||||
}
|
|
||||||
if _, ok := cfg["FileSuffix"]; !ok {
|
|
||||||
cfg["FileSuffix"] = FileCacheFileSuffix
|
|
||||||
}
|
|
||||||
if _, ok := cfg["DirectoryLevel"]; !ok {
|
|
||||||
cfg["DirectoryLevel"] = strconv.Itoa(FileCacheDirectoryLevel)
|
|
||||||
}
|
|
||||||
if _, ok := cfg["EmbedExpiry"]; !ok {
|
|
||||||
cfg["EmbedExpiry"] = strconv.FormatInt(int64(FileCacheEmbedExpiry.Seconds()), 10)
|
|
||||||
}
|
|
||||||
fc.CachePath = cfg["CachePath"]
|
|
||||||
fc.FileSuffix = cfg["FileSuffix"]
|
|
||||||
fc.DirectoryLevel, _ = strconv.Atoi(cfg["DirectoryLevel"])
|
|
||||||
fc.EmbedExpiry, _ = strconv.Atoi(cfg["EmbedExpiry"])
|
|
||||||
|
|
||||||
fc.Init()
|
const cpKey = "CachePath"
|
||||||
return nil
|
const fsKey = "FileSuffix"
|
||||||
|
const dlKey = "DirectoryLevel"
|
||||||
|
const eeKey = "EmbedExpiry"
|
||||||
|
|
||||||
|
if _, ok := cfg[cpKey]; !ok {
|
||||||
|
cfg[cpKey] = FileCachePath
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := cfg[fsKey]; !ok {
|
||||||
|
cfg[fsKey] = FileCacheFileSuffix
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := cfg[dlKey]; !ok {
|
||||||
|
cfg[dlKey] = strconv.Itoa(FileCacheDirectoryLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := cfg[eeKey]; !ok {
|
||||||
|
cfg[eeKey] = strconv.FormatInt(int64(FileCacheEmbedExpiry.Seconds()), 10)
|
||||||
|
}
|
||||||
|
fc.CachePath = cfg[cpKey]
|
||||||
|
fc.FileSuffix = cfg[fsKey]
|
||||||
|
fc.DirectoryLevel, err = strconv.Atoi(cfg[dlKey])
|
||||||
|
if err != nil {
|
||||||
|
return berror.Wrapf(err, InvalidFileCacheDirectoryLevelCfg,
|
||||||
|
"invalid directory level config, please check your input, it must be integer: %s", cfg[dlKey])
|
||||||
|
}
|
||||||
|
fc.EmbedExpiry, err = strconv.Atoi(cfg[eeKey])
|
||||||
|
if err != nil {
|
||||||
|
return berror.Wrapf(err, InvalidFileCacheEmbedExpiryCfg,
|
||||||
|
"invalid embed expiry config, please check your input, it must be integer: %s", cfg[eeKey])
|
||||||
|
}
|
||||||
|
return fc.Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init makes new a dir for file cache if it does not already exist
|
// Init makes new a dir for file cache if it does not already exist
|
||||||
func (fc *FileCache) Init() {
|
func (fc *FileCache) Init() error {
|
||||||
if ok, _ := exists(fc.CachePath); !ok { // todo : error handle
|
ok, err := exists(fc.CachePath)
|
||||||
_ = os.MkdirAll(fc.CachePath, os.ModePerm) // todo : error handle
|
if err != nil || ok {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
err = os.MkdirAll(fc.CachePath, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return berror.Wrapf(err, CreateFileCacheDirFailed,
|
||||||
|
"could not create directory, please check the config [%s] and file mode.", fc.CachePath)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCachedFilename returns an md5 encoded file name.
|
// getCachedFilename returns an md5 encoded file name.
|
||||||
func (fc *FileCache) getCacheFileName(key string) string {
|
func (fc *FileCache) getCacheFileName(key string) (string, error) {
|
||||||
m := md5.New()
|
m := md5.New()
|
||||||
io.WriteString(m, key)
|
_, _ = io.WriteString(m, key)
|
||||||
keyMd5 := hex.EncodeToString(m.Sum(nil))
|
keyMd5 := hex.EncodeToString(m.Sum(nil))
|
||||||
cachePath := fc.CachePath
|
cachePath := fc.CachePath
|
||||||
switch fc.DirectoryLevel {
|
switch fc.DirectoryLevel {
|
||||||
@ -113,18 +134,29 @@ func (fc *FileCache) getCacheFileName(key string) string {
|
|||||||
case 1:
|
case 1:
|
||||||
cachePath = filepath.Join(cachePath, keyMd5[0:2])
|
cachePath = filepath.Join(cachePath, keyMd5[0:2])
|
||||||
}
|
}
|
||||||
|
ok, err := exists(cachePath)
|
||||||
if ok, _ := exists(cachePath); !ok { // todo : error handle
|
if err != nil {
|
||||||
_ = os.MkdirAll(cachePath, os.ModePerm) // todo : error handle
|
return "", err
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
err = os.MkdirAll(cachePath, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return "", berror.Wrapf(err, CreateFileCacheDirFailed,
|
||||||
|
"could not create the directory: %s", cachePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, fc.FileSuffix))
|
return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, fc.FileSuffix)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get value from file cache.
|
// Get value from file cache.
|
||||||
// if nonexistent or expired return an empty string.
|
// if nonexistent or expired return an empty string.
|
||||||
func (fc *FileCache) Get(ctx context.Context, key string) (interface{}, error) {
|
func (fc *FileCache) Get(ctx context.Context, key string) (interface{}, error) {
|
||||||
fileData, err := FileGetContents(fc.getCacheFileName(key))
|
fn, err := fc.getCacheFileName(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fileData, err := FileGetContents(fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -136,7 +168,7 @@ func (fc *FileCache) Get(ctx context.Context, key string) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if to.Expired.Before(time.Now()) {
|
if to.Expired.Before(time.Now()) {
|
||||||
return nil, errors.New("The key is expired")
|
return nil, ErrKeyExpired
|
||||||
}
|
}
|
||||||
return to.Data, nil
|
return to.Data, nil
|
||||||
}
|
}
|
||||||
@ -159,7 +191,7 @@ func (fc *FileCache) GetMulti(ctx context.Context, keys []string) ([]interface{}
|
|||||||
if len(keysErr) == 0 {
|
if len(keysErr) == 0 {
|
||||||
return rc, nil
|
return rc, nil
|
||||||
}
|
}
|
||||||
return rc, errors.New(strings.Join(keysErr, "; "))
|
return rc, berror.Error(MultiGetFailed, strings.Join(keysErr, "; "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put value into file cache.
|
// Put value into file cache.
|
||||||
@ -179,14 +211,26 @@ func (fc *FileCache) Put(ctx context.Context, key string, val interface{}, timeo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return FilePutContents(fc.getCacheFileName(key), data)
|
|
||||||
|
fn, err := fc.getCacheFileName(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return FilePutContents(fn, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete file cache value.
|
// Delete file cache value.
|
||||||
func (fc *FileCache) Delete(ctx context.Context, key string) error {
|
func (fc *FileCache) Delete(ctx context.Context, key string) error {
|
||||||
filename := fc.getCacheFileName(key)
|
filename, err := fc.getCacheFileName(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if ok, _ := exists(filename); ok {
|
if ok, _ := exists(filename); ok {
|
||||||
return os.Remove(filename)
|
err = os.Remove(filename)
|
||||||
|
if err != nil {
|
||||||
|
return berror.Wrapf(err, DeleteFileCacheItemFailed,
|
||||||
|
"can not delete this file cache key-value, key is %s and file name is %s", key, filename)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -199,25 +243,12 @@ func (fc *FileCache) Incr(ctx context.Context, key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var res interface{}
|
val, err := incr(data)
|
||||||
switch val := data.(type) {
|
if err != nil {
|
||||||
case int:
|
return err
|
||||||
res = val + 1
|
|
||||||
case int32:
|
|
||||||
res = val + 1
|
|
||||||
case int64:
|
|
||||||
res = val + 1
|
|
||||||
case uint:
|
|
||||||
res = val + 1
|
|
||||||
case uint32:
|
|
||||||
res = val + 1
|
|
||||||
case uint64:
|
|
||||||
res = val + 1
|
|
||||||
default:
|
|
||||||
return errors.Errorf("data is not (u)int (u)int32 (u)int64")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fc.Put(context.Background(), key, res, time.Duration(fc.EmbedExpiry))
|
return fc.Put(context.Background(), key, val, time.Duration(fc.EmbedExpiry))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decr decreases cached int value.
|
// Decr decreases cached int value.
|
||||||
@ -227,43 +258,21 @@ func (fc *FileCache) Decr(ctx context.Context, key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var res interface{}
|
val, err := decr(data)
|
||||||
switch val := data.(type) {
|
if err != nil {
|
||||||
case int:
|
return err
|
||||||
res = val - 1
|
|
||||||
case int32:
|
|
||||||
res = val - 1
|
|
||||||
case int64:
|
|
||||||
res = val - 1
|
|
||||||
case uint:
|
|
||||||
if val > 0 {
|
|
||||||
res = val - 1
|
|
||||||
} else {
|
|
||||||
return errors.New("data val is less than 0")
|
|
||||||
}
|
|
||||||
case uint32:
|
|
||||||
if val > 0 {
|
|
||||||
res = val - 1
|
|
||||||
} else {
|
|
||||||
return errors.New("data val is less than 0")
|
|
||||||
}
|
|
||||||
case uint64:
|
|
||||||
if val > 0 {
|
|
||||||
res = val - 1
|
|
||||||
} else {
|
|
||||||
return errors.New("data val is less than 0")
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.Errorf("data is not (u)int (u)int32 (u)int64")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fc.Put(context.Background(), key, res, time.Duration(fc.EmbedExpiry))
|
return fc.Put(context.Background(), key, val, time.Duration(fc.EmbedExpiry))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsExist checks if value exists.
|
// IsExist checks if value exists.
|
||||||
func (fc *FileCache) IsExist(ctx context.Context, key string) (bool, error) {
|
func (fc *FileCache) IsExist(ctx context.Context, key string) (bool, error) {
|
||||||
ret, _ := exists(fc.getCacheFileName(key))
|
fn, err := fc.getCacheFileName(key)
|
||||||
return ret, nil
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return exists(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearAll cleans cached files (not implemented)
|
// ClearAll cleans cached files (not implemented)
|
||||||
@ -280,13 +289,19 @@ func exists(path string) (bool, error) {
|
|||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
return false, err
|
return false, berror.Wrapf(err, InvalidFileCachePath, "file cache path is invalid: %s", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileGetContents Reads bytes from a file.
|
// FileGetContents Reads bytes from a file.
|
||||||
// if non-existent, create this file.
|
// if non-existent, create this file.
|
||||||
func FileGetContents(filename string) (data []byte, e error) {
|
func FileGetContents(filename string) ([]byte, error) {
|
||||||
return ioutil.ReadFile(filename)
|
data, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, berror.Wrapf(err, ReadFileCacheContentFailed,
|
||||||
|
"could not read the data from the file: %s, "+
|
||||||
|
"please confirm that file exist and Beego has the permission to read the content.", filename)
|
||||||
|
}
|
||||||
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilePutContents puts bytes into a file.
|
// FilePutContents puts bytes into a file.
|
||||||
@ -301,16 +316,21 @@ func GobEncode(data interface{}) ([]byte, error) {
|
|||||||
enc := gob.NewEncoder(buf)
|
enc := gob.NewEncoder(buf)
|
||||||
err := enc.Encode(data)
|
err := enc.Encode(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, berror.Wrap(err, GobEncodeDataFailed, "could not encode this data")
|
||||||
}
|
}
|
||||||
return buf.Bytes(), err
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GobDecode Gob decodes a file cache item.
|
// GobDecode Gob decodes a file cache item.
|
||||||
func GobDecode(data []byte, to *FileCacheItem) error {
|
func GobDecode(data []byte, to *FileCacheItem) error {
|
||||||
buf := bytes.NewBuffer(data)
|
buf := bytes.NewBuffer(data)
|
||||||
dec := gob.NewDecoder(buf)
|
dec := gob.NewDecoder(buf)
|
||||||
return dec.Decode(&to)
|
err := dec.Decode(&to)
|
||||||
|
if err != nil {
|
||||||
|
return berror.Wrap(err, InvalidGobEncodedData,
|
||||||
|
"could not decode this data to FileCacheItem. Make sure that the data is encoded by GOB.")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
108
client/cache/file_test.go
vendored
Normal file
108
client/cache/file_test.go
vendored
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
// Copyright 2021 beego
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFileCacheStartAndGC(t *testing.T) {
|
||||||
|
fc := NewFileCache().(*FileCache)
|
||||||
|
err := fc.StartAndGC(`{`)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
err = fc.StartAndGC(`{}`)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, fc.CachePath, FileCachePath)
|
||||||
|
assert.Equal(t, fc.DirectoryLevel, FileCacheDirectoryLevel)
|
||||||
|
assert.Equal(t, fc.EmbedExpiry, int(FileCacheEmbedExpiry))
|
||||||
|
assert.Equal(t, fc.FileSuffix, FileCacheFileSuffix)
|
||||||
|
|
||||||
|
err = fc.StartAndGC(`{"CachePath":"/cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}`)
|
||||||
|
// could not create dir
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
str := getTestCacheFilePath()
|
||||||
|
err = fc.StartAndGC(fmt.Sprintf(`{"CachePath":"%s","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}`, str))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, fc.CachePath, str)
|
||||||
|
assert.Equal(t, fc.DirectoryLevel, 2)
|
||||||
|
assert.Equal(t, fc.EmbedExpiry, 0)
|
||||||
|
assert.Equal(t, fc.FileSuffix, ".bin")
|
||||||
|
|
||||||
|
err = fc.StartAndGC(fmt.Sprintf(`{"CachePath":"%s","FileSuffix":".bin","DirectoryLevel":"aaa","EmbedExpiry":"0"}`, str))
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
err = fc.StartAndGC(fmt.Sprintf(`{"CachePath":"%s","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"aaa"}`, str))
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileCacheInit(t *testing.T) {
|
||||||
|
fc := NewFileCache().(*FileCache)
|
||||||
|
fc.CachePath = "////aaa"
|
||||||
|
err := fc.Init()
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
fc.CachePath = getTestCacheFilePath()
|
||||||
|
err = fc.Init()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileGetContents(t *testing.T) {
|
||||||
|
_, err := FileGetContents("/bin/aaa")
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
fn := filepath.Join(os.TempDir(), "fileCache.txt")
|
||||||
|
f, err := os.Create(fn)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
_, err = f.WriteString("text")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
data, err := FileGetContents(fn)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "text", string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGobEncodeDecode(t *testing.T) {
|
||||||
|
_, err := GobEncode(func() {
|
||||||
|
fmt.Print("test func")
|
||||||
|
})
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
data, err := GobEncode(&FileCacheItem{
|
||||||
|
Data: "hello",
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
err = GobDecode([]byte("wrong data"), &FileCacheItem{})
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
dci := &FileCacheItem{}
|
||||||
|
err = GobDecode(data, dci)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "hello", dci.Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileCacheDelete(t *testing.T) {
|
||||||
|
fc := NewFileCache()
|
||||||
|
err := fc.StartAndGC(`{}`)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
err = fc.Delete(context.Background(), "my-key")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestCacheFilePath() string {
|
||||||
|
return filepath.Join(os.TempDir(), "test", "file.txt")
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user