Skip to content

Commit

Permalink
feat: add github action and semantic-release (#6)
Browse files Browse the repository at this point in the history
* ci: add build workflow and semantic-release

* fix: add go.mod

* fix: linting errors

* ci: fix repository name
  • Loading branch information
abichinger authored Nov 22, 2023
1 parent b858943 commit 48fcb5a
Show file tree
Hide file tree
Showing 16 changed files with 226 additions and 194 deletions.
47 changes: 47 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Build

on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
go: ['1.18', '1.19', '1.20']
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go }}

- name: Run go test
run: go test -race -v -bench=.

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20'

- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.51

semantic-release:
needs: [test, lint]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Run semantic-release
if: github.repository == 'casbin/govaluate' && github.event_name == 'push'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npx semantic-release@22.0.8
16 changes: 16 additions & 0 deletions .releaserc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"debug": true,
"branches": [
"+([0-9])?(.{+([0-9]),x}).x",
"master",
{
"name": "beta",
"prerelease": true
}
],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/github"
]
}
10 changes: 0 additions & 10 deletions .travis.yml

This file was deleted.

20 changes: 10 additions & 10 deletions EvaluableExpression_sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import (
)

/*
Returns a string representing this expression as if it were written in SQL.
This function assumes that all parameters exist within the same table, and that the table essentially represents
a serialized object of some sort (e.g., hibernate).
If your data model is more normalized, you may need to consider iterating through each actual token given by `Tokens()`
to create your query.
Returns a string representing this expression as if it were written in SQL.
This function assumes that all parameters exist within the same table, and that the table essentially represents
a serialized object of some sort (e.g., hibernate).
If your data model is more normalized, you may need to consider iterating through each actual token given by `Tokens()`
to create your query.
Boolean values are considered to be "1" for true, "0" for false.
Boolean values are considered to be "1" for true, "0" for false.
Times are formatted according to this.QueryDateFormat.
Times are formatted according to this.QueryDateFormat.
*/
func (this EvaluableExpression) ToSQLQuery() (string, error) {

Expand Down Expand Up @@ -91,7 +91,7 @@ func (this EvaluableExpression) findNextSQLString(stream *tokenStream, transacti
case NREQ:
ret = "NOT RLIKE"
default:
ret = fmt.Sprintf("%s", token.Value.(string))
ret = fmt.Sprintf("%s", token.Value)
}

case TERNARY:
Expand All @@ -116,7 +116,7 @@ func (this EvaluableExpression) findNextSQLString(stream *tokenStream, transacti
switch prefixSymbols[token.Value.(string)] {

case INVERT:
ret = fmt.Sprintf("NOT")
ret = "NOT"
default:

right, err := this.findNextSQLString(stream, transactions)
Expand Down Expand Up @@ -149,7 +149,7 @@ func (this EvaluableExpression) findNextSQLString(stream *tokenStream, transacti

ret = fmt.Sprintf("MOD(%s, %s)", left, right)
default:
ret = fmt.Sprintf("%s", token.Value.(string))
ret = fmt.Sprintf("%s", token.Value)
}
case CLAUSE:
ret = "("
Expand Down
87 changes: 39 additions & 48 deletions benchmarks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,81 +5,78 @@ import (
)

/*
Serves as a "water test" to give an idea of the general overhead of parsing
Serves as a "water test" to give an idea of the general overhead of parsing
*/
func BenchmarkSingleParse(bench *testing.B) {

for i := 0; i < bench.N; i++ {
NewEvaluableExpression("1")
_, _ = NewEvaluableExpression("1")
}
}

/*
The most common use case, a single variable, modified slightly, compared to a constant.
This is the "expected" use case of govaluate.
The most common use case, a single variable, modified slightly, compared to a constant.
This is the "expected" use case of govaluate.
*/
func BenchmarkSimpleParse(bench *testing.B) {

for i := 0; i < bench.N; i++ {
NewEvaluableExpression("(requests_made * requests_succeeded / 100) >= 90")
_, _ = NewEvaluableExpression("(requests_made * requests_succeeded / 100) >= 90")
}
}

/*
Benchmarks all syntax possibilities in one expression.
Benchmarks all syntax possibilities in one expression.
*/
func BenchmarkFullParse(bench *testing.B) {

var expression string

// represents all the major syntax possibilities.
expression = "2 > 1 &&" +
expression := "2 > 1 &&" +
"'something' != 'nothing' || " +
"'2014-01-20' < 'Wed Jul 8 23:07:35 MDT 2015' && " +
"[escapedVariable name with spaces] <= unescaped\\-variableName &&" +
"modifierTest + 1000 / 2 > (80 * 100 % 2)"

for i := 0; i < bench.N; i++ {
NewEvaluableExpression(expression)
_, _ = NewEvaluableExpression(expression)
}
}

/*
Benchmarks the bare-minimum evaluation time
Benchmarks the bare-minimum evaluation time
*/
func BenchmarkEvaluationSingle(bench *testing.B) {

expression, _ := NewEvaluableExpression("1")

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(nil)
_, _ = expression.Evaluate(nil)
}
}

/*
Benchmarks evaluation times of literals (no variables, no modifiers)
Benchmarks evaluation times of literals (no variables, no modifiers)
*/
func BenchmarkEvaluationNumericLiteral(bench *testing.B) {

expression, _ := NewEvaluableExpression("(2) > (1)")

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(nil)
_, _ = expression.Evaluate(nil)
}
}

/*
Benchmarks evaluation times of literals with modifiers
Benchmarks evaluation times of literals with modifiers
*/
func BenchmarkEvaluationLiteralModifiers(bench *testing.B) {

expression, _ := NewEvaluableExpression("(2) + (2) == (4)")

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(nil)
_, _ = expression.Evaluate(nil)
}
}

