jmespath / jmespath/go-jmespath
Comparison expressions don't evaluate operand type
- Dominant language
- Go
- Stars
- 621
- Forks
- 101
- PR merge metrics
- No merged PRs in 30d
Description
### Description
Comparison expressions do not evaluate as expected in cases where one operand is a literal value and the other is a pointer to a value. This results in expressions such as `AutoScalingGroups[].[length(Instances[?LifecycleState=='InService']` used in the AWS SDK for Go's Autoscaling waiter `WaitUntilGroupInService` not evaluating correctly since `LifecycleState` is a pointer to a string that is being evaluated against the literal string `InService`.
### Steps to reproduce
Save this code as `main_test.go` and run `go test -v`:
```go
package main
import (
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/aws/aws-sdk-go/service/autoscaling"
)
func TestWaitUntilGroupInService(t *testing.T) {
mockResponse := &autoscaling.DescribeAutoScalingGroupsOutput{
AutoScalingGroups: []*autoscaling.Group{
&autoscaling.Group{
Instances: []*autoscaling.Instance{
&autoscaling.Instance{
LifecycleState: aws.String("InService"),
},
&autoscaling.Instance{
LifecycleState: aws.String("InService"),
},
},
MaxSize: aws.Int64(4),
MinSize: aws.Int64(2),
DesiredCapacity: aws.Int64(2),
},
&autoscaling.Group{
Instances: []*autoscaling.Instance{
&autoscaling.Instance{
LifecycleState: aws.String("InService"),
},
&autoscaling.Instance{
LifecycleState: aws.String("Pending"),
},
},
MaxSize: aws.Int64(4),
MinSize: aws.Int64(2),
DesiredCapacity: aws.Int64(2),
},
},
}
var testCases = []struct {
expect []interface{}
data interface{}
path string
}{
{[]interface{}{true}, mockResponse, "contains(AutoScalingGroups[].[length(Instances[?LifecycleState=='InService']) >= MinSize][], `false`)"},
{[]interface{}{true, false}, mockResponse, "AutoScalingGroups[].[length(Instances[?LifecycleState=='InService']) >= MinSize][]"},
{[]interface{}{2, 1}, mockResponse, "AutoScalingGroups[].[length(Instances[?LifecycleState=='InService'])][]"},
}
for i, c := range testCases {
v, err := awsutil.ValuesAtPath(c.data, c.path)
if err != nil {
t.Errorf("case %v, expected no error, %v", i, c.path)
}
if e, a := c.expect, v; !awsutil.DeepEqual(e, a) {
t.Errorf("case %v, %v, expected: %#v, but got: %#v", i, c.path, e, a)
}
}
}
```
```
$ go get -u github.com/aws/aws-sdk-go
$ go test -v
=== RUN TestWaitUntilGroupInService
--- FAIL: TestWaitUntilGroupInService (0.00s)
main_test.go:59: case 0, contains(AutoScalingGroups[].[length(Instances[?LifecycleState=='InService']) >= MinSize][], `false`), expected: []interface {}{true}, but got: []interface {}{false}
main_test.go:59: case 1, AutoScalingGroups[].[length(Instances[?LifecycleState=='InService']) >= MinSize][], expected: []interface {}{true, false}, but got: []interface {}{}
main_test.go:59: case 2, AutoScalingGroups[].[length(Instances[?LifecycleState=='InService'])][], expected: []interface {}{2, 1}, but got: []interface {}{0, 0}
FAIL
exit status 1
FAIL _/Users/masayuki-morita/work/tmp/20190228 0.019s
```
### Related items
Originating issue: https://github.com/aws/aws-sdk-go/issues/2478
Related to #15 and #20.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.