Skip to content

Commit

Permalink
Add the duration declarations in the new style when UTC is enabled as…
Browse files Browse the repository at this point in the history
… the partial declaration causes improper dynamic dispatch (#565)
  • Loading branch information
TristonianJones committed Jul 13, 2022
1 parent 79192b9 commit f3df06c
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 19 deletions.
28 changes: 22 additions & 6 deletions cel/cel_test.go
Expand Up @@ -202,8 +202,10 @@ func TestCustomEnvError(t *testing.T) {
}

func TestCustomEnv(t *testing.T) {
e, _ := NewCustomEnv(Variable("a.b.c", BoolType))

e, err := NewCustomEnv(Variable("a.b.c", BoolType))
if err != nil {
t.Fatalf("NewCustomEnv(a.b.c:bool) failed: %v", err)
}
t.Run("err", func(t *testing.T) {
_, iss := e.Compile("a.b.c == true")
if iss.Err() == nil {
Expand Down Expand Up @@ -1704,28 +1706,42 @@ func TestDefaultUTCTimeZone(t *testing.T) {
}

func TestDefaultUTCTimeZoneExtension(t *testing.T) {
env, err := NewEnv(Variable("x", TimestampType), DefaultUTCTimeZone(true))
env, err := NewEnv(
Variable("x", TimestampType),
Variable("y", DurationType),
DefaultUTCTimeZone(true),
)
if err != nil {
t.Fatalf("NewEnv() failed: %v", err)
}
env, err = env.Extend()
if err != nil {
t.Fatalf("env.Extend() failed: %v", err)
}
ast, iss := env.Compile(`x.getFullYear() == 1970`)
ast, iss := env.Compile(`
x.getFullYear() == 1970
&& y.getHours() == 2
&& y.getMinutes() == 120
&& y.getSeconds() == 7235
&& y.getMilliseconds() == 7235000`)
if iss.Err() != nil {
t.Fatalf("env.Compile() failed: %v", iss.Err())
}
prg, err := env.Program(ast)
if err != nil {
t.Fatalf("env.Program() failed: %v", err)
}
out, _, err := prg.Eval(map[string]interface{}{"x": time.Unix(7506, 1000000).Local()})
out, _, err := prg.Eval(
map[string]interface{}{
"x": time.Unix(7506, 1000000).Local(),
"y": time.Duration(7235) * time.Second,
},
)
if err != nil {
t.Fatalf("prg.Eval() failed: %v", err)
}
if out != types.True {
t.Errorf("Eval() got %v, wanted true", out)
t.Errorf("Eval() got %v, wanted true", out.Value())
}
}

Expand Down
12 changes: 5 additions & 7 deletions cel/decls.go
Expand Up @@ -662,20 +662,18 @@ func (f *functionDecl) merge(other *functionDecl) (*functionDecl, error) {
return merged, nil
}

// addOverload ensures that the new overload does not collide with an existing overload signature,
// nor does it redefine an existing overload binding.
// addOverload ensures that the new overload does not collide with an existing overload signature;
// however, if the function signatures are identical, the implementation may be rewritten as its
// difficult to compare functions by object identity.
func (f *functionDecl) addOverload(overload *overloadDecl) error {
for id, o := range f.overloads {
if id != overload.id && o.signatureOverlaps(overload) {
return fmt.Errorf("overload signature collision in function %s: %s collides with %s", f.name, o.id, overload.id)
}
if id == overload.id {
if o.signatureEquals(overload) && o.nonStrict == overload.nonStrict {
if !o.hasBinding() && overload.hasBinding() {
f.overloads[id] = overload
} else if o.hasBinding() && overload.hasBinding() && o != overload {
return fmt.Errorf("overload binding collision in function %s: %s has multiple bindings", f.name, o.id)
}
// Allow redefinition of an overload implementation so long as the signatures match.
f.overloads[id] = overload
} else {
return fmt.Errorf("overload redefinition in function. %s: %s has multiple definitions", f.name, o.id)
}
Expand Down
4 changes: 0 additions & 4 deletions cel/decls_test.go
Expand Up @@ -147,10 +147,6 @@ func TestFunctionMerge(t *testing.T) {
t.Errorf("prg.Eval() got %v, wanted %v", out, want)
}

_, err = NewCustomEnv(vectorExt, vectorExt)
if err == nil || !strings.Contains(err.Error(), "overload binding collision") {
t.Errorf("NewCustomEnv(vectorExt, vectorExt) did not produce expected error: %v", err)
}
_, err = NewCustomEnv(size, size)
if err == nil || !strings.Contains(err.Error(), "already has a binding") {
t.Errorf("NewCustomEnv(size, size) did not produce the expected error: %v", err)
Expand Down
28 changes: 26 additions & 2 deletions cel/library.go
Expand Up @@ -85,7 +85,7 @@ func (stdLibrary) ProgramOptions() []ProgramOption {
type timeUTCLibrary struct{}

func (timeUTCLibrary) CompileOptions() []EnvOption {
return timestampOverloadDeclarations
return timeOverloadDeclarations
}

func (timeUTCLibrary) ProgramOptions() []ProgramOption {
Expand All @@ -97,7 +97,31 @@ func (timeUTCLibrary) ProgramOptions() []ProgramOption {
var (
utcTZ = types.String("UTC")

timestampOverloadDeclarations = []EnvOption{
timeOverloadDeclarations = []EnvOption{
Function(overloads.TimeGetHours,
MemberOverload(overloads.DurationToHours, []*Type{DurationType}, IntType,
UnaryBinding(func(dur ref.Val) ref.Val {
d := dur.(types.Duration)
return types.Int(d.Hours())
}))),
Function(overloads.TimeGetMinutes,
MemberOverload(overloads.DurationToMinutes, []*Type{DurationType}, IntType,
UnaryBinding(func(dur ref.Val) ref.Val {
d := dur.(types.Duration)
return types.Int(d.Minutes())
}))),
Function(overloads.TimeGetSeconds,
MemberOverload(overloads.DurationToSeconds, []*Type{DurationType}, IntType,
UnaryBinding(func(dur ref.Val) ref.Val {
d := dur.(types.Duration)
return types.Int(d.Seconds())
}))),
Function(overloads.TimeGetMilliseconds,
MemberOverload(overloads.DurationToMilliseconds, []*Type{DurationType}, IntType,
UnaryBinding(func(dur ref.Val) ref.Val {
d := dur.(types.Duration)
return types.Int(d.Milliseconds())
}))),
Function(overloads.TimeGetFullYear,
MemberOverload(overloads.TimestampToYear, []*Type{TimestampType}, IntType,
UnaryBinding(func(ts ref.Val) ref.Val {
Expand Down

0 comments on commit f3df06c

Please sign in to comment.