Expand All @@ -92,12 +89,12 @@ func BenchmarkEvaluationParameter(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(parameters)
_, _ = expression.Evaluate(parameters)
}
}

/*
Benchmarks evaluation times of parameters
Benchmarks evaluation times of parameters
*/
func BenchmarkEvaluationParameters(bench *testing.B) {

Expand All @@ -109,12 +106,12 @@ func BenchmarkEvaluationParameters(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(parameters)
_, _ = expression.Evaluate(parameters)
}
}

/*
Benchmarks evaluation times of parameters + literals with modifiers
Benchmarks evaluation times of parameters + literals with modifiers
*/
func BenchmarkEvaluationParametersModifiers(bench *testing.B) {

Expand All @@ -126,21 +123,18 @@ func BenchmarkEvaluationParametersModifiers(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(parameters)
_, _ = expression.Evaluate(parameters)
}
}

/*
Benchmarks the ludicrously-unlikely worst-case expression,
one which uses all features.
This is largely a canary benchmark to make sure that any syntax additions don't
unnecessarily bloat the evaluation time.
Benchmarks the ludicrously-unlikely worst-case expression,
one which uses all features.
This is largely a canary benchmark to make sure that any syntax additions don't
unnecessarily bloat the evaluation time.
*/
func BenchmarkComplexExpression(bench *testing.B) {

var expressionString string

expressionString = "2 > 1 &&" +
expressionString := "2 > 1 &&" +
"'something' != 'nothing' || " +
"'2014-01-20' < 'Wed Jul 8 23:07:35 MDT 2015' && " +
"[escapedVariable name with spaces] <= unescaped\\-variableName &&" +
Expand All @@ -155,21 +149,18 @@ func BenchmarkComplexExpression(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(parameters)
_, _ = expression.Evaluate(parameters)
}
}

/*
Benchmarks uncompiled parameter regex operators, which are the most expensive of the lot.
Note that regex compilation times are unpredictable and wily things. The regex engine has a lot of edge cases
and possible performance pitfalls. This test doesn't aim to be comprehensive against all possible regex scenarios,
it is primarily concerned with tracking how much longer it takes to compile a regex at evaluation-time than during parse-time.
Benchmarks uncompiled parameter regex operators, which are the most expensive of the lot.
Note that regex compilation times are unpredictable and wily things. The regex engine has a lot of edge cases
and possible performance pitfalls. This test doesn't aim to be comprehensive against all possible regex scenarios,
it is primarily concerned with tracking how much longer it takes to compile a regex at evaluation-time than during parse-time.
*/
func BenchmarkRegexExpression(bench *testing.B) {

var expressionString string

expressionString = "(foo !~ bar) && (foobar =~ oba)"
expressionString := "(foo !~ bar) && (foobar =~ oba)"

expression, _ := NewEvaluableExpression(expressionString)
parameters := map[string]interface{}{
Expand All @@ -181,14 +172,14 @@ func BenchmarkRegexExpression(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(parameters)
_, _ = expression.Evaluate(parameters)
}
}

/*
Benchmarks pre-compilable regex patterns. Meant to serve as a sanity check that constant strings used as regex patterns
are actually being precompiled.
Also demonstrates that (generally) compiling a regex at evaluation-time takes an order of magnitude more time than pre-compiling.
Benchmarks pre-compilable regex patterns. Meant to serve as a sanity check that constant strings used as regex patterns
are actually being precompiled.
Also demonstrates that (generally) compiling a regex at evaluation-time takes an order of magnitude more time than pre-compiling.
*/
func BenchmarkConstantRegexExpression(bench *testing.B) {

Expand All @@ -202,7 +193,7 @@ func BenchmarkConstantRegexExpression(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(parameters)
_, _ = expression.Evaluate(parameters)
}
}

Expand All @@ -213,7 +204,7 @@ func BenchmarkAccessors(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(fooFailureParameters)
_, _ = expression.Evaluate(fooFailureParameters)
}
}

Expand All @@ -224,7 +215,7 @@ func BenchmarkAccessorMethod(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(fooFailureParameters)
_, _ = expression.Evaluate(fooFailureParameters)
}
}

Expand All @@ -235,7 +226,7 @@ func BenchmarkAccessorMethodParams(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(fooFailureParameters)
_, _ = expression.Evaluate(fooFailureParameters)
}
}

Expand All @@ -246,6 +237,6 @@ func BenchmarkNestedAccessors(bench *testing.B) {

bench.ResetTimer()
for i := 0; i < bench.N; i++ {
expression.Evaluate(fooFailureParameters)
_, _ = expression.Evaluate(fooFailureParameters)
}
}
Loading

0 comments on commit 48fcb5a

Please sign in to comment.